From a959eea3d57d2d76154d6eee1009a72c8d36562b Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Thu, 18 May 2023 08:48:48 -0700 Subject: [PATCH] wave: Remove wave module from codebase --- CHANGES.md | 1 + CMakeLists.txt | 2 +- RELEASE_NOTES.md | 7 + doc/models/Makefile | 1 - doc/models/source/index.rst | 1 - src/netanim/CMakeLists.txt | 1 - src/netanim/model/animation-interface.cc | 65 +- src/netanim/model/animation-interface.h | 17 +- src/wave/CMakeLists.txt | 44 - src/wave/doc/wave.rst | 935 ------ src/wave/examples/CMakeLists.txt | 42 - .../low99-ct-unterstrass-1day.filt.7.adj.mob | 1515 ---------- src/wave/examples/vanet-routing-compare.cc | 2500 ----------------- src/wave/examples/wave-simple-80211p.cc | 201 -- src/wave/examples/wave-simple-device.cc | 302 -- src/wave/helper/wave-bsm-helper.cc | 165 -- src/wave/helper/wave-bsm-helper.h | 148 - src/wave/helper/wave-bsm-stats.cc | 203 -- src/wave/helper/wave-bsm-stats.h | 239 -- src/wave/helper/wave-helper.cc | 476 ---- src/wave/helper/wave-helper.h | 237 -- src/wave/helper/wave-mac-helper.cc | 72 - src/wave/helper/wave-mac-helper.h | 135 - src/wave/helper/wifi-80211p-helper.cc | 101 - src/wave/helper/wifi-80211p-helper.h | 80 - src/wave/model/bsm-application.cc | 427 --- src/wave/model/bsm-application.h | 179 -- src/wave/model/channel-coordinator.cc | 403 --- src/wave/model/channel-coordinator.h | 256 -- src/wave/model/channel-manager.cc | 184 -- src/wave/model/channel-manager.h | 172 -- src/wave/model/channel-scheduler.cc | 174 -- src/wave/model/channel-scheduler.h | 246 -- src/wave/model/default-channel-scheduler.cc | 449 --- src/wave/model/default-channel-scheduler.h | 142 - src/wave/model/higher-tx-tag.cc | 119 - src/wave/model/higher-tx-tag.h | 89 - src/wave/model/ocb-wifi-mac.cc | 531 ---- src/wave/model/ocb-wifi-mac.h | 199 -- src/wave/model/vendor-specific-action.cc | 403 --- src/wave/model/vendor-specific-action.h | 260 -- src/wave/model/vsa-manager.cc | 293 -- src/wave/model/vsa-manager.h | 221 -- src/wave/model/wave-frame-exchange-manager.cc | 179 -- src/wave/model/wave-frame-exchange-manager.h | 88 - src/wave/model/wave-net-device.cc | 782 ------ src/wave/model/wave-net-device.h | 421 --- src/wave/test/examples-to-run.py | 23 - src/wave/test/mac-extension-test-suite.cc | 1558 ---------- src/wave/test/ocb-test-suite.cc | 507 ---- src/wifi/helper/wifi-mac-helper.cc | 6 +- 51 files changed, 14 insertions(+), 15787 deletions(-) delete mode 100644 src/wave/CMakeLists.txt delete mode 100644 src/wave/doc/wave.rst delete mode 100644 src/wave/examples/CMakeLists.txt delete mode 100644 src/wave/examples/low99-ct-unterstrass-1day.filt.7.adj.mob delete mode 100644 src/wave/examples/vanet-routing-compare.cc delete mode 100644 src/wave/examples/wave-simple-80211p.cc delete mode 100644 src/wave/examples/wave-simple-device.cc delete mode 100644 src/wave/helper/wave-bsm-helper.cc delete mode 100644 src/wave/helper/wave-bsm-helper.h delete mode 100644 src/wave/helper/wave-bsm-stats.cc delete mode 100644 src/wave/helper/wave-bsm-stats.h delete mode 100644 src/wave/helper/wave-helper.cc delete mode 100644 src/wave/helper/wave-helper.h delete mode 100644 src/wave/helper/wave-mac-helper.cc delete mode 100644 src/wave/helper/wave-mac-helper.h delete mode 100644 src/wave/helper/wifi-80211p-helper.cc delete mode 100644 src/wave/helper/wifi-80211p-helper.h delete mode 100644 src/wave/model/bsm-application.cc delete mode 100644 src/wave/model/bsm-application.h delete mode 100644 src/wave/model/channel-coordinator.cc delete mode 100644 src/wave/model/channel-coordinator.h delete mode 100644 src/wave/model/channel-manager.cc delete mode 100644 src/wave/model/channel-manager.h delete mode 100644 src/wave/model/channel-scheduler.cc delete mode 100644 src/wave/model/channel-scheduler.h delete mode 100644 src/wave/model/default-channel-scheduler.cc delete mode 100644 src/wave/model/default-channel-scheduler.h delete mode 100644 src/wave/model/higher-tx-tag.cc delete mode 100644 src/wave/model/higher-tx-tag.h delete mode 100644 src/wave/model/ocb-wifi-mac.cc delete mode 100644 src/wave/model/ocb-wifi-mac.h delete mode 100644 src/wave/model/vendor-specific-action.cc delete mode 100644 src/wave/model/vendor-specific-action.h delete mode 100644 src/wave/model/vsa-manager.cc delete mode 100644 src/wave/model/vsa-manager.h delete mode 100644 src/wave/model/wave-frame-exchange-manager.cc delete mode 100644 src/wave/model/wave-frame-exchange-manager.h delete mode 100644 src/wave/model/wave-net-device.cc delete mode 100644 src/wave/model/wave-net-device.h delete mode 100644 src/wave/test/examples-to-run.py delete mode 100644 src/wave/test/mac-extension-test-suite.cc delete mode 100644 src/wave/test/ocb-test-suite.cc diff --git a/CHANGES.md b/CHANGES.md index 290a34ca9..efd291a56 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -70,6 +70,7 @@ Changes from ns-3.38 to ns-3-dev * (lte) The `EpsBearer` is extended to include 3GPP Release 18 5QIs. * (lte) Add PDCP discard timer. If enabled using the attribute `EnablePdcpDiscarding`, in case that the buffering time (head-of-line delay) of a packet is greater than the PDB or a value set by the user, it will perform discarding at the moment of passing the PDCP SDU to RLC. * (lte) Centralize the constants `MIN_NO_CC` and `MAX_NO_CC`, declared in multiple header files, into the header `lte-common.h`. +* (wave) The Wave module was removed from the codebase due to lack of maintenance ### Changes to build system diff --git a/CMakeLists.txt b/CMakeLists.txt index 83d262056..6467138af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,7 +93,7 @@ set(NS3_ENABLED_MODULES "" CACHE STRING "List of modules to enable (e.g. core;network;internet)" ) set(NS3_DISABLED_MODULES "" - CACHE STRING "List of modules to disable (e.g. lte;wimax;wave)" + CACHE STRING "List of modules to disable (e.g. lte;wimax)" ) # Filter in the modules from which examples and tests will be built diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 831ad4a75..a7e40659e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -18,6 +18,7 @@ Release 3-dev ### Supported platforms + ### New user-visible features - (lr-wpan) !1399 - Add orphan scan support. @@ -26,6 +27,12 @@ Release 3-dev - (lr-wpan) !1410 - Add Mac16 and Mac64 functions - (applications) !1412 - Add Tx and TxWithAddresses trace sources in UdpClient +Note: This release has removed the "wave" module from the codebase due to lack of maintenance +and due to lack of relevance to modern vehicular networks which appear to be moving to cellular +V2X solutions. Future users who may wish to use this code should obtain it from an earlier ns-3 +release but should also be aware of a number of issues that arose and can be found in the +[ns-3 Issue tracker](https://gitlab.com/nsnam/ns-3-dev/-/issues/?state=all&label_name%5B%5D=module%3A%3Awave); in particular, #249, #879, #872, and #637. + ### Bugs fixed - (lr-wpan) !1406 - Fixes issues during MAC scan diff --git a/doc/models/Makefile b/doc/models/Makefile index f9a943ae6..584e865ce 100644 --- a/doc/models/Makefile +++ b/doc/models/Makefile @@ -98,7 +98,6 @@ SOURCES = \ $(SRC)/spectrum/doc/spectrum.rst \ $(SRC)/netanim/doc/animation.rst \ $(SRC)/flow-monitor/doc/flow-monitor.rst \ - $(SRC)/wave/doc/wave.rst \ $(SRC)/sixlowpan/doc/sixlowpan.rst \ $(SRC)/lr-wpan/doc/lr-wpan.rst \ diff --git a/doc/models/source/index.rst b/doc/models/source/index.rst index 29b6d3bba..382f7b9ca 100644 --- a/doc/models/source/index.rst +++ b/doc/models/source/index.rst @@ -59,6 +59,5 @@ from the ``doc/`` directory of each module. Source file column width is 100 col topology traffic-control uan - wave wifi wimax diff --git a/src/netanim/CMakeLists.txt b/src/netanim/CMakeLists.txt index eb1f68861..bb3a8bdce 100644 --- a/src/netanim/CMakeLists.txt +++ b/src/netanim/CMakeLists.txt @@ -12,7 +12,6 @@ build_lib( ${libuan} ${libenergy} ${liblr-wpan} - ${libwave} ${libpoint-to-point-layout} TEST_SOURCES test/netanim-test.cc ) diff --git a/src/netanim/model/animation-interface.cc b/src/netanim/model/animation-interface.cc index 08a601520..f4669782e 100644 --- a/src/netanim/model/animation-interface.cc +++ b/src/netanim/model/animation-interface.cc @@ -35,7 +35,6 @@ #ifdef __WIN32__ #include "ns3/bs-net-device.h" #include "ns3/csma-net-device.h" -#include "ns3/wave-net-device.h" #endif #include "animation-interface.h" @@ -108,7 +107,7 @@ AnimationInterface::AnimationInterface(const std::string fn) * The .dll.a/.lib however, only gets linked if we instantiate at * least one symbol exported by the .dll. * - * To ensure TypeIds from the Csma, Uan, Wave, Wifi and Wimax + * To ensure TypeIds from the Csma, Uan, Wifi and Wimax * modules are registered during runtime, we need to instantiate * at least one symbol exported by each of these module libraries. */ @@ -116,7 +115,6 @@ AnimationInterface::AnimationInterface(const std::string fn) static CsmaNetDevice c; static WifiNetDevice w; static UanNetDevice u; - static WaveNetDevice wv; #endif } @@ -495,7 +493,6 @@ AnimationInterface::MobilityAutoCheck() PurgePendingPackets(AnimationInterface::LTE); PurgePendingPackets(AnimationInterface::CSMA); PurgePendingPackets(AnimationInterface::LRWPAN); - PurgePendingPackets(AnimationInterface::WAVE); Simulator::Schedule(m_mobilityPollInterval, &AnimationInterface::MobilityAutoCheck, this); } } @@ -1084,50 +1081,6 @@ AnimationInterface::LrWpanPhyRxBeginTrace(std::string context, Ptr OutputWirelessPacketRxInfo(p, m_pendingLrWpanPackets[animUid], animUid); } -void -AnimationInterface::WavePhyTxBeginTrace(std::string context, Ptr p) -{ - NS_LOG_FUNCTION(this); - return GenericWirelessTxTrace(context, p, AnimationInterface::WAVE); -} - -void -AnimationInterface::WavePhyRxBeginTrace(std::string context, Ptr p) -{ - NS_LOG_FUNCTION(this); - CHECK_STARTED_INTIMEWINDOW_TRACKPACKETS; - Ptr ndev = GetNetDeviceFromContext(context); - NS_ASSERT(ndev); - UpdatePosition(ndev); - uint64_t animUid = GetAnimUidFromPacket(p); - NS_LOG_INFO("Wave RxBeginTrace for packet:" << animUid); - if (!IsPacketPending(animUid, AnimationInterface::WAVE)) - { - NS_ASSERT_MSG(false, "WavePhyRxBeginTrace: unknown Uid"); - std::ostringstream oss; - WifiMacHeader hdr; - if (!p->PeekHeader(hdr)) - { - NS_LOG_WARN("WaveMacHeader not present"); - return; - } - oss << hdr.GetAddr2(); - if (m_macToNodeIdMap.find(oss.str()) == m_macToNodeIdMap.end()) - { - NS_LOG_WARN("Transmitter Mac address " << oss.str() << " never seen before. Skipping"); - return; - } - Ptr txNode = NodeList::GetNode(m_macToNodeIdMap[oss.str()]); - UpdatePosition(txNode); - AnimPacketInfo pktInfo(nullptr, Simulator::Now(), m_macToNodeIdMap[oss.str()]); - AddPendingPacket(AnimationInterface::WAVE, animUid, pktInfo); - NS_LOG_WARN("WavePhyRxBegin: unknown Uid, but we are adding a wave packet"); - } - /// \todo NS_ASSERT (WavePacketIsPending (animUid) == true); - m_pendingWavePackets[animUid].ProcessRxBegin(ndev, Simulator::Now().GetSeconds()); - OutputWirelessPacketRxInfo(p, m_pendingWavePackets[animUid], animUid); -} - void AnimationInterface::WimaxTxTrace(std::string context, Ptr p, const Mac48Address& m) { @@ -1419,10 +1372,6 @@ AnimationInterface::ProtocolTypeToPendingPackets(AnimationInterface::ProtocolTyp pendingPackets = &m_pendingLrWpanPackets; break; } - case AnimationInterface::WAVE: { - pendingPackets = &m_pendingWavePackets; - break; - } } return pendingPackets; } @@ -1457,10 +1406,6 @@ AnimationInterface::ProtocolTypeToString(AnimationInterface::ProtocolType protoc result = "LRWPAN"; break; } - case AnimationInterface::WAVE: { - result = "WAVE"; - break; - } } return result; } @@ -1775,14 +1720,6 @@ AnimationInterface::ConnectCallbacks() MakeCallback(&AnimationInterface::LrWpanMacRxTrace, this)); Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::LrWpanNetDevice/Mac/MacRxDrop", MakeCallback(&AnimationInterface::LrWpanMacRxDropTrace, this)); - - // Wave - Config::ConnectFailSafe( - "/NodeList/*/DeviceList/*/$ns3::WaveNetDevice/PhyEntities/*/$ns3::WifiPhy/PhyTxBegin", - MakeCallback(&AnimationInterface::WavePhyTxBeginTrace, this)); - Config::ConnectFailSafe( - "/NodeList/*/DeviceList/*/$ns3::WaveNetDevice/PhyEntities/*/$ns3::WifiPhy/PhyRxBegin", - MakeCallback(&AnimationInterface::WavePhyRxBeginTrace, this)); } Vector diff --git a/src/netanim/model/animation-interface.h b/src/netanim/model/animation-interface.h index 95058ae65..402fe5090 100644 --- a/src/netanim/model/animation-interface.h +++ b/src/netanim/model/animation-interface.h @@ -544,8 +544,7 @@ class AnimationInterface WIFI, WIMAX, CSMA, - LRWPAN, - WAVE + LRWPAN }; /// NodeSize structure @@ -669,7 +668,6 @@ class AnimationInterface AnimUidPacketInfoMap m_pendingLtePackets; ///< pending LTE packets AnimUidPacketInfoMap m_pendingCsmaPackets; ///< pending CSMA packets AnimUidPacketInfoMap m_pendingUanPackets; ///< pending UAN packets - AnimUidPacketInfoMap m_pendingWavePackets; ///< pending WAVE packets std::map m_nodeLocation; ///< node location std::map m_macToNodeIdMap; ///< MAC to node ID map @@ -1077,19 +1075,6 @@ class AnimationInterface void WifiPhyRxBeginTrace(std::string context, Ptr p, RxPowerWattPerChannelBand rxPowersW); - /** - * WAVE Phy transmit begin trace function - * \param context the context - * \param p the packet - */ - void WavePhyTxBeginTrace(std::string context, Ptr p); - /** - * WAVE Phy receive begin trace function - * - * \param context the context - * \param p the packet - */ - void WavePhyRxBeginTrace(std::string context, Ptr p); /** * LR-WPAN Phy receive begin trace function * diff --git a/src/wave/CMakeLists.txt b/src/wave/CMakeLists.txt deleted file mode 100644 index 03b363842..000000000 --- a/src/wave/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -build_lib( - LIBNAME wave - SOURCE_FILES - helper/wave-bsm-helper.cc - helper/wave-bsm-stats.cc - helper/wave-helper.cc - helper/wave-mac-helper.cc - helper/wifi-80211p-helper.cc - model/bsm-application.cc - model/channel-coordinator.cc - model/channel-manager.cc - model/channel-scheduler.cc - model/default-channel-scheduler.cc - model/higher-tx-tag.cc - model/ocb-wifi-mac.cc - model/vendor-specific-action.cc - model/vsa-manager.cc - model/wave-frame-exchange-manager.cc - model/wave-net-device.cc - HEADER_FILES - helper/wave-bsm-helper.h - helper/wave-bsm-stats.h - helper/wave-helper.h - helper/wave-mac-helper.h - helper/wifi-80211p-helper.h - model/bsm-application.h - model/channel-coordinator.h - model/channel-manager.h - model/channel-scheduler.h - model/default-channel-scheduler.h - model/higher-tx-tag.h - model/ocb-wifi-mac.h - model/vendor-specific-action.h - model/vsa-manager.h - model/wave-frame-exchange-manager.h - model/wave-net-device.h - LIBRARIES_TO_LINK - ${libcore} - ${libpropagation} - ${libwifi} - ${libinternet} - TEST_SOURCES test/mac-extension-test-suite.cc - test/ocb-test-suite.cc -) diff --git a/src/wave/doc/wave.rst b/src/wave/doc/wave.rst deleted file mode 100644 index 5c11a5ced..000000000 --- a/src/wave/doc/wave.rst +++ /dev/null @@ -1,935 +0,0 @@ -WAVE models ------------ -WAVE is a system architecture for wireless-based vehicular communications, -specified by the IEEE. This chapter documents available models for WAVE -within |ns3|. The focus is on the MAC layer and MAC extension layer -defined by [ieee80211p]_ and [ieee1609dot4]_. - -.. include:: replace.txt - -.. heading hierarchy: - ------------- Chapter - ************* Section (#.#) - ============= Subsection (#.#.#) - ############# Paragraph (no number) - -Model Description -***************** - -WAVE is an overall system architecture for vehicular communications. -The standards for specifying WAVE include a set of extensions to the IEEE -802.11 standard, found in IEEE Std 802.11p-2010 [ieee80211p]_, and -the IEEE 1609 standard set, consisting of four documents: -resource manager: IEEE 1609.1 [ieee1609dot1]_, -security services: IEEE 1609.2 [ieee1609dot2]_, -network and transport layer services: IEEE 1609.3 [ieee1609dot3]_, -and multi-channel coordination: IEEE 1609.4 [ieee1609dot4]_. -Additionally, SAE standard J2735 [saej2735]_ describes a Dedicated -Short Range Communications (DSRC) application message set that allows -applications to transmit information using WAVE. - -In |ns3|, the focus of the ``wave`` module is on both the MAC layer and the -multi-channel coordination layer. -The key design aspect of 802.11p-compliant MAC layer is that they allow -communications outside the context of a basic service set (BSS). -The literature uses the acronym OCB to denote "outside the context -of a BSS", and the class ``ns3::OcbWifiMac`` models this in |ns3|. -This MAC does not require any association between devices (similar to an -adhoc WiFi MAC). Many management frames will not be used, but when used, the BSSID field -needs to be set to a wildcard BSSID value. Management information is -transmitted by what is called a vendor specific action (VSA) frame. With these -changes, the packet transmissions (for a moving vehicle) can be fast with -small delay in the MAC layer. Users can create IEEE802.11p-compliant device -(the object of the class ``ns3::WifiNetDevice`` associating with -``ns3::OcbWifiMac``) . - -The key design aspect of the WAVE-compliant MAC layer (including 802.11p MAC -layer and 1609.4 MAC extension layer) is that, based on OCB features, they -provide devices with the capability of switching between control and service channels, using a single radio or using multiple radios. -Therefore devices can communicate with others in single or multiple -channels, which can -support both safety related and non-safety related service for vehicular environments. - -At the physical layer, the biggest difference is the use of the 5.9 GHz band -with a channel bandwidth of 10 MHz. These physical -layer changes can make the wireless signal relatively more stable, -without degrading throughput too much (ranging from 3 Mbps to 27 Mbps). - -The source code for the WAVE MAC models lives in the directory -``src/wave``. - -For better modeling WAVE and VANET, the WAVE models for high layers -(mainly [ieee1609dot3]_ ) are planned for a later patch. - -Design -====== - -In |ns3|, support for 802.11p involves the MAC and PHY layers. -To use an 802.11p NetDevice, ``ns3::Wifi80211pHelper`` is suggested. - -In |ns3|, support for WAVE involves the MAC, its MAC extension and PHY layers. -To use a WAVE NetDevice, ``ns3::WaveHelper`` is suggested. - -MAC layer -######### - -The classes used to model the MAC layer are ``ns3::OrganizationIdentifier``, -``ns3::VendorSpecificActionHeader`` and ``ns3::OcbWifiMac``. - -The OrganizationIdentifier and VendorSpecificActionHeader are used to support -the sending of a Vendor Specific Action frame. - -OcbWifiMac is very similar to AdhocWifiMac, with some modifications. -The |ns3| AdhocWifiMac class is implemented very close to the 802.11p OCB -mode rather than a real 802.11 ad-hoc mode. The AdhocWifiMac has no BSS -context that is defined in 802.11 standard, so it will not take time to -send beacons and to authenticate, making its behavior similar to that -of an OcbWifiMac. - -1. SetBssid, GetBssid, SetSsid, GetSsid - - These methods are related to 802.11 BSS context, and are unused in the OCB context. - -2. SetLinkUpCallback, SetLinkDownCallback - - WAVE device can send packets directly, so the WiFi link is never down. - -3. SendVsc, AddReceiveVscCallback - - WAVE management information shall be sent by vendor specific action frames, - sent by the upper layer 1609.4 standard as WSA - (WAVE Service Advertisement) packets or other vendor specific information. - -4. SendTimingAdvertisement (not implemented) - - Although Timing Advertisement is very important and specifically defined in - 802.11p standard, it is not useful in a simulation environment. - Every node in |ns3| vehicular simulation is assumed to be already time - synchronized (perhaps by GPS). - -5. ConfigureEdca - - This method will allow the user to set EDCA parameters of WAVE channels - including CCH and SCHs. And the OcbWifiMac itself also uses this method - to configure default 802.11p EDCA parameters. - -6. Wildcard BSSID - - The Wildcard BSSID is set to "ff:ff:ff:ff:ff:ff". - As defined in IEEE 802.11-2007, a wildcard BSSID shall not be used in the - BSSID field except for management frames of subtype probe request. But Adhoc - mode of |ns3| simplifies this mechanism: when stations receive packets, - they will be forwarded up to the higher layer, regardless of BSSID. - This process is very close - to OCB mode as defined in 802.11p-2010, in which stations use the wildcard - BSSID to allow the higher layer of other stations to hear directly. - -7. Enqueue, Receive - - The most important methods are send and receive methods. According to the - standard, we should filter the frames that are not permitted. Thus here we - just identify the frames we care about; the other frames will be discarded. - -MAC extension layer -################### - -Although 1609.4 is still in the MAC layer, the implementation -approach for |ns3| does not do much modification in the -source code of the wifi module. Instead, if some feature is related -to wifi MAC classes, then a relevant subclass is defined; if some -feature has no relation to wifi MAC classes, then a new class -will be defined. This approach was selected to be non-intrusive to the -|ns3| wifi module. All of these classes will be hosted in a 'container' -class called ``ns3:: WaveNetDevice``. This class is a subclass inheriting -from ``ns3::NetDevice``, composed of the objects of -``ns3::ChannelScheduler``, ``ns3::ChannelManager``, -``ns3::ChannelCoordinator`` and ``ns3::VsaManager`` -classes to provide the features described in 1609.4 while still -containing the objects of ``ns3::OcbWifiMac`` and ``ns3::WifiPhy`` -classes. Moreover, ``ns3::OcbWifiMac`` class is further extended with -support for IEEE 1609.4 associating with ``ns3::HigherLayerTxVectorTag`` -and ``ns3::WaveMacLow``. The main work of the WaveNetDevice is to create -objects, configure, check arguments and provide new APIs for multiple -channel operation as follows: - -1. AddMac, GetMac and GetMacs - - Different from ``ns3::WifiNetDevice``, the WAVE device will have - multiple internal MAC entities rather than a single one. Each MAC - entity is used to support each WAVE channel. Thus, when - devices switch from the current channel to the next channel in different - channel intervals, the packets in the internal queue will not be - flushed and the current MAC entity will perform a suspend operation - until woken up in next appropriate channel interval. - -2. AddPhy, GetPhy and GetPhys - - Also in contrast to ``ns3::WifiNetDevice``, the WAVE device here - can allow more than one PHY entity, which permits the use cases of - of single-PHY devices or multiple-PHY devices. - -3. SetChannelScheduler and GetChannelScheduler - - How to deal with multiple MAC entities and PHY entities to assign - channel access for different requests from higher layer? IEEE - 1609.4 [ieee1609dot4]_ does not seem to give a very clear and detailed - mechanism, deferring to the implementor. In this model, the class - ``ns3::ChannelScheduler`` provides the API and delegates to the subclasses - to implement the virtual methods. In the current implementation, the default - assignment mechanism for channel access, - called ``ns3::DefaultChannelScheduler``, gives a simple answer that only - deals with multiple channel operation in the context of a single-PHY device. - If users define their own different assignment mechanisms such as in the - context of two PHY entities, they can easily reuse models using AddPhy and - SetChannelScheduler methods to import a new assignment mechanism. - -4. SetChannelManager and GetChannelManager - - class ``ns3::ChannelManager`` is a WAVE channel set which contains - valid WAVE channel numbers. Moreover, the tx information in this channel - set such as data rate and tx power level is used for transmitting management frames. - -5. SetVsaManager and GetVsaManager - - class ``ns3::VsaManager`` is used to deal with sending and receiving - VSA frames. According to different request parameters from the higher layer, - this class may transmit VSA frames repeatedly in the appropriate channel - number and channel interval. - -6. SetChannelCoordinator and GetChannelCoordinator - - class ``ns3::ChannelCoordinator`` is used to deal with channel coordination. - The WAVE device can be aware of the channel interval at the current time or - in the future. It can also notify listeners about incoming channel coordination - events. Generally this class is used in the case of assigning alternating CCH and SCH access. - -7. StartSch and StopSch - - In contrast to the basic 802.11p device that allow transmission packets - immediately after - the device is created, the WAVE device should assign channel access - for sending packets. This method will call class ``ns3::ChannelScheduler`` - to assign radio resources for the relevant channel. - -8. ChangeAddress - - The WAVE device can support a change of address after devices are already - initialized, which will cause all of MAC entities reset their status. - -9. CancelTx - - The WAVE device can support a request to cancel all transmissions associated - with the particular category and channel number, which will reset the - particular interval queue and drop all of the queued packets in this queue. - -10. RegisterTxProfile and DeleteTxProfile - - After channel access is assigned, we still cannot send IP-based - (or other protocol) packets by the ``Send()`` method. A tx profile should - be registered to specify tx parameters before transmission. - -11. StartVsa, StopVsa and SetWaveVsaCallback - - These methods will call an object from class ``ns3::VsaManager`` to send - and receive VSA frames. Generally these methods are used by IEEE 1609.3 - for WSA management information. - -12. SendX - - After channel access is assigned, we can send WSMP (or other protocol) - packets via the ``SendX()`` method. We should specify the tx parameters for - each packet, e.g. the channel number for transmit. - -13. Send and SetReceiveCallback - - This method is the abstract method defined in the parent class - ``ns3::NetDevice``, defined to allow the sending of IP-based packets. - The channel access should be already assigned and tx profile should - be registered, otherwise incoming packets from the higher layer will be - discarded. No matter whether packets are sent by Send method or SendX - method, the received packets will be only be delivered to the higher layer - by the registered ReceiveCallback. - -14. other methods from its parent class ``ns3::NetDevice`` - - These methods are implemented very similar to the code in ``ns3::WifiNetDevice``. - -In the above numbered list, we can categorize the methods into three types: -the first type, from 1 to 6 and also 14, is the configuration for modeling and -creating a WAVE device; the second type, from 7 to 11, is -the management plane of the standard; and the third type, 12 and 13, -is the data plane of the standard. - -Channel coordination - -The class ``ns3::ChannelCoordinator`` defines the CCH Interval, SCH Interval and GuardInterval. Users can be aware of which interval the current time or -future time will be in. If channel access mode is assigned to -alternating CCH and SCH access, -channel interval events will be notified repeatedly for class -``ns3::ChannelCoordinator`` to switch channels. Current default values are -for CCHI with 50ms interval, SCHI with 50ms interval, and GuardI with 4ms interval. Users can change these values by configuring the class attributes. - -Channel routing - -Channel routing service means different transmission approaches for WSMP data, -IP datagram and management information. -For WSMP data, the SendX () method implements the service primitive -MA-UNITDATAX, and users can -set transmission parameters for each individual packet. The parameters include -channel number, priority, -data rate and tx power level (expiration time is not supported now). -For IP datagrams, the Send () method is a virtual method from ``ns3::NetDevice`` that implements the service primitive MA-UNITDATA. -Users should insert QoS tags into packets themselves if they want to use QoS. -Moreover, a tx profile should be registered -before the Send method is called for transmit; the profile contains SCH number, data rate, power level and adaptable mode. -For management information, StartVsa method implements the service primitive -MLMEX-VSA. The tx information is already configured -in ``ns3::ChannelManager``, including data rate, power level and adaptable mode. - -Channel access assignment - -The channel access assignment is done by class ``ns3::ChannelScheduler`` to assign ContinuousAccess, ExtendedAccess -and AlternatingAccess. Besides that, immediate access is achieved by enabling -the "immediate" parameter, in which case -the request channel will be switched to immediately. However this class is a -virtual parent class. The current module provides a -subclass ``ns3::DefaultChannelScheduler`` to assign channel access in the context of a single-PHY device. In this subclass, if the channel -access is already assigned for another request, the next coming request will -fail until the previous channel access is released. -Users can implement different assignment mechanisms to deal with multiple MAC entities and multiple PHY entities by -inheriting from parent class ``ns3::ChannelScheduler``. -An important point is that channel access should be assigned before sending -routing packets, otherwise the packets will be discard. - -Vendor Specific Action frames - -When users want to send VSA repeatedly by calling WaveNetDevice::StartVsa, VSA will be sent repeatedly by -``ns3::VsaManager``. It is worth noting that if the peer MAC address is a unicast address, the VSA can only -be transmitted once even there is a repeat request. The tx parameters for VSA management frames can be obtained from the ``ns3::ChannelManager``. - -User priority and Multi-channel synchronization - -Since wifi module has already implemented a QoS mechanism, the wave module -reuses the mechanism; VSA frames will be assigned the default value with the -highest AC according to the standard. -Multiple-channel synchronization is very important in practice for devices -without a local timing source. -However, in simulation, every node is supposed to have the same system clock, which could be provided by GPS devices in a real environment, so this feature is not modelled in |ns3|. -During the guard interval, the device can only be in receive state, except -for the switch state when the device does channel switching operation. - -PHY layer -######### - -No modification or extension is made to the |ns3| PHY layer -corresponding to this model. -In the 802.11p standard, the PHY layer wireless technology is still 80211a OFDM with a 10MHz channel width, -so Wifi80211pHelper will only allow the user to set the standard -to WIFI_PHY_STANDARD_80211_10MHZ or WIFI_PHY_STANDARD_80211_20MHZ, -while WaveHelper will only support WIFI_PHY_STANDARD_80211_10MHZ. -The maximum station transmit power and maximum permitted EIRP defined in -802.11p is larger -than that of WiFi, so transmit range can normally become longer than the -usual WiFi. However, this feature will -not be implemented. Users who want to obtain longer range should configure -attributes "TxPowerStart", -"TxPowerEnd" and "TxPowerLevels" of the YansWifiPhy class by themselves. - -Scope and Limitations -===================== - -1. Does the model involve vehicular mobility of some sort? - -Vehicular networks involve not only communication protocols, but -also a communication environment including vehicular mobility and -propagation loss models. Because of specific features of the latter, -the protocols need to change. The MAC layer model in this project just -adapts MAC changes to vehicular environment. However this model -does not involve any vehicular mobility with time limit. While users -should understand that vehicular mobility is out of scope for the -current WAVE module, they can use any mobility model in |ns3|. For -example, users may use a ``ns3::RandomWaypointMobilityModel`` (RWP) -for node mobilty or may generate ns-2-style playback files using -other third-party tools and then playback those mobility traces -using ``ns3::Ns2MobilityHelper``. - -2. Does this model use different propagation models? - -Referring to the first issue, some more realistic propagation loss -models for vehicualr environment are suggested and welcome. Some -existing propagation los models in |ns3| are also suitable. -Normally, users can use Friis, Two-Ray Ground, and Nakagami models. -The ``ns3::VanetRoutingExample`` example defaults to Two-Ray -Ground propagation loss with no additional fading, although adding -stochastic Nakagami-m fading is parametrically supported. - -3. Are there any vehicular application models to drive the code? - -About vehicular application models, SAE J2375 depends on WAVE -architecture and is an application message set in US. Cooperative Awareness -Messages (CAM) and Decentralized Environment Notification Messages (DENM) can -be sent Europe between network and application layer, and is -very close to being an application model. The BSM in J2375 [saej2735] and CAM -send alert messages that every vehicle node will sent periodically about -its status information to cooperate with others. The -``ns3::VanetRoutingExample`` example sets up a network of (vehicular) -nodes that each broadcast BSMs at regular intervals and may additionally -attempt to route non-BSM data through the network using select IP-based -routing protocols. - -5. Why are there two kinds of NetDevice helpers? - -The current module provides two helpers to create two kinds of NetDevice. -The first is an object of WifiNetDevice (802.11p device) which mainly -contains class ``ns3::OcbWifiMac`` to enable OCB mode. The second -is an object of WaveNetDevice (WAVE device) which contains additional -classes ``ns3::ChannelScheduler``, ``ns3::ChannelManager``, -``ns3::ChannelCoordinator`` and ``ns3::VsaManager`` to support -multi-channel operation mode. The reason to provide a special 802.11p -device helper is that, considering the fact that many researchers are -interested in routing protocols or other aspects of vehicular environment in -a single channel context, they need neither multi-channel operation nor -WAVE architectures. -Besides that, the European standard may also reuse an 802.11p device in an -modified ITS-G5 implementation (maybe called ItsG5NetDevice). Hence, -the model supports configuration of both types of devices. - -References -========== - -.. [ieee80211p] IEEE Std 802.11p-2010 "IEEE Standard for Information technology-- Local and metropolitan area networks-- Specific requirements-- Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications Amendment 6: Wireless Access in Vehicular Environments" - -.. [ieee1609dot1] IEEE Std 1609.1-2010 "IEEE Standard for Wireless Access in Vehicular Environments (WAVE) - Resource Manager, 2010" - -.. [ieee1609dot2] IEEE Std 1609.2-2010 "IEEE Standard for Wireless Access in Vehicular Environments (WAVE) - Security Services for Applications and Management Messages, 2010" - -.. [ieee1609dot3] IEEE Std 1609.3-2010 "IEEE Standard for Wireless Access in Vehicular Environments (WAVE) - Networking Services, 2010" - -.. [ieee1609dot4] IEEE Std 1609.4-2010 "IEEE Standard for Wireless Access in Vehicular Environments (WAVE) - Multi-Channel Operation, 2010" - -.. [saej2735] SAE Std J2735 "J2735 dedicated short range communications (DSRC) message set dictionary. 2009" - -Usage -***** - -Helpers -======= - -The helpers include a) lower-level MAC and PHY channel helpers and -b) higher-level application helpers that handle the sending and receiving -of the Basic Safety Message (BSM). - -The lower-level helpers include ``ns3::YansWavePhyHelper``, ``ns3::NqosWaveMacHelper``, ``ns3::QosWaveMacHelper``, -``ns3::Wifi80211pHelper`` and ``ns3::WaveHelper``. - -Wifi80211pHelper is used to create -802.11p devices that follow the 802.11p-2010 standard. WaveHelper is -used to create WAVE devices that follow both 802.11p-2010 and 1609.4-2010 -standards which are the MAC and PHY layers of the WAVE architecture. - -The relation of ``ns3::NqosWaveMacHelper``, ``ns3::QosWaveMacHelper`` and -``ns3::Wifi80211pHelper`` is described as below: - -:: - - WifiHelper ------------use--------------> WifiMacHelper - ^ ^ ^ - | | | - | | | - inherit inherit inherit - | | | - Wifi80211pHelper ------use-----> QosWaveMacHelper or NqosWaveHelper - -From the above diagram, there are two Mac helper classes that both -inherit from the WifiMacHelper; when the WAVE module was originally -written, there were specialized versions (QoS and Nqos) of WifiMacHelper -that have since been removed from the Wifi codebase, but the distinction -remains in the WAVE helpers. The functions of WiFi 802.11p device can be achieved by -WaveNetDevice's ContinuousAccess assignment, Wifi80211pHelper is recommended -if there is no need for multiple channel operation. -Usage is as follows: - -:: - - NodeContainer nodes; - NetDeviceContainer devices; - nodes.Create(2); - YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default(); - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); - wifiPhy.SetChannel(wifiChannel.Create()); - NqosWave80211pMacHelper wifi80211pMac = NqosWaveMacHelper::Default(); - Wifi80211pHelper 80211pHelper = Wifi80211pHelper::Default(); - devices = 80211pHelper.Install(wifiPhy, wifi80211pMac, nodes); - -The relation of ``ns3::YansWavePhyHelper``, ``ns3::QosWaveMacHelper`` and ``ns3::WaveHelper`` -is described as below: - -:: - - WifiMacHelper - ^ - | - inherit - | - WaveHelper -------- only use --------> QosWaveMacHelper - -From the above diagram, WaveHelper is not the subclass of WifiHelper and should only -use QosWaveMacHelper because WAVE MAC layer is based on QoS mechanism. But -the WaveHelper is recommended if there is a need for multiple channel operation. -Usage is as follows: - -:: - - NodeContainer nodes; - NetDeviceContainer devices; - nodes.Create(2); - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); - YansWavePhyHelper wavePhy = YansWavePhyHelper::Default(); - wavePhy.SetChannel(wifiChannel.Create()); - QosWaveMacHelper waveMac = QosWaveMacHelper::Default(); - WaveHelper waveHelper = WaveHelper::Default(); - devices = waveHelper.Install(wavePhy, waveMac, nodes); - -The higher-level helpers include ``ns3::WaveBsmStats`` and ``ns3::WaveBsmHelper``. - -WaveBsmStats is used to collect and manage statistics, such as packet and byte -counts and Packet Delivery Ratio (PDR), regarding the sending -and receiving of WAVE BSM packets. WaveBsmHelper is used by applications that -wish to send and receive BSMs. - -The relation of ``ns3::WaveBsmHelper`` and ``WaveBsmStats`` is described -below: - -:: - - ----use----> WaveBsmHelper ----use----> WaveBsmStats - -From , usage is as follows: - - // declare WAVE BSM helper instance - WaveBsmHelper m_waveBsmHelper; - - // the following are passed to the WaveBsmHelper::Install() - // method, and they are thus assumed to be created and - // initialized themselves, based on the user's - // simulation setup criteria. - // container of network node - NodeContainer m_adhocTxNodes; - // (transmitting) devices (1 per node) - NetDeviceContainer m_adhocTxDevices; - // IPv4 interfaces (1 per device) - Ipv4InterfaceContainer m_adhocTxInterfaces; - // total simulation time (in seconds) - double m_TotalSimTime; - // WAVE BSM broadcast interval. E.g., 100ms = 0.1 seconds - double m_waveInterval; // seconds - // time-synchronization accuracy of GPS devices. E.g., +/- 40ns - double m_gpsAccuracyNs; - // array of distances (m) at which safety PDR shall be determined, - // e.g. 50m, 100m, 200m, 300m, 400m, 500m, 600m, 800m, 1000m, and 1500m - std::vector m_txSafetyRanges; - // used to get consistent random numbers across scenarios - int64_t m_streamIndex; - - m_waveBsmHelper.Install(m_adhocTxNodes, - m_adhocTxDevices, - m_adhocTxInterfaces, - Seconds(m_TotalSimTime), - m_wavePacketSize, - Seconds(m_waveInterval), - // convert GPS accuracy, in ns, to Time - Seconds(m_gpsAccuracyNs / 1000000.0), - m_txSafetyRanges); - - // fix random number streams - m_streamIndex += m_waveBsmHelper.AssignStreams(m_streamIndex); - -Example usages of BSM statistics are as follows: - - // Get the cumulative PDR of the first safety Tx range (i.e, 50m in the - // m_txSafetyRanges example above). - double bsm_pdr1 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(1); - - // total WAVE BSM bytes sent - uint32_t cumulativeWaveBsmBytes = m_waveBsmHelper.GetWaveBsmStats()->GetTxByteCount(); - - // get number of WAVE BSM packets sent - int wavePktsSent = m_waveBsmHelper.GetWaveBsmStats()->GetTxPktCount(); - - // get number of WAVE BSM packets received - int wavePktsReceived = m_waveBsmHelper.GetWaveBsmStats()->GetRxPktCount(); - - // reset count of WAVE BSM packets received - m_waveBsmHelper.GetWaveBsmStats()->SetRxPktCount(0); - - // reset count of WAVE BSM packets sent - m_waveBsmHelper.GetWaveBsmStats()->SetTxPktCount(0); - - // indicate that a node (nodeId) is moving. (set to 0 to "stop" node) - WaveBsmHelper::GetNodesMoving()[nodeId] = 1; - -APIs -==== - -MAC layer -######### -The 802.11p device can allow the upper layer to send different information -over Vendor Specific Action management frames by using different -OrganizationIdentifier fields to identify differences. - -1. create some Node objects and WifiNetDevice objects, e.g. one sender and one receiver. - -2. receiver defines an OrganizationIdentifier - - :: - - uint8_t oi_bytes[5] = {0x00, 0x50, 0xC2, 0x4A, 0x40}; - OrganizationIdentifier oi(oi_bytes,5); - -3. receiver defines a Callback for the defined OrganizationIdentifier - - :: - - VscCallback vsccall = MakeCallback(&VsaExample::GetWsaAndOi, this); - -4. receiver registers this identifier and function - - :: - - Ptr device1 = DynamicCast(nodes.Get(i)->GetDevice(0)); - Ptr ocb1 = DynamicCast(device->GetMac()); - ocb1->AddReceiveVscCallback(oi, vsccall); - -5. sender transmits management information over VSA frames - - :: - - Ptr vsc = Create(); - ocb2->SendVsc(vsc, Mac48Address::GetBroadcast(), m_16093oi); - -6. then registered callbacks in the receiver will be called. - -MAC extension layer -################### - -The WAVE devices allow the upper layer to route packets in different control -approaches. However dedicated APIs and invocation sequences should be -followed; otherwise, the packets may be discarded by devices. - -1. create some Node objects and WaveNetDevice objects by helpers, e.g. one sender and one receiver. - -2. receiver registers the receive callback if WSMP and IP-based packets are supposed to be received. - - :: - - // the class ``ns3::WaveNetDeviceExample``here will has a receive method "Receive" to be registered. - receiver->SetReceiveCallback(MakeCallback(&WaveNetDeviceExample::Receive, this)); - -3. receiver registers the receive callback if WSA frames are supposed to be received. - - :: - - // the class ``ns3::WaveNetDeviceExample``here will has a receive method "ReceiveVsa" to be registered. - receiver->SetWaveVsaCallback(MakeCallback (&WaveNetDeviceExample::ReceiveVsa, this)); - -4. sender and receiver assign channel access by StartSch method. - - :: - - // in this case that alternating access with non-immediate mode is assigned for sender and receiver devices. - const SchInfo schInfo = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, sender, schInfo); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, receiver, schInfo); - - or - - :: - - // in this case that continuous access with immediate mode is assigned for sender and receiver devices. - const SchInfo schInfo = SchInfo(SCH1, true, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, sender, schInfo); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, receiver, schInfo) - - or - - :: - - // in this case that extended access with non-immediate mode is assigned for sender and receiver devices. - const SchInfo schInfo = SchInfo(SCH1, false, 100); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, sender, schInfo); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, receiver, schInfo) - -5. sender registers a tx profile if IP-based packets are planned to be transmitted - - :: - - // the IP-based packets will be transmitted in SCH1 with 6Mbps and 4 txPowerLevel with adaptable mode. - const TxProfile txProfile = TxProfile(SCH1, true, 4, WifiMode("OfdmRate6MbpsBW10MHz")); - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::RegisterTxProfile, sender, txProfile); - -6. sender transmits WSMP packets by SendX method. - - :: - - // the data rate and txPowerLevel is controlled by the high layer which are 6Mbps and 0 level here. - const TxInfo txInfo = TxInfo(CCH, 7, WifiMode("OfdmRate6MbpsBW10MHz"), 0); - // this packet will contain WSMP header when IEEE 1609.3 model is implemented - const static uint16_t WSMP_PROT_NUMBER = 0x88DC; - Ptr wsaPacket = Create(100); - const Address dest = receiver->GetAddress(); - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::SendX, sender, wsaPacket, dest, WSMP_PROT_NUMBER, txInfo); - - or - - :: - - // the data rate and txPowerLevel is controlled by the MAC layer which are decided by WifiRemoteStationManager - const TxInfo txInfo = TxInfo(CCH, 7, WifiMode(), 8); - // this packet will contain WSMP header when IEEE 1609.3 model is implemented - const static uint16_t WSMP_PROT_NUMBER = 0x88DC; - Ptr wsaPacket = Create(100); - const Address dest = receiver->GetAddress(); - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::SendX, sender, wsaPacket, dest, WSMP_PROT_NUMBER, txInfo); - -7. sender transmits IP-based packets by Send method. - - :: - - const static uint16_t IPv6_PROT_NUMBER = 0x86DD; - Ptr packet = Create(100); - const Address dest = receiver->GetAddress(); - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::Send, sender, packet, dest, IPv6_PROT_NUMBER); - -8. send transmits WSA frames repeatedly by StartVsa method. - - :: - - // this packet will contain WSA management information when IEEE 1609.3 model is implemented - Ptr wsaPacket = Create(100); - Mac48Address dest = Mac48Address::GetBroadcast(); - const VsaInfo vsaInfo = VsaInfo(dest, OrganizationIdentifier(), 0, wsaPacket, SCH1, 100, VSA_TRANSMIT_IN_BOTHI); - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::StartVsa, sender, vsaInfo); - -9. sender stops WSA frames repeatedly transmit by StopVsa method. - - :: - - Simulator::Schedule(Seconds(3.0), &WaveNetDevice::StopVsa, sender, SCH1); - -10. sender and receiver release assigned channel access by StopSch method. - - :: - - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::StopSch, sender, SCH1); - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::StopSch, receiver, SCH1); - -11. sender or receiver changes current MAC address by ChangeAddress method. - - :: - - Address newAddress = Mac48Address::Allocate(); - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::ChangeAddress, sender, newAddress); - -12. sender cancels all transmissions with the particular category and channel number by CancelTx method. - - :: - - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::CancelTx, sender, CCH, AC_BE); - -For transmitting and receiving these packets successfully, -the normal and appropriate invocation procedures should be performed. - -(a) For WSMP, channel access should be assigned for transmit and receive. -The channel access release operation may be optional if there is no need for -transmission in another channel. - -:: - - StartSch -------------> SendX / ReceiveCallback --------------> StopSch - -(b) For IP, a tx profile should be registered before transmit and receive -operations. The delete operation of tx profile may be -optional if there is no need for transmission with other tx parameters. -The channel access assignment and release optional usage is the same with -WSMP here. - -:: - - StartSch -------------> RegisterTxProfile ----------> Send / ReceiveCallback --------------> DeleteTxProfile -------------> StopSch - -(c) For WSA, StartVsa is called to transmit while StopVsa is an optional -operation for canceling repeat transmit. The channel -access assignment and release optional usage is also the same with WSMP here. -To receive VSA, WaveVsaCallback should -be registered; otherwise, the received VSA frames will be discard by -the MAC extension layer and not delivered to the higher layer. - -:: - - StartSch -------------> StartVsa / WaveVsaCallback --------------> StopVsa ---------------> StopSch - -(d) Here an important point is that if the higher layer wants to transmit -these packets in a control channel (the channel 178), -there will be no need to request for CCH by the StartSch method, which means -that StartSch can be optional or should be avoided -here. The reason is that the default continuous CCH access has been assigned automatically after WAVE devices are created and initialized. -Therefore, if calling StartSch and StopSch method with CCH as a parameter, -the request will be discarded by devices and the method will return false to -indicate failure. - -Attributes -========== - -The channel interval duration's default value is defined in the standard. -However, the current implementation allows users to configure these -attributes with other values. These attributes are included in the class -``ns3::ChannelCoodinator`` with config paths shown in the below. The method -IsValidConfig is suggested to test whether new configuration follows the -standard. - -:: - -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/ChannelCoordinator/$ns3::ChannelCoordinator/CchInterval -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/ChannelCoordinator/$ns3::ChannelCoordinator/SchInterval -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/ChannelCoordinator/$ns3::ChannelCoordinator/GuardInterval - -The ``ns3::WaveNetDevice`` is a wrapper class that contains those classes to support for multiple channel -operation. To set or get the pointers of those objects, users can also -use them by config paths shown in the below. - -:: - -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/Mtu -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/Channel -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/PhyEntities -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/MacEntities -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/ChannelScheduler -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/ChannelManager -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/ChannelCoordinator -/NodeList/[i]/DeviceList/[i]/$ns3::WaveNetDevice/VsaManager - -Output -====== - -For the 802.11p device, current classes provide output of the same type as WiFi devices; -namely, ASCII and pcap traces, and logging output. The 802.11p logging -components can be enabled globally via the call to - -:: - - Wifi80211pHelper::EnableLogComponents(); - -For the WAVE device, current classes provide output of the same type as WiFi -devices; namely, ASCII and pcap traces, and logging output. The WAVE logging -components can be enabled globally via the call to - -:: - - WaveHelper::EnableLogComponents(); - - -Advanced Usage -============== - -Advanced WaveHelper configuration -################################# - -If users can make sure in which channel this WAVE device will work, -they can set specific channel numbers to save resources of unused channels . -Usage is as follows: - -:: - - // in this case, the MAC entities for SCH2 to SCH6 will not be created - WaveHelper helper = WaveHelper::Default(); - uint32_t channels[] = {CCH, SCH1}; - std::vector channelsVector(channels, channels + 2); - helper.CreateMacForChannel(channelsVector); - -If users can create other channel access assignment mechanism, e.g. -in the context of more PHY entities, which may be called -"ns3::AnotherScheduler", they can use this helper to create WAVE devices -with new assignment mechanisms. Usage is as follows: - -:: - - WaveHelper helper = WaveHelper::Default(); - helper.helper.CreateMacForChannel(ChannelManager::GetWaveChannels()); // create all 7 MAC entities for WAVE - helper.CreatePhys(2); // or other number which should be less than 7 - helper.SetChannelScheduler("ns3::AnotherScheduler"); // The AnotherScheduler should be implemented by users. - helper.SetRemoteStationManager("ns3::ConstantRateWifiManager"); // or other rate control algorithms - -Examples -======== - -A basic example exists called ``wave-simple-80211p.cc``. -This example shows basic construction of an 802.11p node. Two nodes -are constructed with 802.11p devices, and by default, one node sends a single -packet to another node (the number of packets and interval between -them can be configured by command-line arguments). The example shows -typical usage of the helper classes for this mode of WiFi. - -Another example exists called ``wave-simple-device.cc``. This -example shows how to create WAVE devices by helpers and the routing service -for different packets. -After WAVE devices are configured and created by helpers, these packets are -transmitted in different approaches. - -Another example exists called ``vanet-routing-compare.cc``. This -example shows how to create mobility nodes in a VANET scenario and -send Basic Safety Message (BSM) packets are regular intervals and/or -additional data traffic to be routed between nodes. BSMs are transmitted -assuming the WAVE Short Message Protocol (WSMP), whereas non-BSM data -packets are relayed by using one of several different IP-based routing -protocols (e.g., AODV, OLSR, DSDV, or DSR). - -Troubleshooting -=============== - -To be defined. - -Validation -********** - -A test suite named ``wifi-80211p-ocb`` is defined. This test -case consists of a stationary node and a mobile node. The mobile -node moves towards the stationary mode, and time points are checked -at which time the physical layer starts to receive packets (and -whether the MAC becomes associated, if applicable). The same physical -experiment is repeated for normal WiFi NetDevices in AP/STA mode, in -Adhoc mode, and the new OCB mode. - -Another test suite named ``wave-mac-extension`` is defined. This test suite -has four test cases, including ``channel-coordination``, ``channel-routing``, -``channel-access`` and ``annex-c``. The first case is to test channel -coordination -feature. The second case is to test channel routing for three types of packets. -The third case is to test four channel access assignments. And the fourth case -is to test the implemented feature described in the Annex C of the standard. -It is worth noting that the ``channel-routing`` and ``channel-access`` test -cases are both in the context of single-PHY device, which depends on the -default channel -access assignment mechanism ``ns3:DefaultChannelScheduler``, thus they may not -be suitable for testing when other channel access assignment mechanisms are -used. Although they are test cases, they are also good examples to show -usage. - -The ``ns3::VanetRoutingExample`` example was studied using mobility trace -files in the Raleigh, NC USA area generated using Simulation for Urban -Mobility (SUMO). Three environments were studied: a) an open highway -scenario, b) a residential neighborhood scenario, and c) and urban downtown -scenario. For each environment, a constant number of 50-750 vehicles was -maintained for 2000 simulation seconds (> 30 minutes). The mobility trace -file were played back using ``ns3::Ns2MobilityHelper``. All vehicular nodes -transmitted a 200-byte BSM at 10 Hz and the PDR was determined for -transmission ranges of 50-1500m. No additional non-BSM data was injected / -routed through the network. The default propagation loss model used -was Two-Ray Ground. Different fading / shadowing models were evaluated, -including a) no fading, b) stochastic Nakagami-m fading, and c) an -obstacle shadowing model (to be contributed to |ns3|). 30 trials of each -scenario were run in the North Carolina State University (NCSU) High -Performance Computing (HPC) center, with each trial requiring from -8 hours to 6 days of CPU time to complete. Preliminary results were -presented at the PhD Forum, 22nd IEEE International Conference on -Network Protocols (ICNP), October 24, 2014, Research Triangle Park, NC. -See: https://web.archive.org/web/20170808113648/http://www4.ncsu.edu/~scarpen/Research_files/Final-PHD_Forum_SE_Carpenter_2014.pdf diff --git a/src/wave/examples/CMakeLists.txt b/src/wave/examples/CMakeLists.txt deleted file mode 100644 index 11206c0f3..000000000 --- a/src/wave/examples/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -build_lib_example( - NAME wave-simple-80211p - SOURCE_FILES wave-simple-80211p.cc - LIBRARIES_TO_LINK - ${libcore} - ${libapplications} - ${libmobility} - ${libnetwork} - ${libwifi} - ${libwave} -) - -build_lib_example( - NAME wave-simple-device - SOURCE_FILES wave-simple-device.cc - LIBRARIES_TO_LINK - ${libcore} - ${libapplications} - ${libmobility} - ${libnetwork} - ${libwifi} - ${libwave} -) - -build_lib_example( - NAME vanet-routing-compare - SOURCE_FILES vanet-routing-compare.cc - LIBRARIES_TO_LINK - ${libcore} - ${libaodv} - ${libapplications} - ${libconfig-store} - ${libdsr} - ${libdsdv} - ${libflow-monitor} - ${libmobility} - ${libnetwork} - ${libolsr} - ${libpropagation} - ${libwifi} - ${libwave} -) diff --git a/src/wave/examples/low99-ct-unterstrass-1day.filt.7.adj.mob b/src/wave/examples/low99-ct-unterstrass-1day.filt.7.adj.mob deleted file mode 100644 index 2d5642bec..000000000 --- a/src/wave/examples/low99-ct-unterstrass-1day.filt.7.adj.mob +++ /dev/null @@ -1,1515 +0,0 @@ -# Statistics: -# T_min: 0.000000 T_max: 300.010000 -# X_min: 10 X_max: 4660 -# Y_min: 10 Y_max: 3010 -# V_min: 9.937942 V_max: 32.054187 V_avg: 15.446680 -# nn: 99 area: 13950000.000000 -# events: 792 hosts/area: 0.070968 -# Last mov would end time at (time): 351.020 -# -# Processed from file: ct-unterstrass-1day.filt.7.mov -# ADJUSTMENT: X_min=679990.0 Y_min=247490.0 T_min=36610.980000 T_max= T_scalar=1 -# -# Statistics: -# T_min: 36610.980000 T_max: 36910.990000 -# X_min: 680000 X_max: 684650 -# Y_min: 247500 Y_max: 250500 -# V_min: 9.937942 V_max: 32.054187 V_avg: 15.446680 -# nn: 99 area: 13950000.000000 -# events: 792 hosts/area: 0.070968 -# Last mov would end time at (time): 36962.000 -# -# Processed from file: ct-unterstrass-1day.filt.mov -# FILTERING: X_min=0 X_max=999999999 Y_min=0 Y_max=999999999 T_min=36610.990000 T_max=36910.990000 V_min=0 -# -# Statistics: -# T_min: 35560.990000 T_max: 37461.000000 -# X_min: 680000 X_max: 684650 -# Y_min: 247500 Y_max: 250500 -# V_min: 7.806775 V_max: 32.386778 V_avg: 15.496693 -# nn: 505 area: 13950000.000000 -# events: 5174 hosts/area: 0.362007 -# Last mov would end time at (time): 37484.000 -# -# Processed from file: ct-unterstrass-1day.mov -# FILTERING: X_min=0 X_max=999999999 Y_min=0 Y_max=999999999 T_min=35561 T_max=37461 V_min=0 -# -# -# VANET traces; ns-2 movement file -# Parser: car-xml2ns -# -# City region: Unterstrass -# Statistics: -# T_min: 16392.990000 T_max: 88387.766811 -# X_min: 680000 X_max: 685000 -# Y_min: 247500 Y_max: 250500 -# V_min: 1.279985 V_max: 32.641710 V_avg: 14.853009 -# nn: 96934 area: 15000000.000000 -# events: 1973502 hosts/area: 64.622667 -# Last mov would end time at (time): 88387.767 -# -# Processed from file: VANET-traces-ns2.mov -# X_min=680000 X_max=685000 Y_min=247500 Y_max=250500 T_min=0 T_max=999999999 V_min=0 -# -# -# VANET traces; ns-2 movement file -# Parser: car-xml2ns -# -# Statistic for VANET-traces-ns2.mov -# T_min: 14208.990000 T_max: 90811.692948 -# X_min: 486740 X_max: 840500 -# Y_min: 46000 Y_max: 309000 -# V_min: 0.787110 V_max: 32.679368 V_avg: 20.536439 -# nn: 259978 -# events: 27609858 -# -# More information on VANET traces can be found in the MobiHoc 2006 paper: -# Val Naumov, Rainer Baumann, Thomas Gross "An Evaluation of Inter-Vehicle Ad Hoc Networks Based on Realistic Vehicular Traces" -# (http://www.lst.inf.ethz.ch/research) -# -# The speed of 10^9 m/s is used to initially place nodes -# from (0,0) to their trip starting points, e.g.: -# $node_(12345) set X_ 0.0 -# $node_(12345) set Y_ 0.0 -# $node_(12345) set Z_ 0.0 -# $ns_ at 10000.990000 "$node_(12345) setdest 710130.000000 91630.000000 1000000000.0" -# - -$ns_ at 0.0 "$node_(0) switch OFF" ;# set_X,Y,Z -$node_(0) set X_ 0.000000 -$node_(0) set Y_ 0.000000 -$node_(0) set Z_ 0.0 -$ns_ at 0.000000 "$node_(0) setdest 1335.996339 1004.578227 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(0) switch ON" ;# inside -$ns_ at 0.010000 "$node_(0) setdest 1290.000000 1090.000000 16.142807" ;# -$ns_ at 0.0 "$node_(1) switch OFF" ;# set_X,Y,Z -$node_(1) set X_ 0.000000 -$node_(1) set Y_ 0.000000 -$node_(1) set Z_ 0.0 -$ns_ at 0.000000 "$node_(1) setdest 3386.590740 102.881482 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(1) switch ON" ;# inside -$ns_ at 0.010000 "$node_(1) setdest 3310.000000 160.000000 13.629680" ;# -$ns_ at 0.0 "$node_(2) switch OFF" ;# set_X,Y,Z -$node_(2) set X_ 0.000000 -$node_(2) set Y_ 0.000000 -$node_(2) set Z_ 0.0 -$ns_ at 0.000000 "$node_(2) setdest 1151.671243 2088.378976 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(2) switch ON" ;# inside -$ns_ at 0.010000 "$node_(2) setdest 1071.000000 2103.000000 16.364369" ;# -$ns_ at 0.0 "$node_(3) switch OFF" ;# set_X,Y,Z -$node_(3) set X_ 0.000000 -$node_(3) set Y_ 0.000000 -$node_(3) set Z_ 0.0 -$ns_ at 0.000000 "$node_(3) setdest 2145.733295 1665.474912 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(3) switch ON" ;# inside -$ns_ at 0.010000 "$node_(3) setdest 2145.139452 1666.087027 12.762536" ;# -$ns_ at 0.0 "$node_(4) switch OFF" ;# set_X,Y,Z -$node_(4) set X_ 0.000000 -$node_(4) set Y_ 0.000000 -$node_(4) set Z_ 0.0 -$ns_ at 0.000000 "$node_(4) setdest 1344.895727 2053.358569 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(4) switch ON" ;# inside -$ns_ at 0.010000 "$node_(4) setdest 1071.000000 2103.000000 16.364369" ;# -$ns_ at 0.0 "$node_(5) switch OFF" ;# set_X,Y,Z -$node_(5) set X_ 0.000000 -$node_(5) set Y_ 0.000000 -$node_(5) set Z_ 0.0 -$ns_ at 0.000000 "$node_(5) setdest 1302.721238 2548.142173 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(5) switch ON" ;# inside -$ns_ at 0.010000 "$node_(5) setdest 1265.525646 2567.811046 15.943000" ;# -$ns_ at 0.0 "$node_(6) switch OFF" ;# set_X,Y,Z -$node_(6) set X_ 0.000000 -$node_(6) set Y_ 0.000000 -$node_(6) set Z_ 0.0 -$ns_ at 0.000000 "$node_(6) setdest 3014.330992 373.464793 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(6) switch ON" ;# inside -$ns_ at 0.010000 "$node_(6) setdest 2560.000000 10.000000 13.527727" ;# -$ns_ at 0.0 "$node_(7) switch OFF" ;# set_X,Y,Z -$node_(7) set X_ 0.000000 -$node_(7) set Y_ 0.000000 -$node_(7) set Z_ 0.0 -$ns_ at 0.000000 "$node_(7) setdest 3827.411664 1295.726554 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(7) switch ON" ;# inside -$ns_ at 0.010000 "$node_(7) setdest 3810.000000 1480.000000 13.211580" ;# -$ns_ at 0.0 "$node_(8) switch OFF" ;# set_X,Y,Z -$node_(8) set X_ 0.000000 -$node_(8) set Y_ 0.000000 -$node_(8) set Z_ 0.0 -$ns_ at 0.000000 "$node_(8) setdest 3902.621739 499.753269 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(8) switch ON" ;# inside -$ns_ at 0.010000 "$node_(8) setdest 3878.703961 752.883083 13.865834" ;# -$ns_ at 0.0 "$node_(9) switch OFF" ;# set_X,Y,Z -$node_(9) set X_ 0.000000 -$node_(9) set Y_ 0.000000 -$node_(9) set Z_ 0.0 -$ns_ at 0.000000 "$node_(9) setdest 2967.771730 91.554346 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(9) switch ON" ;# inside -$ns_ at 0.010000 "$node_(9) setdest 2560.000000 10.000000 16.627238" ;# -$ns_ at 0.0 "$node_(10) switch OFF" ;# set_X,Y,Z -$node_(10) set X_ 0.000000 -$node_(10) set Y_ 0.000000 -$node_(10) set Z_ 0.0 -$ns_ at 0.000000 "$node_(10) setdest 2318.919116 1486.960295 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(10) switch ON" ;# inside -$ns_ at 0.010000 "$node_(10) setdest 2291.086492 1515.649308 13.727766" ;# -$ns_ at 0.0 "$node_(11) switch OFF" ;# set_X,Y,Z -$node_(11) set X_ 0.000000 -$node_(11) set Y_ 0.000000 -$node_(11) set Z_ 0.0 -$ns_ at 0.000000 "$node_(11) setdest 1419.066610 2039.915684 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(11) switch ON" ;# inside -$ns_ at 0.010000 "$node_(11) setdest 1384.989853 2046.091826 15.647451" ;# -$ns_ at 0.0 "$node_(12) switch OFF" ;# set_X,Y,Z -$node_(12) set X_ 0.000000 -$node_(12) set Y_ 0.000000 -$node_(12) set Z_ 0.0 -$ns_ at 0.000000 "$node_(12) setdest 3124.161401 1857.484928 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(12) switch ON" ;# inside -$ns_ at 0.010000 "$node_(12) setdest 3111.196216 1922.959110 13.728154" ;# -$ns_ at 0.0 "$node_(13) switch OFF" ;# set_X,Y,Z -$node_(13) set X_ 0.000000 -$node_(13) set Y_ 0.000000 -$node_(13) set Z_ 0.0 -$ns_ at 0.000000 "$node_(13) setdest 1765.904200 206.177913 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(13) switch ON" ;# inside -$ns_ at 0.010000 "$node_(13) setdest 1575.313011 560.132979 16.252872" ;# -$ns_ at 0.0 "$node_(14) switch OFF" ;# set_X,Y,Z -$node_(14) set X_ 0.000000 -$node_(14) set Y_ 0.000000 -$node_(14) set Z_ 0.0 -$ns_ at 0.000000 "$node_(14) setdest 2644.602103 77.681682 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(14) switch ON" ;# inside -$ns_ at 0.010000 "$node_(14) setdest 2560.000000 10.000000 13.526031" ;# -$ns_ at 0.0 "$node_(15) switch OFF" ;# set_X,Y,Z -$node_(15) set X_ 0.000000 -$node_(15) set Y_ 0.000000 -$node_(15) set Z_ 0.0 -$ns_ at 0.000000 "$node_(15) setdest 1412.404730 1269.781947 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(15) switch ON" ;# inside -$ns_ at 0.010000 "$node_(15) setdest 1450.191974 1325.281961 13.601995" ;# -$ns_ at 0.0 "$node_(16) switch OFF" ;# set_X,Y,Z -$node_(16) set X_ 0.000000 -$node_(16) set Y_ 0.000000 -$node_(16) set Z_ 0.0 -$ns_ at 0.000000 "$node_(16) setdest 3808.631535 1683.901279 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(16) switch ON" ;# inside -$ns_ at 0.010000 "$node_(16) setdest 3802.025034 2668.269892 12.752087" ;# -$ns_ at 0.0 "$node_(17) switch OFF" ;# set_X,Y,Z -$node_(17) set X_ 0.000000 -$node_(17) set Y_ 0.000000 -$node_(17) set Z_ 0.0 -$ns_ at 0.000000 "$node_(17) setdest 2168.625696 1641.878129 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(17) switch ON" ;# inside -$ns_ at 0.010000 "$node_(17) setdest 2077.481811 1735.826441 12.043499" ;# -$ns_ at 0.0 "$node_(18) switch OFF" ;# set_X,Y,Z -$node_(18) set X_ 0.000000 -$node_(18) set Y_ 0.000000 -$node_(18) set Z_ 0.0 -$ns_ at 0.000000 "$node_(18) setdest 1487.721647 2027.472503 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(18) switch ON" ;# inside -$ns_ at 0.010000 "$node_(18) setdest 1444.642737 2035.280214 15.606334" ;# -$ns_ at 0.0 "$node_(19) switch OFF" ;# set_X,Y,Z -$node_(19) set X_ 0.000000 -$node_(19) set Y_ 0.000000 -$node_(19) set Z_ 0.0 -$ns_ at 0.000000 "$node_(19) setdest 2522.490892 1279.382742 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(19) switch ON" ;# inside -$ns_ at 0.010000 "$node_(19) setdest 2510.000000 1290.000000 16.231244" ;# -$ns_ at 0.0 "$node_(20) switch OFF" ;# set_X,Y,Z -$node_(20) set X_ 0.000000 -$node_(20) set Y_ 0.000000 -$node_(20) set Z_ 0.0 -$ns_ at 0.000000 "$node_(20) setdest 3808.901377 1643.694814 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(20) switch ON" ;# inside -$ns_ at 0.010000 "$node_(20) setdest 3805.915125 2088.646417 11.701108" ;# -$ns_ at 0.0 "$node_(21) switch OFF" ;# set_X,Y,Z -$node_(21) set X_ 0.000000 -$node_(21) set Y_ 0.000000 -$node_(21) set Z_ 0.0 -$ns_ at 0.000000 "$node_(21) setdest 3310.000000 343.829579 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(21) switch ON" ;# inside -$ns_ at 0.010000 "$node_(21) setdest 3310.000000 417.405846 13.140070" ;# -$ns_ at 0.0 "$node_(22) switch OFF" ;# set_X,Y,Z -$node_(22) set X_ 0.000000 -$node_(22) set Y_ 0.000000 -$node_(22) set Z_ 0.0 -$ns_ at 0.000000 "$node_(22) setdest 2855.036555 1507.937286 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(22) switch ON" ;# inside -$ns_ at 0.010000 "$node_(22) setdest 2651.364951 1666.692719 16.038021" ;# -$ns_ at 0.0 "$node_(23) switch OFF" ;# set_X,Y,Z -$node_(23) set X_ 0.000000 -$node_(23) set Y_ 0.000000 -$node_(23) set Z_ 0.0 -$ns_ at 0.000000 "$node_(23) setdest 1592.382893 1534.124874 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(23) switch ON" ;# inside -$ns_ at 0.010000 "$node_(23) setdest 1610.000000 1560.000000 15.573683" ;# -$ns_ at 0.0 "$node_(24) switch OFF" ;# set_X,Y,Z -$node_(24) set X_ 0.000000 -$node_(24) set Y_ 0.000000 -$node_(24) set Z_ 0.0 -$ns_ at 8.316123 "$node_(24) setdest 3917.755102 10.000000 1000000000.000000" ;# init_node -$ns_ at 8.326123 "$node_(24) switch ON" ;# inside -$ns_ at 8.326123 "$node_(24) setdest 3930.000000 210.000000 13.636597" ;# -$ns_ at 0.0 "$node_(25) switch OFF" ;# set_X,Y,Z -$node_(25) set X_ 0.000000 -$node_(25) set Y_ 0.000000 -$node_(25) set Z_ 0.0 -$ns_ at 0.000000 "$node_(25) setdest 2260.037210 1971.720046 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(25) switch ON" ;# inside -$ns_ at 0.010000 "$node_(25) setdest 1980.000000 2190.000000 16.131718" ;# -$ns_ at 0.0 "$node_(26) switch OFF" ;# set_X,Y,Z -$node_(26) set X_ 0.000000 -$node_(26) set Y_ 0.000000 -$node_(26) set Z_ 0.0 -$ns_ at 0.000000 "$node_(26) setdest 3296.991650 876.671168 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(26) switch ON" ;# inside -$ns_ at 0.010000 "$node_(26) setdest 3290.000000 1020.000000 13.033539" ;# -$ns_ at 0.0 "$node_(27) switch OFF" ;# set_X,Y,Z -$node_(27) set X_ 0.000000 -$node_(27) set Y_ 0.000000 -$node_(27) set Z_ 0.0 -$ns_ at 0.000000 "$node_(27) setdest 3175.428887 1175.425929 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(27) switch ON" ;# inside -$ns_ at 0.010000 "$node_(27) setdest 3032.000000 1370.000000 16.104256" ;# -$ns_ at 0.0 "$node_(28) switch OFF" ;# set_X,Y,Z -$node_(28) set X_ 0.000000 -$node_(28) set Y_ 0.000000 -$node_(28) set Z_ 0.0 -$ns_ at 0.000000 "$node_(28) setdest 2409.695914 1393.390366 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(28) switch ON" ;# inside -$ns_ at 0.010000 "$node_(28) setdest 2179.032149 1631.151477 13.107394" ;# -$ns_ at 0.0 "$node_(29) switch OFF" ;# set_X,Y,Z -$node_(29) set X_ 0.000000 -$node_(29) set Y_ 0.000000 -$node_(29) set Z_ 0.0 -$ns_ at 0.000000 "$node_(29) setdest 3452.084028 54.039030 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(29) switch ON" ;# inside -$ns_ at 0.010000 "$node_(29) setdest 3431.218482 69.599776 13.629680" ;# -$ns_ at 0.0 "$node_(30) switch OFF" ;# set_X,Y,Z -$node_(30) set X_ 0.000000 -$node_(30) set Y_ 0.000000 -$node_(30) set Z_ 0.0 -$ns_ at 0.000000 "$node_(30) setdest 1115.272435 1128.723407 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(30) switch ON" ;# inside -$ns_ at 0.010000 "$node_(30) setdest 1049.135457 1143.380791 17.914625" ;# -$ns_ at 0.0 "$node_(31) switch OFF" ;# set_X,Y,Z -$node_(31) set X_ 0.000000 -$node_(31) set Y_ 0.000000 -$node_(31) set Z_ 0.0 -$ns_ at 0.000000 "$node_(31) setdest 3917.389929 343.456587 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(31) switch ON" ;# inside -$ns_ at 0.010000 "$node_(31) setdest 3854.700880 1006.915687 13.418520" ;# -$ns_ at 0.0 "$node_(32) switch OFF" ;# set_X,Y,Z -$node_(32) set X_ 0.000000 -$node_(32) set Y_ 0.000000 -$node_(32) set Z_ 0.0 -$ns_ at 0.000000 "$node_(32) setdest 1916.905265 2069.068425 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(32) switch ON" ;# inside -$ns_ at 0.010000 "$node_(32) setdest 1860.000000 1960.000000 13.653812" ;# -$ns_ at 0.0 "$node_(33) switch OFF" ;# set_X,Y,Z -$node_(33) set X_ 0.000000 -$node_(33) set Y_ 0.000000 -$node_(33) set Z_ 0.0 -$ns_ at 25.600909 "$node_(33) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 25.610909 "$node_(33) switch ON" ;# inside -$ns_ at 25.610909 "$node_(33) setdest 3310.000000 160.000000 13.629680" ;# -$ns_ at 0.0 "$node_(34) switch OFF" ;# set_X,Y,Z -$node_(34) set X_ 0.000000 -$node_(34) set Y_ 0.000000 -$node_(34) set Z_ 0.0 -$ns_ at 0.000000 "$node_(34) setdest 3322.430436 150.729845 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(34) switch ON" ;# inside -$ns_ at 0.010000 "$node_(34) setdest 3310.000000 160.000000 15.352977" ;# -$ns_ at 0.0 "$node_(35) switch OFF" ;# set_X,Y,Z -$node_(35) set X_ 0.000000 -$node_(35) set Y_ 0.000000 -$node_(35) set Z_ 0.0 -$ns_ at 0.000000 "$node_(35) setdest 1489.808529 718.927017 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(35) switch ON" ;# inside -$ns_ at 0.010000 "$node_(35) setdest 1290.000000 1090.000000 16.203316" ;# -$ns_ at 0.0 "$node_(36) switch OFF" ;# set_X,Y,Z -$node_(36) set X_ 0.000000 -$node_(36) set Y_ 0.000000 -$node_(36) set Z_ 0.0 -$ns_ at 0.000000 "$node_(36) setdest 3217.224801 688.858919 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(36) switch ON" ;# inside -$ns_ at 0.010000 "$node_(36) setdest 2696.443341 1131.523160 13.544152" ;# -$ns_ at 0.0 "$node_(37) switch OFF" ;# set_X,Y,Z -$node_(37) set X_ 0.000000 -$node_(37) set Y_ 0.000000 -$node_(37) set Z_ 0.0 -$ns_ at 0.000000 "$node_(37) setdest 3310.000000 367.414167 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(37) switch ON" ;# inside -$ns_ at 0.010000 "$node_(37) setdest 3310.000000 610.000000 13.469508" ;# -$ns_ at 0.0 "$node_(38) switch OFF" ;# set_X,Y,Z -$node_(38) set X_ 0.000000 -$node_(38) set Y_ 0.000000 -$node_(38) set Z_ 0.0 -$ns_ at 0.000000 "$node_(38) setdest 3304.673333 719.196665 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(38) switch ON" ;# inside -$ns_ at 0.010000 "$node_(38) setdest 3290.000000 1020.000000 13.682917" ;# -$ns_ at 0.0 "$node_(39) switch OFF" ;# set_X,Y,Z -$node_(39) set X_ 0.000000 -$node_(39) set Y_ 0.000000 -$node_(39) set Z_ 0.0 -$ns_ at 26.010001 "$node_(39) setdest 2560.000000 10.000000 1000000000.000000" ;# init_node -$ns_ at 26.020001 "$node_(39) switch ON" ;# inside -$ns_ at 26.020001 "$node_(39) setdest 2560.000000 10.000000 16.187162" ;# -$ns_ at 0.0 "$node_(40) switch OFF" ;# set_X,Y,Z -$node_(40) set X_ 0.000000 -$node_(40) set Y_ 0.000000 -$node_(40) set Z_ 0.0 -$ns_ at 0.000000 "$node_(40) setdest 3447.779989 57.248822 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(40) switch ON" ;# inside -$ns_ at 0.010000 "$node_(40) setdest 3310.000000 160.000000 13.211017" ;# -$ns_ at 0.0 "$node_(41) switch OFF" ;# set_X,Y,Z -$node_(41) set X_ 0.000000 -$node_(41) set Y_ 0.000000 -$node_(41) set Z_ 0.0 -$ns_ at 13.039465 "$node_(41) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 13.049465 "$node_(41) switch ON" ;# inside -$ns_ at 13.049465 "$node_(41) setdest 3310.000000 160.000000 13.226301" ;# -$ns_ at 0.0 "$node_(42) switch OFF" ;# set_X,Y,Z -$node_(42) set X_ 0.000000 -$node_(42) set Y_ 0.000000 -$node_(42) set Z_ 0.0 -$ns_ at 4.811641 "$node_(42) setdest 3917.755102 10.000000 1000000000.000000" ;# init_node -$ns_ at 4.821641 "$node_(42) switch ON" ;# inside -$ns_ at 4.821641 "$node_(42) setdest 3930.000000 210.000000 12.370050" ;# -$ns_ at 0.0 "$node_(43) switch OFF" ;# set_X,Y,Z -$node_(43) set X_ 0.000000 -$node_(43) set Y_ 0.000000 -$node_(43) set Z_ 0.0 -$ns_ at 0.000000 "$node_(43) setdest 3926.546213 153.588154 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(43) switch ON" ;# inside -$ns_ at 0.010000 "$node_(43) setdest 3930.000000 210.000000 11.280936" ;# -$ns_ at 0.0 "$node_(44) switch OFF" ;# set_X,Y,Z -$node_(44) set X_ 0.000000 -$node_(44) set Y_ 0.000000 -$node_(44) set Z_ 0.0 -$ns_ at 0.000000 "$node_(44) setdest 3237.376624 671.729869 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(44) switch ON" ;# inside -$ns_ at 0.010000 "$node_(44) setdest 2887.075383 969.485924 13.635745" ;# -$ns_ at 0.0 "$node_(45) switch OFF" ;# set_X,Y,Z -$node_(45) set X_ 0.000000 -$node_(45) set Y_ 0.000000 -$node_(45) set Z_ 0.0 -$ns_ at 0.000000 "$node_(45) setdest 2447.488785 1354.434637 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(45) switch ON" ;# inside -$ns_ at 0.010000 "$node_(45) setdest 2140.491793 1670.877690 12.843287" ;# -$ns_ at 0.0 "$node_(46) switch OFF" ;# set_X,Y,Z -$node_(46) set X_ 0.000000 -$node_(46) set Y_ 0.000000 -$node_(46) set Z_ 0.0 -$ns_ at 0.000000 "$node_(46) setdest 607.861722 2915.580975 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(46) switch ON" ;# inside -$ns_ at 0.010000 "$node_(46) setdest 429.306931 3010.000000 16.007155" ;# -$ns_ at 12.628238 "$node_(46) switch OFF" ;# leaving_area -$ns_ at 0.0 "$node_(47) switch OFF" ;# set_X,Y,Z -$node_(47) set X_ 0.000000 -$node_(47) set Y_ 0.000000 -$node_(47) set Z_ 0.0 -$ns_ at 0.000000 "$node_(47) setdest 3247.678772 560.143018 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(47) switch ON" ;# inside -$ns_ at 0.010000 "$node_(47) setdest 2934.323476 309.458781 13.323892" ;# -$ns_ at 0.0 "$node_(48) switch OFF" ;# set_X,Y,Z -$node_(48) set X_ 0.000000 -$node_(48) set Y_ 0.000000 -$node_(48) set Z_ 0.0 -$ns_ at 0.000000 "$node_(48) setdest 3230.522293 1783.588111 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(48) switch ON" ;# inside -$ns_ at 0.010000 "$node_(48) setdest 3432.713282 2204.819337 15.937765" ;# -$ns_ at 0.0 "$node_(49) switch OFF" ;# set_X,Y,Z -$node_(49) set X_ 0.000000 -$node_(49) set Y_ 0.000000 -$node_(49) set Z_ 0.0 -$ns_ at 0.000000 "$node_(49) setdest 2880.947177 974.694900 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(49) switch ON" ;# inside -$ns_ at 0.010000 "$node_(49) setdest 2510.000000 1290.000000 12.480033" ;# -$ns_ at 0.0 "$node_(50) switch OFF" ;# set_X,Y,Z -$node_(50) set X_ 0.000000 -$node_(50) set Y_ 0.000000 -$node_(50) set Z_ 0.0 -$ns_ at 0.000000 "$node_(50) setdest 3263.335772 649.664594 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(50) switch ON" ;# inside -$ns_ at 0.010000 "$node_(50) setdest 2799.701274 1043.753917 12.273351" ;# -$ns_ at 0.0 "$node_(51) switch OFF" ;# set_X,Y,Z -$node_(51) set X_ 0.000000 -$node_(51) set Y_ 0.000000 -$node_(51) set Z_ 0.0 -$ns_ at 0.000000 "$node_(51) setdest 474.355810 2204.848463 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(51) switch ON" ;# inside -$ns_ at 0.010000 "$node_(51) setdest 682.726230 2169.279179 15.059437" ;# -$ns_ at 0.0 "$node_(52) switch OFF" ;# set_X,Y,Z -$node_(52) set X_ 0.000000 -$node_(52) set Y_ 0.000000 -$node_(52) set Z_ 0.0 -$ns_ at 0.000000 "$node_(52) setdest 2947.761957 2261.550302 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(52) switch ON" ;# inside -$ns_ at 0.010000 "$node_(52) setdest 2789.626910 2518.979448 9.937942" ;# -$ns_ at 0.0 "$node_(53) switch OFF" ;# set_X,Y,Z -$node_(53) set X_ 0.000000 -$node_(53) set Y_ 0.000000 -$node_(53) set Z_ 0.0 -$ns_ at 0.000000 "$node_(53) setdest 2192.087846 1617.694066 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(53) switch ON" ;# inside -$ns_ at 0.010000 "$node_(53) setdest 2038.935574 1775.558716 13.528813" ;# -$ns_ at 0.0 "$node_(54) switch OFF" ;# set_X,Y,Z -$node_(54) set X_ 0.000000 -$node_(54) set Y_ 0.000000 -$node_(54) set Z_ 0.0 -$ns_ at 0.000000 "$node_(54) setdest 3199.841733 2703.083238 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(54) switch ON" ;# inside -$ns_ at 0.010000 "$node_(54) setdest 3161.675427 2757.606532 17.588560" ;# -$ns_ at 0.0 "$node_(55) switch OFF" ;# set_X,Y,Z -$node_(55) set X_ 0.000000 -$node_(55) set Y_ 0.000000 -$node_(55) set Z_ 0.0 -$ns_ at 0.000000 "$node_(55) setdest 3295.830375 900.477312 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(55) switch ON" ;# inside -$ns_ at 0.010000 "$node_(55) setdest 3290.000000 1020.000000 14.939426" ;# -$ns_ at 0.0 "$node_(56) switch OFF" ;# set_X,Y,Z -$node_(56) set X_ 0.000000 -$node_(56) set Y_ 0.000000 -$node_(56) set Z_ 0.0 -$ns_ at 27.328226 "$node_(56) setdest 3511.136363 10.000000 1000000000.000000" ;# init_node -$ns_ at 27.338226 "$node_(56) switch ON" ;# inside -$ns_ at 27.338226 "$node_(56) setdest 3310.000000 160.000000 13.430737" ;# -$ns_ at 0.0 "$node_(57) switch OFF" ;# set_X,Y,Z -$node_(57) set X_ 0.000000 -$node_(57) set Y_ 0.000000 -$node_(57) set Z_ 0.0 -$ns_ at 34.730846 "$node_(57) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 34.740846 "$node_(57) switch ON" ;# inside -$ns_ at 34.740846 "$node_(57) setdest 3479.270091 33.764678 13.210281" ;# -$ns_ at 0.0 "$node_(58) switch OFF" ;# set_X,Y,Z -$node_(58) set X_ 0.000000 -$node_(58) set Y_ 0.000000 -$node_(58) set Z_ 0.0 -$ns_ at 0.000000 "$node_(58) setdest 2502.168218 1298.072760 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(58) switch ON" ;# inside -$ns_ at 0.010000 "$node_(58) setdest 2113.048299 1699.165600 11.361111" ;# -$ns_ at 0.0 "$node_(59) switch OFF" ;# set_X,Y,Z -$node_(59) set X_ 0.000000 -$node_(59) set Y_ 0.000000 -$node_(59) set Z_ 0.0 -$ns_ at 0.000000 "$node_(59) setdest 3180.760450 2438.422024 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(59) switch ON" ;# inside -$ns_ at 0.010000 "$node_(59) setdest 3230.000000 2660.000000 12.603172" ;# -$ns_ at 0.0 "$node_(60) switch OFF" ;# set_X,Y,Z -$node_(60) set X_ 0.000000 -$node_(60) set Y_ 0.000000 -$node_(60) set Z_ 0.0 -$ns_ at 0.000000 "$node_(60) setdest 3298.426977 847.246971 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(60) switch ON" ;# inside -$ns_ at 0.010000 "$node_(60) setdest 3290.000000 1020.000000 13.294269" ;# -$ns_ at 0.0 "$node_(61) switch OFF" ;# set_X,Y,Z -$node_(61) set X_ 0.000000 -$node_(61) set Y_ 0.000000 -$node_(61) set Z_ 0.0 -$ns_ at 0.000000 "$node_(61) setdest 1517.875494 666.802655 1000000000.000000" ;# init_node -$ns_ at 0.010000 "$node_(61) switch ON" ;# inside -$ns_ at 0.010000 "$node_(61) setdest 1417.806992 852.644157 17.696076" ;# -$ns_ at 0.076824 "$node_(3) setdest 1860.000000 1960.000000 15.198613" ;# -$ns_ at 1.919728 "$node_(29) setdest 3310.000000 160.000000 14.971426" ;# -$ns_ at 2.020000 "$node_(34) setdest 3060.137172 110.027434 18.021479" ;# -$ns_ at 2.020000 "$node_(19) setdest 2050.787795 1763.341811 11.429272" ;# -$ns_ at 2.223263 "$node_(11) setdest 1178.615011 2083.495632 17.638126" ;# -$ns_ at 2.649143 "$node_(5) setdest 655.054915 2890.625411 16.620014" ;# -$ns_ at 2.815319 "$node_(18) setdest 1272.682302 2066.446680 18.024390" ;# -$ns_ at 2.921721 "$node_(10) setdest 2125.369766 1686.465011 15.334893" ;# -$ns_ at 3.020000 "$node_(23) setdest 1727.986402 1748.778243 13.637945" ;# -$ns_ at 3.791364 "$node_(30) setdest 400.780217 1287.070330 16.187840" ;# -$ns_ at 3.793946 "$node_(54) setdest 3090.000000 2860.000000 15.194059" ;# -$ns_ at 4.871944 "$node_(12) setdest 3090.000000 2030.000000 15.265594" ;# -$ns_ at 4.946232 "$node_(15) setdest 1565.819542 1495.109953 13.868165" ;# -$ns_ at 5.609381 "$node_(21) setdest 3310.000000 520.726879 13.636364" ;# -$ns_ at 6.020000 "$node_(2) setdest 986.595609 2117.408013 17.746939" ;# -$ns_ at 6.020000 "$node_(43) setdest 4184.308366 276.189849 10.624238" ;# -$ns_ at 0.0 "$node_(62) switch OFF" ;# set_X,Y,Z -$node_(62) set X_ 0.000000 -$node_(62) set Y_ 0.000000 -$node_(62) set Z_ 0.0 -$ns_ at 21.663345 "$node_(62) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 21.673345 "$node_(62) switch ON" ;# inside -$ns_ at 21.673345 "$node_(62) setdest 1624.591870 468.615099 15.962482" ;# -$ns_ at 7.020000 "$node_(0) setdest 1144.244259 860.324287 13.686075" ;# -$ns_ at 8.020000 "$node_(1) setdest 3310.000000 406.390980 13.636364" ;# -$ns_ at 9.020000 "$node_(14) setdest 2560.000000 10.000000 12.232374" ;# -$ns_ at 9.020000 "$node_(14) switch OFF" ;# leaving_area -$ns_ at 9.020000 "$node_(55) setdest 3267.610092 1133.069036 15.548435" ;# -#$ns_ at 10.020000 $node_(32) arrived_to 1860.000000 1960.000000 -$ns_ at 10.020000 "$node_(32) switch OFF" ;# arrived_to -$ns_ at 11.020000 "$node_(32) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 11.030000 "$node_(32) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 10.844793 "$node_(2) setdest 245.000000 2244.000000 16.292787" ;# -$ns_ at 10.878517 "$node_(17) setdest 1944.619748 1872.776568 14.878609" ;# -$ns_ at 11.937533 "$node_(61) setdest 1290.000000 1090.000000 15.780990" ;# -$ns_ at 12.020000 "$node_(26) setdest 3184.747598 1551.524630 13.728154" ;# -$ns_ at 12.511178 "$node_(18) setdest 1071.000000 2103.000000 15.172901" ;# -$ns_ at 13.020000 "$node_(54) setdest 2856.135371 2789.296740 15.963316" ;# -$ns_ at 13.020000 "$node_(12) setdest 2660.000000 2730.000000 10.953640" ;# -$ns_ at 13.020000 "$node_(29) setdest 3310.000000 610.000000 13.636364" ;# -$ns_ at 13.186257 "$node_(21) setdest 3310.000000 610.000000 15.302890" ;# -$ns_ at 0.0 "$node_(63) switch OFF" ;# set_X,Y,Z -$node_(63) set X_ 0.000000 -$node_(63) set Y_ 0.000000 -$node_(63) set Z_ 0.0 -$ns_ at 40.472571 "$node_(63) setdest 3511.136363 10.000000 1000000000.000000" ;# init_node -$ns_ at 40.482571 "$node_(63) switch ON" ;# inside -$ns_ at 40.482571 "$node_(63) setdest 3506.004290 13.827309 13.160959" ;# -$ns_ at 14.020000 "$node_(60) setdest 3095.122467 1284.368746 15.380819" ;# -$ns_ at 14.020000 "$node_(40) setdest 3310.000000 610.000000 13.636364" ;# -$ns_ at 14.046680 "$node_(51) setdest 809.510897 2147.636760 17.612676" ;# -$ns_ at 14.114380 "$node_(11) setdest 1071.000000 2103.000000 18.519346" ;# -$ns_ at 15.020000 "$node_(7) setdest 3806.412901 2014.477749 13.272601" ;# -$ns_ at 0.0 "$node_(64) switch OFF" ;# set_X,Y,Z -$node_(64) set X_ 0.000000 -$node_(64) set Y_ 0.000000 -$node_(64) set Z_ 0.0 -$ns_ at 19.911426 "$node_(64) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 19.921426 "$node_(64) switch ON" ;# inside -$ns_ at 19.921426 "$node_(64) setdest 3362.802632 120.621766 13.629680" ;# -$ns_ at 16.020000 "$node_(27) setdest 2490.547415 1792.044791 15.855134" ;# -$ns_ at 0.0 "$node_(65) switch OFF" ;# set_X,Y,Z -$node_(65) set X_ 0.000000 -$node_(65) set Y_ 0.000000 -$node_(65) set Z_ 0.0 -$ns_ at 51.600909 "$node_(65) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 51.610909 "$node_(65) switch ON" ;# inside -$ns_ at 51.610909 "$node_(65) setdest 3310.000000 160.000000 13.629680" ;# -$ns_ at 16.111438 "$node_(22) setdest 2371.972360 1884.470213 14.981457" ;# -$ns_ at 16.159300 "$node_(34) setdest 2560.000000 10.000000 16.008495" ;# -$ns_ at 16.267702 "$node_(53) setdest 1860.000000 1960.000000 15.339731" ;# -$ns_ at 16.433257 "$node_(55) setdest 3195.265097 1498.411260 13.248144" ;# -$ns_ at 18.020000 "$node_(4) setdest 675.293496 2170.547962 18.050376" ;# -$ns_ at 18.346962 "$node_(8) setdest 3850.356305 1052.895768 15.199614" ;# -$ns_ at 18.441338 "$node_(10) setdest 1860.000000 1960.000000 12.884523" ;# -$ns_ at 19.020000 "$node_(37) setdest 3019.273244 857.117743 12.352381" ;# -$ns_ at 19.020000 "$node_(59) setdest 3090.000000 2860.000000 16.275407" ;# -$ns_ at 19.343302 "$node_(23) setdest 1822.317642 1899.708228 13.873502" ;# -$ns_ at 19.761014 "$node_(15) setdest 1610.000000 1560.000000 14.927294" ;# -$ns_ at 20.020000 "$node_(21) setdest 3044.211745 835.920017 10.938056" ;# -$ns_ at 0.0 "$node_(66) switch OFF" ;# set_X,Y,Z -$node_(66) set X_ 0.000000 -$node_(66) set Y_ 0.000000 -$node_(66) set Z_ 0.0 -$ns_ at 35.071538 "$node_(66) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 35.081538 "$node_(66) switch ON" ;# inside -$ns_ at 35.081538 "$node_(66) setdest 1740.185930 253.940416 16.589689" ;# -$ns_ at 0.0 "$node_(67) switch OFF" ;# set_X,Y,Z -$node_(67) set X_ 0.000000 -$node_(67) set Y_ 0.000000 -$node_(67) set Z_ 0.0 -$ns_ at 55.600909 "$node_(67) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 55.610909 "$node_(67) switch ON" ;# inside -$ns_ at 55.610909 "$node_(67) setdest 3310.000000 160.000000 13.629680" ;# -$ns_ at 21.020000 "$node_(11) setdest 622.932312 2179.486131 16.430355" ;# -$ns_ at 21.349295 "$node_(51) setdest 1071.000000 2103.000000 15.912438" ;# -#$ns_ at 22.020000 $node_(42) arrived_to 3930.000000 210.000000 -$ns_ at 22.020000 "$node_(42) switch OFF" ;# arrived_to -$ns_ at 23.020000 "$node_(42) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 23.030000 "$node_(42) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 23.020000 $node_(25) arrived_to 1980.000000 2190.000000 -$ns_ at 23.020000 "$node_(25) switch OFF" ;# arrived_to -$ns_ at 24.020000 "$node_(25) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 24.030000 "$node_(25) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 23.020000 "$node_(38) setdest 3213.718018 1405.224010 13.728154" ;# -$ns_ at 23.702829 "$node_(17) setdest 1860.000000 1960.000000 14.611387" ;# -$ns_ at 24.020000 "$node_(24) setdest 3886.630839 668.990288 13.427965" ;# -$ns_ at 24.744488 "$node_(13) setdest 1485.096514 727.677903 19.049920" ;# -$ns_ at 25.283097 "$node_(28) setdest 1999.747898 1815.952167 13.727766" ;# -$ns_ at 26.020000 "$node_(15) setdest 1319.230885 1852.926956 15.221304" ;# -#$ns_ at 26.020000 $node_(9) arrived_to 2560.000000 10.000000 -$ns_ at 26.020000 "$node_(9) switch OFF" ;# arrived_to -$ns_ at 27.020000 "$node_(9) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 27.030000 "$node_(9) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 26.088671 "$node_(1) setdest 3310.000000 501.409247 15.578368" ;# -$ns_ at 26.895783 "$node_(0) setdest 1111.751489 809.123558 14.424040" ;# -$ns_ at 27.020000 "$node_(18) setdest 793.293376 2150.405126 16.430355" ;# -$ns_ at 27.020000 "$node_(35) setdest 1218.992860 978.109962 14.247854" ;# -$ns_ at 27.020000 "$node_(39) setdest 2945.432575 318.346060 13.527727" ;# -$ns_ at 0.0 "$node_(68) switch OFF" ;# set_X,Y,Z -$node_(68) set X_ 0.000000 -$node_(68) set Y_ 0.000000 -$node_(68) set Z_ 0.0 -$ns_ at 43.372761 "$node_(68) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 43.382761 "$node_(68) switch ON" ;# inside -$ns_ at 43.382761 "$node_(68) setdest 1626.443588 465.176194 16.264410" ;# -#$ns_ at 28.020000 $node_(3) arrived_to 1860.000000 1960.000000 -$ns_ at 28.020000 "$node_(3) switch OFF" ;# arrived_to -$ns_ at 29.020000 "$node_(3) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 29.030000 "$node_(3) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 28.325008 "$node_(54) setdest 2728.508244 2750.711795 16.637835" ;# -$ns_ at 0.0 "$node_(69) switch OFF" ;# set_X,Y,Z -$node_(69) set X_ 0.000000 -$node_(69) set Y_ 0.000000 -$node_(69) set Z_ 0.0 -$ns_ at 29.354827 "$node_(69) setdest 3511.136363 10.000000 1000000000.000000" ;# init_node -$ns_ at 29.364827 "$node_(69) switch ON" ;# inside -$ns_ at 29.364827 "$node_(69) setdest 3310.000000 160.000000 12.765598" ;# -$ns_ at 29.326782 "$node_(48) setdest 3579.061480 2509.711417 18.214880" ;# -$ns_ at 30.020000 "$node_(61) setdest 1344.994298 1170.772875 16.003152" ;# -$ns_ at 30.128119 "$node_(47) setdest 2671.108075 98.886460 13.527727" ;# -$ns_ at 30.410654 "$node_(52) setdest 2760.657979 2566.138174 11.977805" ;# -$ns_ at 30.754101 "$node_(43) setdest 4346.804596 318.483388 11.379102" ;# -$ns_ at 31.099924 "$node_(0) setdest 960.000000 570.000000 13.537772" ;# -$ns_ at 32.172350 "$node_(23) setdest 1860.000000 1960.000000 14.666683" ;# -$ns_ at 32.188044 "$node_(1) setdest 3310.000000 610.000000 12.295211" ;# -$ns_ at 33.020000 "$node_(41) setdest 3310.000000 368.122809 14.621366" ;# -#$ns_ at 33.020000 $node_(17) arrived_to 1860.000000 1960.000000 -$ns_ at 33.020000 "$node_(17) switch OFF" ;# arrived_to -$ns_ at 34.020000 "$node_(17) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 34.030000 "$node_(17) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 33.497734 "$node_(64) setdest 3310.000000 160.000000 14.565550" ;# -$ns_ at 33.726495 "$node_(44) setdest 2825.150685 1022.121917 15.219462" ;# -$ns_ at 34.020000 "$node_(53) setdest 1444.491111 2035.307695 15.517953" ;# -$ns_ at 34.338383 "$node_(45) setdest 1983.675546 1832.519053 13.147719" ;# -$ns_ at 34.733511 "$node_(13) setdest 1290.000000 1090.000000 15.654787" ;# -#$ns_ at 35.020000 $node_(59) arrived_to 3090.000000 2860.000000 -$ns_ at 35.020000 "$node_(59) switch OFF" ;# arrived_to -$ns_ at 36.020000 "$node_(59) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 36.030000 "$node_(59) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 35.031340 "$node_(52) setdest 2660.000000 2730.000000 10.690566" ;# -$ns_ at 35.373400 "$node_(60) setdest 3032.000000 1370.000000 18.840035" ;# -$ns_ at 36.126115 "$node_(61) setdest 1610.000000 1560.000000 13.494562" ;# -$ns_ at 36.321008 "$node_(35) setdest 960.000000 570.000000 13.170769" ;# -$ns_ at 36.338804 "$node_(54) setdest 2660.000000 2730.000000 19.442226" ;# -$ns_ at 37.750015 "$node_(57) setdest 3310.000000 160.000000 14.797356" ;# -$ns_ at 38.020000 "$node_(23) setdest 1980.000000 2190.000000 13.653812" ;# -$ns_ at 38.037306 "$node_(20) setdest 3802.957225 2529.373416 12.845117" ;# -$ns_ at 38.173057 "$node_(8) setdest 3810.000000 1480.000000 13.060778" ;# -$ns_ at 39.020000 "$node_(51) setdest 1437.648683 2036.547831 15.741164" ;# -$ns_ at 39.020000 "$node_(64) setdest 3310.000000 610.000000 13.636364" ;# -$ns_ at 39.066531 "$node_(44) setdest 2510.000000 1290.000000 13.362525" ;# -$ns_ at 0.0 "$node_(70) switch OFF" ;# set_X,Y,Z -$node_(70) set X_ 0.000000 -$node_(70) set Y_ 0.000000 -$node_(70) set Z_ 0.0 -$ns_ at 40.803139 "$node_(70) setdest 3917.755102 10.000000 1000000000.000000" ;# init_node -$ns_ at 40.813139 "$node_(70) switch ON" ;# inside -$ns_ at 40.813139 "$node_(70) setdest 3921.897255 77.655162 14.231013" ;# -$ns_ at 39.756789 "$node_(22) setdest 2132.313140 2071.276830 18.619493" ;# -$ns_ at 40.020000 "$node_(49) setdest 2411.643775 1391.382570 14.280623" ;# -$ns_ at 40.259448 "$node_(4) setdest 245.000000 2244.000000 15.177654" ;# -$ns_ at 40.969015 "$node_(63) setdest 3379.387957 108.253049 14.844106" ;# -#$ns_ at 41.020000 $node_(54) arrived_to 2660.000000 2730.000000 -$ns_ at 41.020000 "$node_(54) switch OFF" ;# arrived_to -$ns_ at 42.020000 "$node_(54) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 42.030000 "$node_(54) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 42.020000 "$node_(60) setdest 2648.452720 1668.962709 15.306413" ;# -$ns_ at 42.020000 "$node_(1) setdest 2860.842523 991.783855 12.842619" ;# -$ns_ at 44.020000 "$node_(6) setdest 2560.000000 10.000000 15.881382" ;# -$ns_ at 44.020000 "$node_(6) switch OFF" ;# leaving_area -$ns_ at 44.038988 "$node_(28) setdest 1860.000000 1960.000000 15.460807" ;# -$ns_ at 44.166535 "$node_(18) setdest 705.713161 2165.355259 18.400794" ;# -$ns_ at 44.199506 "$node_(5) setdest 443.743582 3002.365959 18.819432" ;# -$ns_ at 44.545590 "$node_(55) setdest 3177.366049 1588.801450 14.749930" ;# -$ns_ at 0.0 "$node_(71) switch OFF" ;# set_X,Y,Z -$node_(71) set X_ 0.000000 -$node_(71) set Y_ 0.000000 -$node_(71) set Z_ 0.0 -$ns_ at 48.463739 "$node_(71) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 48.473739 "$node_(71) switch ON" ;# inside -$ns_ at 48.473739 "$node_(71) setdest 1290.000000 1090.000000 16.454428" ;# -$ns_ at 44.815166 "$node_(30) setdest 10.000000 1373.675675 19.086673" ;# -$ns_ at 65.785924 "$node_(30) switch OFF" ;# leaving_area -$ns_ at 45.020000 "$node_(33) setdest 3310.000000 435.072554 13.066308" ;# -$ns_ at 45.510099 "$node_(43) setdest 4660.000000 400.000000 10.270737" ;# -$ns_ at 45.576106 "$node_(70) setdest 3930.000000 210.000000 12.695710" ;# -$ns_ at 0.0 "$node_(72) switch OFF" ;# set_X,Y,Z -$node_(72) set X_ 0.000000 -$node_(72) set Y_ 0.000000 -$node_(72) set Z_ 0.0 -$ns_ at 67.289997 "$node_(72) setdest 10.000000 518.541114 1000000000.000000" ;# init_node -$ns_ at 67.299997 "$node_(72) switch ON" ;# inside -$ns_ at 67.299997 "$node_(72) setdest 100.000000 470.000000 13.245560" ;# -$ns_ at 47.020000 "$node_(56) setdest 3100.811579 118.162316 14.610681" ;# -$ns_ at 47.020000 "$node_(29) setdest 2871.215338 982.966963 12.885176" ;# -$ns_ at 47.254156 "$node_(41) setdest 3310.000000 610.000000 12.889226" ;# -$ns_ at 0.0 "$node_(73) switch OFF" ;# set_X,Y,Z -$node_(73) set X_ 0.000000 -$node_(73) set Y_ 0.000000 -$node_(73) set Z_ 0.0 -$ns_ at 50.986223 "$node_(73) setdest 3511.136363 10.000000 1000000000.000000" ;# init_node -$ns_ at 50.996223 "$node_(73) switch ON" ;# inside -$ns_ at 50.996223 "$node_(73) setdest 3310.000000 160.000000 14.738798" ;# -$ns_ at 47.893835 "$node_(48) setdest 3800.000000 2970.000000 15.892582" ;# -#$ns_ at 48.020000 $node_(40) arrived_to 3310.000000 610.000000 -$ns_ at 48.020000 "$node_(40) switch OFF" ;# arrived_to -$ns_ at 49.020000 "$node_(40) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 49.030000 "$node_(40) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 48.685196 "$node_(11) setdest 494.489546 2201.411591 17.638474" ;# -$ns_ at 48.994971 "$node_(18) setdest 245.000000 2244.000000 16.102564" ;# -$ns_ at 49.020000 "$node_(34) setdest 2560.000000 10.000000 14.572952" ;# -$ns_ at 49.020000 "$node_(34) switch OFF" ;# leaving_area -$ns_ at 49.020000 "$node_(10) setdest 1071.000000 2103.000000 16.364369" ;# -$ns_ at 49.197879 "$node_(58) setdest 1860.000000 1960.000000 14.073656" ;# -$ns_ at 49.588366 "$node_(50) setdest 2510.000000 1290.000000 13.372981" ;# -$ns_ at 49.673763 "$node_(31) setdest 3810.000000 1480.000000 14.690782" ;# -$ns_ at 49.909718 "$node_(37) setdest 2895.038572 962.717214 13.832905" ;# -$ns_ at 49.911226 "$node_(49) setdest 2167.765222 1642.765079 12.740107" ;# -$ns_ at 50.020000 "$node_(69) setdest 3310.000000 394.728837 13.636364" ;# -$ns_ at 50.474190 "$node_(36) setdest 2510.000000 1290.000000 14.788989" ;# -$ns_ at 50.792760 "$node_(55) setdest 3090.000000 2030.000000 13.536046" ;# -$ns_ at 0.0 "$node_(74) switch OFF" ;# set_X,Y,Z -$node_(74) set X_ 0.000000 -$node_(74) set Y_ 0.000000 -$node_(74) set Z_ 0.0 -$ns_ at 66.494791 "$node_(74) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 66.504791 "$node_(74) switch ON" ;# inside -$ns_ at 66.504791 "$node_(74) setdest 1473.664290 748.909176 16.136236" ;# -$ns_ at 51.467543 "$node_(45) setdest 1860.000000 1960.000000 14.149804" ;# -$ns_ at 51.489652 "$node_(26) setdest 3150.170530 1726.138824 15.687276" ;# -$ns_ at 51.609540 "$node_(63) setdest 3310.000000 160.000000 15.998430" ;# -$ns_ at 51.625744 "$node_(38) setdest 3166.147644 1645.454398 15.199707" ;# -$ns_ at 51.782074 "$node_(66) setdest 1604.241888 506.407922 17.882141" ;# -$ns_ at 51.911523 "$node_(21) setdest 2745.055228 1090.203056 11.797218" ;# -#$ns_ at 53.020000 $node_(0) arrived_to 960.000000 570.000000 -$ns_ at 53.020000 "$node_(0) switch OFF" ;# arrived_to -$ns_ at 54.020000 "$node_(0) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 54.030000 "$node_(0) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 53.020000 "$node_(57) setdest 3310.000000 610.000000 13.636364" ;# -$ns_ at 53.135829 "$node_(15) setdest 1071.000000 2103.000000 18.658828" ;# -$ns_ at 54.020000 "$node_(52) setdest 2682.314562 2813.307698 18.212495" ;# -$ns_ at 54.304528 "$node_(62) setdest 1421.963170 844.925541 16.589689" ;# -$ns_ at 0.0 "$node_(75) switch OFF" ;# set_X,Y,Z -$node_(75) set X_ 0.000000 -$node_(75) set Y_ 0.000000 -$node_(75) set Z_ 0.0 -$ns_ at 89.010001 "$node_(75) setdest 2560.000000 10.000000 1000000000.000000" ;# init_node -$ns_ at 89.020001 "$node_(75) switch ON" ;# inside -$ns_ at 89.020001 "$node_(75) setdest 2560.000000 10.000000 16.187162" ;# -$ns_ at 55.045844 "$node_(47) setdest 2560.000000 10.000000 14.265643" ;# -$ns_ at 55.290162 "$node_(7) setdest 3803.495480 2449.173521 12.392857" ;# -$ns_ at 56.072495 "$node_(11) setdest 245.000000 2244.000000 15.870723" ;# -$ns_ at 56.076454 "$node_(22) setdest 1980.000000 2190.000000 17.646729" ;# -$ns_ at 56.901083 "$node_(5) setdest 429.306930 3010.000000 15.589882" ;# -$ns_ at 57.948609 "$node_(5) switch OFF" ;# leaving_area -#$ns_ at 57.020000 $node_(70) arrived_to 3930.000000 210.000000 -$ns_ at 57.020000 "$node_(70) switch OFF" ;# arrived_to -$ns_ at 58.020000 "$node_(70) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 58.030000 "$node_(70) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 0.0 "$node_(76) switch OFF" ;# set_X,Y,Z -$node_(76) set X_ 0.000000 -$node_(76) set Y_ 0.000000 -$node_(76) set Z_ 0.0 -$ns_ at 68.010000 "$node_(76) setdest 3838.461538 3010.000000 1000000000.000000" ;# init_node -$ns_ at 68.020000 "$node_(76) switch ON" ;# inside -$ns_ at 68.020000 "$node_(76) setdest 3800.000000 2970.000000 27.745675" ;# -$ns_ at 58.020000 "$node_(2) setdest 10.000000 2297.153203 27.467800" ;# -$ns_ at 66.791588 "$node_(2) switch OFF" ;# leaving_area -$ns_ at 58.020000 "$node_(28) setdest 1749.929190 1783.886705 13.873502" ;# -$ns_ at 58.020000 "$node_(63) setdest 3310.000000 327.330076 13.636364" ;# -$ns_ at 58.020000 "$node_(23) setdest 2196.975090 2362.303748 14.877269" ;# -$ns_ at 58.353920 "$node_(24) setdest 3860.098415 949.791769 15.165341" ;# -$ns_ at 58.755457 "$node_(52) setdest 2735.000000 3010.000000 16.082464" ;# -$ns_ at 71.416836 "$node_(52) switch OFF" ;# leaving_area -$ns_ at 0.0 "$node_(77) switch OFF" ;# set_X,Y,Z -$node_(77) set X_ 0.000000 -$node_(77) set Y_ 0.000000 -$node_(77) set Z_ 0.0 -$ns_ at 86.590419 "$node_(77) setdest 3511.136363 10.000000 1000000000.000000" ;# init_node -$ns_ at 86.600419 "$node_(77) switch ON" ;# inside -$ns_ at 86.600419 "$node_(77) setdest 3507.896464 12.416196 13.163994" ;# -$ns_ at 59.318759 "$node_(27) setdest 2209.659280 2010.988013 16.467044" ;# -$ns_ at 59.721921 "$node_(19) setdest 1860.000000 1960.000000 13.498673" ;# -$ns_ at 0.0 "$node_(78) switch OFF" ;# set_X,Y,Z -$node_(78) set X_ 0.000000 -$node_(78) set Y_ 0.000000 -$node_(78) set Z_ 0.0 -$ns_ at 76.468432 "$node_(78) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 76.478432 "$node_(78) switch ON" ;# inside -$ns_ at 76.478432 "$node_(78) setdest 3310.000000 160.000000 12.839810" ;# -$ns_ at 61.232236 "$node_(53) setdest 1071.000000 2103.000000 17.421516" ;# -$ns_ at 61.621042 "$node_(56) setdest 2898.815759 77.763152 19.400182" ;# -$ns_ at 61.696874 "$node_(37) setdest 2510.000000 1290.000000 11.940049" ;# -$ns_ at 62.020000 "$node_(13) setdest 1100.568594 791.502028 13.103689" ;# -$ns_ at 62.691820 "$node_(51) setdest 1742.898093 1981.223793 16.364369" ;# -$ns_ at 62.836730 "$node_(26) setdest 3090.000000 2030.000000 12.808911" ;# -$ns_ at 63.507618 "$node_(39) setdest 3058.719372 408.975498 14.499594" ;# -$ns_ at 0.0 "$node_(79) switch OFF" ;# set_X,Y,Z -$node_(79) set X_ 0.000000 -$node_(79) set Y_ 0.000000 -$node_(79) set Z_ 0.0 -$ns_ at 73.701755 "$node_(79) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 73.711755 "$node_(79) switch ON" ;# inside -$ns_ at 73.711755 "$node_(79) setdest 3310.000000 160.000000 12.355081" ;# -$ns_ at 65.020000 "$node_(45) setdest 1433.581205 2037.285029 16.364369" ;# -#$ns_ at 66.020000 $node_(47) arrived_to 2560.000000 10.000000 -$ns_ at 66.020000 "$node_(47) switch OFF" ;# arrived_to -$ns_ at 67.020000 "$node_(47) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 67.030000 "$node_(47) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 66.072048 "$node_(33) setdest 3310.000000 610.000000 14.640790" ;# -$ns_ at 67.020000 "$node_(41) setdest 3303.787354 737.359240 13.682917" ;# -$ns_ at 67.233448 "$node_(69) setdest 3310.000000 480.277751 15.860949" ;# -$ns_ at 67.737571 "$node_(38) setdest 3090.000000 2030.000000 12.945212" ;# -$ns_ at 67.817144 "$node_(66) setdest 1290.000000 1090.000000 16.086701" ;# -#$ns_ at 68.020000 $node_(22) arrived_to 1980.000000 2190.000000 -$ns_ at 68.020000 "$node_(22) switch OFF" ;# arrived_to -$ns_ at 69.020000 "$node_(22) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 69.030000 "$node_(22) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 68.020000 "$node_(36) setdest 2035.070740 1779.542468 13.169265" ;# -$ns_ at 69.020000 "$node_(73) setdest 3310.000000 610.000000 13.636364" ;# -$ns_ at 70.020000 "$node_(4) setdest 10.000000 2297.153203 26.882564" ;# -$ns_ at 78.982546 "$node_(4) switch OFF" ;# leaving_area -$ns_ at 70.290872 "$node_(63) setdest 3310.000000 393.291200 15.612614" ;# -$ns_ at 71.020000 "$node_(76) setdest 3682.872943 2725.985298 18.171700" ;# -$ns_ at 71.020000 "$node_(65) setdest 3310.000000 249.628909 15.700741" ;# -$ns_ at 71.020000 "$node_(44) setdest 1860.000000 1960.000000 13.727766" ;# -$ns_ at 0.0 "$node_(80) switch OFF" ;# set_X,Y,Z -$node_(80) set X_ 0.000000 -$node_(80) set Y_ 0.000000 -$node_(80) set Z_ 0.0 -$ns_ at 77.881324 "$node_(80) setdest 3511.136363 10.000000 1000000000.000000" ;# init_node -$ns_ at 77.891324 "$node_(80) switch ON" ;# inside -$ns_ at 77.891324 "$node_(80) setdest 3310.000000 160.000000 14.648535" ;# -$ns_ at 72.020000 "$node_(8) setdest 3803.933314 2383.936182 12.715764" ;# -$ns_ at 72.020000 "$node_(61) setdest 1071.000000 2103.000000 16.632495" ;# -$ns_ at 72.239299 "$node_(56) setdest 2849.588535 67.917707 19.419495" ;# -$ns_ at 72.348937 "$node_(20) setdest 3800.000000 2970.000000 14.850716" ;# -$ns_ at 72.627130 "$node_(69) setdest 3310.000000 610.000000 12.481851" ;# -$ns_ at 72.989630 "$node_(28) setdest 1710.732502 1721.172003 15.240545" ;# -#$ns_ at 73.020000 $node_(15) arrived_to 1071.000000 2103.000000 -$ns_ at 73.020000 "$node_(15) switch OFF" ;# arrived_to -$ns_ at 74.020000 "$node_(15) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 74.030000 "$node_(15) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 73.020000 "$node_(11) setdest 10.000000 2297.153203 32.054187" ;# -$ns_ at 80.536529 "$node_(11) switch OFF" ;# leaving_area -#$ns_ at 73.020000 $node_(64) arrived_to 3310.000000 610.000000 -$ns_ at 73.020000 "$node_(64) switch OFF" ;# arrived_to -$ns_ at 74.020000 "$node_(64) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 74.030000 "$node_(64) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 73.513269 "$node_(39) setdest 3310.000000 610.000000 13.130931" ;# -$ns_ at 73.790965 "$node_(60) setdest 2288.942757 1949.189106 16.467044" ;# -#$ns_ at 74.020000 $node_(35) arrived_to 960.000000 570.000000 -$ns_ at 74.020000 "$node_(35) switch OFF" ;# arrived_to -$ns_ at 75.020000 "$node_(35) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 75.030000 "$node_(35) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 74.515733 "$node_(63) setdest 3310.000000 610.000000 13.130472" ;# -$ns_ at 74.824440 "$node_(56) setdest 2560.000000 10.000000 16.230527" ;# -$ns_ at 75.020000 "$node_(67) setdest 3310.000000 377.483559 13.636364" ;# -$ns_ at 75.168046 "$node_(68) setdest 1429.744513 830.474476 16.589689" ;# -#$ns_ at 76.020000 $node_(72) arrived_to 100.000000 470.000000 -$ns_ at 76.020000 "$node_(72) switch OFF" ;# arrived_to -$ns_ at 77.020000 "$node_(72) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 77.030000 "$node_(72) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 76.020000 "$node_(58) setdest 1071.000000 2103.000000 16.364369" ;# -$ns_ at 76.338969 "$node_(41) setdest 3298.983616 835.835864 15.904662" ;# -$ns_ at 76.643591 "$node_(23) setdest 2382.278109 2509.456145 18.587284" ;# -$ns_ at 76.728578 "$node_(65) setdest 3310.000000 610.000000 13.204556" ;# -$ns_ at 76.952393 "$node_(24) setdest 3810.000000 1480.000000 12.659855" ;# -$ns_ at 77.204488 "$node_(16) setdest 3800.000000 2970.000000 13.831303" ;# -$ns_ at 77.402569 "$node_(49) setdest 2082.185204 1730.978328 15.039381" ;# -$ns_ at 77.842223 "$node_(28) setdest 1610.000000 1560.000000 13.405608" ;# -#$ns_ at 78.020000 $node_(43) arrived_to 4660.000000 400.000000 -$ns_ at 78.020000 "$node_(43) switch OFF" ;# arrived_to -$ns_ at 79.020000 "$node_(43) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 79.030000 "$node_(43) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 79.020000 $node_(18) arrived_to 245.000000 2244.000000 -$ns_ at 79.020000 "$node_(18) switch OFF" ;# arrived_to -$ns_ at 80.020000 "$node_(18) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 80.030000 "$node_(18) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 79.020000 "$node_(50) setdest 2232.243741 1576.302606 12.801209" ;# -$ns_ at 79.020000 "$node_(33) setdest 3068.928899 814.910436 12.447342" ;# -$ns_ at 80.067320 "$node_(62) setdest 1290.000000 1090.000000 18.615038" ;# -$ns_ at 0.0 "$node_(81) switch OFF" ;# set_X,Y,Z -$node_(81) set X_ 0.000000 -$node_(81) set Y_ 0.000000 -$node_(81) set Z_ 0.0 -$ns_ at 81.503502 "$node_(81) setdest 3917.755102 10.000000 1000000000.000000" ;# init_node -$ns_ at 81.513502 "$node_(81) switch ON" ;# inside -$ns_ at 81.513502 "$node_(81) setdest 3930.000000 210.000000 12.921969" ;# -$ns_ at 80.946077 "$node_(27) setdest 1980.000000 2190.000000 18.115363" ;# -$ns_ at 81.020000 "$node_(48) setdest 3838.461538 3010.000000 29.888688" ;# -$ns_ at 82.876600 "$node_(48) switch OFF" ;# leaving_area -$ns_ at 81.020000 "$node_(19) setdest 1071.000000 2103.000000 16.364369" ;# -$ns_ at 81.649008 "$node_(51) setdest 1860.000000 1960.000000 18.679926" ;# -$ns_ at 82.538014 "$node_(41) setdest 3290.000000 1020.000000 12.731894" ;# -#$ns_ at 83.020000 $node_(31) arrived_to 3810.000000 1480.000000 -$ns_ at 83.020000 "$node_(31) switch OFF" ;# arrived_to -$ns_ at 84.020000 "$node_(31) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 84.030000 "$node_(31) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 0.0 "$node_(82) switch OFF" ;# set_X,Y,Z -$node_(82) set X_ 0.000000 -$node_(82) set Y_ 0.000000 -$node_(82) set Z_ 0.0 -$ns_ at 89.213655 "$node_(82) setdest 3511.136363 10.000000 1000000000.000000" ;# init_node -$ns_ at 89.223655 "$node_(82) switch ON" ;# inside -$ns_ at 89.223655 "$node_(82) setdest 3310.000000 160.000000 13.348873" ;# -$ns_ at 0.0 "$node_(83) switch OFF" ;# set_X,Y,Z -$node_(83) set X_ 0.000000 -$node_(83) set Y_ 0.000000 -$node_(83) set Z_ 0.0 -$ns_ at 111.088639 "$node_(83) setdest 565.476191 10.000000 1000000000.000000" ;# init_node -$ns_ at 111.098639 "$node_(83) switch ON" ;# inside -$ns_ at 111.098639 "$node_(83) setdest 100.000000 470.000000 12.851619" ;# -$ns_ at 84.020000 "$node_(69) setdest 2946.763505 918.751021 13.460928" ;# -$ns_ at 84.020000 "$node_(53) setdest 759.665364 2156.145501 18.893733" ;# -$ns_ at 85.020000 "$node_(55) setdest 2660.000000 2730.000000 11.101662" ;# -$ns_ at 85.192685 "$node_(21) setdest 2510.000000 1290.000000 12.947158" ;# -$ns_ at 85.574748 "$node_(49) setdest 1860.000000 1960.000000 12.540179" ;# -$ns_ at 85.915106 "$node_(76) setdest 3471.121930 2284.837355 16.045433" ;# -$ns_ at 86.907442 "$node_(77) setdest 3429.356254 70.988556 15.578326" ;# -$ns_ at 87.020000 "$node_(57) setdest 2948.388016 917.370186 13.815163" ;# -$ns_ at 87.921266 "$node_(1) setdest 2510.000000 1290.000000 14.806388" ;# -#$ns_ at 88.020000 $node_(26) arrived_to 3090.000000 2030.000000 -$ns_ at 88.020000 "$node_(26) switch OFF" ;# arrived_to -$ns_ at 89.020000 "$node_(26) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 89.030000 "$node_(26) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 88.999624 "$node_(13) setdest 1031.332476 682.402690 14.209679" ;# -#$ns_ at 89.020000 $node_(12) arrived_to 2660.000000 2730.000000 -$ns_ at 89.020000 "$node_(12) switch OFF" ;# arrived_to -$ns_ at 90.020000 "$node_(12) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 90.030000 "$node_(12) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 89.020000 "$node_(51) setdest 1980.000000 2190.000000 13.653812" ;# -$ns_ at 89.374028 "$node_(23) setdest 2507.500076 2608.897119 18.743439" ;# -$ns_ at 90.020000 "$node_(75) setdest 3064.341849 413.473479 13.129175" ;# -$ns_ at 90.367268 "$node_(7) setdest 3801.239648 2785.292469 16.164570" ;# -$ns_ at 90.968794 "$node_(67) setdest 3310.000000 427.728101 15.991769" ;# -$ns_ at 91.502283 "$node_(45) setdest 1369.887024 2048.829094 18.088682" ;# -$ns_ at 91.713123 "$node_(29) setdest 2510.000000 1290.000000 14.674077" ;# -$ns_ at 92.020000 "$node_(63) setdest 3044.881012 835.351140 13.124405" ;# -$ns_ at 0.0 "$node_(84) switch OFF" ;# set_X,Y,Z -$node_(84) set X_ 0.000000 -$node_(84) set Y_ 0.000000 -$node_(84) set Z_ 0.0 -$ns_ at 98.711006 "$node_(84) setdest 3511.136364 10.000000 1000000000.000000" ;# init_node -$ns_ at 98.721006 "$node_(84) switch ON" ;# inside -$ns_ at 98.721006 "$node_(84) setdest 3466.202399 43.510075 15.509769" ;# -#$ns_ at 93.020000 $node_(28) arrived_to 1610.000000 1560.000000 -$ns_ at 93.020000 "$node_(28) switch OFF" ;# arrived_to -$ns_ at 94.020000 "$node_(28) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 94.030000 "$node_(28) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 93.196690 "$node_(77) setdest 3310.000000 160.000000 12.593125" ;# -#$ns_ at 94.020000 $node_(56) arrived_to 2560.000000 10.000000 -$ns_ at 94.020000 "$node_(56) switch OFF" ;# arrived_to -$ns_ at 95.020000 "$node_(56) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 95.030000 "$node_(56) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 94.110694 "$node_(67) setdest 3310.000000 610.000000 13.104314" ;# -$ns_ at 95.020000 "$node_(79) setdest 3310.000000 326.832286 12.456113" ;# -$ns_ at 95.080867 "$node_(45) setdest 1071.000000 2103.000000 16.038557" ;# -$ns_ at 0.0 "$node_(85) switch OFF" ;# set_X,Y,Z -$node_(85) set X_ 0.000000 -$node_(85) set Y_ 0.000000 -$node_(85) set Z_ 0.0 -$ns_ at 107.010001 "$node_(85) setdest 2560.000000 10.000000 1000000000.000000" ;# init_node -$ns_ at 107.020001 "$node_(85) switch ON" ;# inside -$ns_ at 107.020001 "$node_(85) setdest 2560.000000 10.000000 15.432186" ;# -$ns_ at 96.020000 "$node_(80) setdest 3310.000000 264.084004 14.479894" ;# -#$ns_ at 96.020000 $node_(62) arrived_to 1290.000000 1090.000000 -$ns_ at 96.020000 "$node_(62) switch OFF" ;# arrived_to -$ns_ at 97.020000 "$node_(62) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 97.030000 "$node_(62) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 97.020000 "$node_(78) setdest 2873.391011 72.678202 15.284245" ;# -$ns_ at 97.905187 "$node_(23) setdest 2660.000000 2730.000000 14.848559" ;# -$ns_ at 98.020000 "$node_(41) setdest 3207.358318 1437.340495 15.535574" ;# -$ns_ at 98.020000 "$node_(27) setdest 851.301630 2786.850971 16.620014" ;# -$ns_ at 98.020000 "$node_(81) setdest 4246.010292 292.249254 10.932187" ;# -$ns_ at 98.093016 "$node_(13) setdest 960.000000 570.000000 12.183288" ;# -$ns_ at 99.020000 "$node_(10) setdest 825.195870 2144.959301 18.438249" ;# -$ns_ at 99.020000 "$node_(38) setdest 2867.393542 2392.382607 10.669130" ;# -$ns_ at 99.020000 "$node_(39) setdest 3290.000000 1020.000000 13.682917" ;# -$ns_ at 100.020000 "$node_(16) setdest 3802.644628 3010.000000 14.410845" ;# -$ns_ at 102.801747 "$node_(16) switch OFF" ;# leaving_area -$ns_ at 100.176928 "$node_(68) setdest 1290.000000 1090.000000 17.500228" ;# -$ns_ at 100.736553 "$node_(53) setdest 245.000000 2244.000000 15.229216" ;# -$ns_ at 101.471866 "$node_(60) setdest 1980.000000 2190.000000 18.178300" ;# -$ns_ at 102.335078 "$node_(84) setdest 3310.000000 160.000000 12.423179" ;# -$ns_ at 103.020000 "$node_(20) setdest 3838.461538 3010.000000 31.691224" ;# -$ns_ at 104.771001 "$node_(20) switch OFF" ;# leaving_area -$ns_ at 103.020000 "$node_(73) setdest 3301.533898 783.555084 13.682917" ;# -$ns_ at 103.208174 "$node_(80) setdest 3310.000000 610.000000 13.401455" ;# -$ns_ at 104.438397 "$node_(33) setdest 2879.338395 976.062364 14.543216" ;# -$ns_ at 105.020000 "$node_(37) setdest 2261.715038 1545.924499 12.202857" ;# -$ns_ at 105.020000 "$node_(65) setdest 3301.141878 791.591494 13.682917" ;# -$ns_ at 106.020000 "$node_(77) setdest 3310.000000 406.827472 12.451045" ;# -$ns_ at 108.020000 "$node_(85) setdest 3055.111374 406.089099 12.993422" ;# -$ns_ at 108.413608 "$node_(79) setdest 3310.000000 478.314095 13.636364" ;# -$ns_ at 109.020000 "$node_(51) setdest 2123.704561 2304.118328 17.343151" ;# -$ns_ at 109.020000 "$node_(67) setdest 3300.899735 796.555442 13.682917" ;# -$ns_ at 109.020000 "$node_(82) setdest 3310.000000 510.344385 13.220467" ;# -$ns_ at 110.020000 "$node_(21) setdest 2052.051993 1762.038715 13.218839" ;# -#$ns_ at 110.020000 $node_(13) arrived_to 960.000000 570.000000 -$ns_ at 110.020000 "$node_(13) switch OFF" ;# arrived_to -$ns_ at 111.020000 "$node_(13) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 111.030000 "$node_(13) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 110.020000 "$node_(66) setdest 1390.631497 1237.802511 13.489251" ;# -$ns_ at 110.180777 "$node_(50) setdest 2018.905962 1796.204624 13.528813" ;# -$ns_ at 0.0 "$node_(86) switch OFF" ;# set_X,Y,Z -$node_(86) set X_ 0.000000 -$node_(86) set Y_ 0.000000 -$node_(86) set Z_ 0.0 -$ns_ at 116.580034 "$node_(86) setdest 1871.538461 10.000000 1000000000.000000" ;# init_node -$ns_ at 116.590034 "$node_(86) switch ON" ;# inside -$ns_ at 116.590034 "$node_(86) setdest 1595.895451 521.908448 16.360244" ;# -$ns_ at 111.161296 "$node_(7) setdest 3800.000000 2970.000000 15.576043" ;# -$ns_ at 112.020000 "$node_(49) setdest 1447.048442 2034.844199 16.364369" ;# -$ns_ at 112.020000 "$node_(23) setdest 2735.000000 3010.000000 16.564038" ;# -$ns_ at 129.520000 "$node_(23) switch OFF" ;# leaving_area -$ns_ at 112.544044 "$node_(10) setdest 245.000000 2244.000000 15.705761" ;# -$ns_ at 115.020000 "$node_(45) setdest 800.877206 2149.110550 15.532960" ;# -$ns_ at 115.719153 "$node_(73) setdest 3298.548961 844.746298 14.406345" ;# -$ns_ at 116.412026 "$node_(76) setdest 3315.478202 1960.579587 18.536554" ;# -$ns_ at 118.020000 "$node_(68) setdest 398.108304 1287.662484 16.621823" ;# -$ns_ at 118.307183 "$node_(65) setdest 3299.114853 833.145514 14.465543" ;# -$ns_ at 118.513219 "$node_(74) setdest 1290.000000 1090.000000 18.012730" ;# -$ns_ at 118.531898 "$node_(63) setdest 2958.817947 908.504745 14.362559" ;# -$ns_ at 119.020000 "$node_(61) setdest 747.339233 2158.249598 16.430355" ;# -#$ns_ at 119.020000 $node_(84) arrived_to 3310.000000 160.000000 -$ns_ at 119.020000 "$node_(84) switch OFF" ;# arrived_to -$ns_ at 120.020000 "$node_(84) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 120.030000 "$node_(84) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 119.435558 "$node_(69) setdest 2773.538937 1065.991904 14.458335" ;# -$ns_ at 119.522273 "$node_(79) setdest 3310.000000 610.000000 15.496606" ;# -$ns_ at 119.600819 "$node_(51) setdest 2660.000000 2730.000000 16.144277" ;# -$ns_ at 119.812016 "$node_(36) setdest 1860.000000 1960.000000 15.512436" ;# -$ns_ at 119.971721 "$node_(73) setdest 3290.000000 1020.000000 13.447144" ;# -$ns_ at 120.020000 "$node_(24) setdest 3808.480944 1706.339332 14.637236" ;# -$ns_ at 120.020000 "$node_(1) setdest 2405.157699 1398.068218 14.457381" ;# -$ns_ at 121.183219 "$node_(65) setdest 3290.000000 1020.000000 13.520245" ;# -$ns_ at 121.373138 "$node_(57) setdest 2805.464211 1038.855421 15.476236" ;# -$ns_ at 121.547835 "$node_(33) setdest 2831.663988 1016.585611 14.964355" ;# -$ns_ at 122.670398 "$node_(67) setdest 3297.875780 858.546515 15.283891" ;# -$ns_ at 123.275587 "$node_(66) setdest 1517.151500 1423.628766 12.841373" ;# -$ns_ at 124.020000 "$node_(60) setdest 1269.458678 2565.731275 14.975446" ;# -#$ns_ at 124.020000 $node_(71) arrived_to 1290.000000 1090.000000 -$ns_ at 124.020000 "$node_(71) switch OFF" ;# arrived_to -$ns_ at 125.020000 "$node_(71) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 125.030000 "$node_(71) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 124.020000 "$node_(7) setdest 3838.461538 3010.000000 27.745675" ;# -$ns_ at 126.020000 "$node_(7) switch OFF" ;# leaving_area -$ns_ at 125.020000 "$node_(29) setdest 2314.893745 1491.109525 12.787508" ;# -$ns_ at 125.405158 "$node_(41) setdest 3090.000000 2030.000000 12.688636" ;# -$ns_ at 125.729092 "$node_(33) setdest 2510.000000 1290.000000 13.073798" ;# -$ns_ at 125.843836 "$node_(77) setdest 3310.000000 610.000000 15.419704" ;# -$ns_ at 126.020000 "$node_(58) setdest 764.196652 2155.372000 16.430355" ;# -$ns_ at 126.151669 "$node_(78) setdest 2560.000000 10.000000 18.946593" ;# -$ns_ at 126.396280 "$node_(63) setdest 2510.000000 1290.000000 12.910978" ;# -$ns_ at 126.731196 "$node_(67) setdest 3290.000000 1020.000000 13.153880" ;# -$ns_ at 0.0 "$node_(87) switch OFF" ;# set_X,Y,Z -$node_(87) set X_ 0.000000 -$node_(87) set Y_ 0.000000 -$node_(87) set Z_ 0.0 -$ns_ at 140.829201 "$node_(87) setdest 1871.538461 10.000000 1000000000.000000" ;# init_node -$ns_ at 140.839201 "$node_(87) switch ON" ;# inside -$ns_ at 140.839201 "$node_(87) setdest 1864.515162 23.043270 18.081091" ;# -$ns_ at 127.889465 "$node_(81) setdest 4348.345188 318.884364 12.272889" ;# -$ns_ at 129.020000 "$node_(79) setdest 3296.280996 891.239581 13.369011" ;# -$ns_ at 130.020000 "$node_(80) setdest 2871.249270 982.938121 13.608044" ;# -$ns_ at 130.020000 "$node_(39) setdest 3195.904728 1495.181122 15.338174" ;# -$ns_ at 130.434594 "$node_(1) setdest 1860.000000 1960.000000 13.363744" ;# -$ns_ at 131.020000 "$node_(19) setdest 245.000000 2244.000000 16.430355" ;# -$ns_ at 132.661848 "$node_(45) setdest 576.051317 2187.488819 17.655915" ;# -$ns_ at 132.827402 "$node_(50) setdest 1860.000000 1960.000000 15.021165" ;# -$ns_ at 0.0 "$node_(88) switch OFF" ;# set_X,Y,Z -$node_(88) set X_ 0.000000 -$node_(88) set Y_ 0.000000 -$node_(88) set Z_ 0.0 -$ns_ at 157.137696 "$node_(88) setdest 565.476191 10.000000 1000000000.000000" ;# init_node -$ns_ at 157.147696 "$node_(88) switch ON" ;# inside -$ns_ at 157.147696 "$node_(88) setdest 447.380636 126.706195 12.862592" ;# -$ns_ at 133.493591 "$node_(57) setdest 2510.000000 1290.000000 13.133300" ;# -$ns_ at 134.020000 "$node_(73) setdest 3245.511748 1080.352279 17.620032" ;# -$ns_ at 134.240277 "$node_(37) setdest 2044.074180 1770.261999 16.010145" ;# -$ns_ at 135.159840 "$node_(69) setdest 2510.000000 1290.000000 12.877033" ;# -$ns_ at 135.483604 "$node_(24) setdest 3805.479210 2153.597670 12.883208" ;# -$ns_ at 135.520151 "$node_(82) setdest 3310.000000 610.000000 15.331992" ;# -$ns_ at 135.815726 "$node_(76) setdest 3032.000000 1370.000000 15.898616" ;# -$ns_ at 136.020000 "$node_(53) setdest 10.000000 2297.153203 27.467800" ;# -$ns_ at 144.791588 "$node_(53) switch OFF" ;# leaving_area -$ns_ at 136.020000 "$node_(65) setdest 3201.793172 1465.444479 13.547521" ;# -$ns_ at 136.505555 "$node_(81) setdest 4660.000000 400.000000 10.553625" ;# -$ns_ at 137.020000 "$node_(36) setdest 1533.412123 2019.191466 16.364369" ;# -$ns_ at 137.665915 "$node_(49) setdest 1399.568575 2043.449549 17.235207" ;# -$ns_ at 138.275233 "$node_(73) setdest 3032.000000 1370.000000 15.820675" ;# -$ns_ at 138.882085 "$node_(38) setdest 2791.267225 2516.309168 11.748791" ;# -$ns_ at 139.003897 "$node_(61) setdest 532.623433 2194.902053 18.223602" ;# -$ns_ at 139.213699 "$node_(75) setdest 3310.000000 610.000000 15.120226" ;# -$ns_ at 140.020000 "$node_(44) setdest 1271.772161 2066.611636 15.916303" ;# -$ns_ at 140.020000 "$node_(77) setdest 2885.061120 971.198048 13.815163" ;# -$ns_ at 140.020000 "$node_(67) setdest 3207.216219 1438.058096 13.371579" ;# -$ns_ at 140.465614 "$node_(49) setdest 1071.000000 2103.000000 16.245753" ;# -$ns_ at 140.782139 "$node_(66) setdest 1586.789557 1525.909662 16.225247" ;# -#$ns_ at 141.020000 $node_(74) arrived_to 1290.000000 1090.000000 -$ns_ at 141.020000 "$node_(74) switch OFF" ;# arrived_to -$ns_ at 142.020000 "$node_(74) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 142.030000 "$node_(74) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 141.658508 "$node_(87) setdest 1290.000000 1090.000000 16.296098" ;# -$ns_ at 143.020000 "$node_(82) setdest 3032.404943 845.955798 13.815163" ;# -$ns_ at 143.109439 "$node_(8) setdest 3800.000000 2970.000000 15.062159" ;# -#$ns_ at 144.020000 $node_(78) arrived_to 2560.000000 10.000000 -$ns_ at 144.020000 "$node_(78) switch OFF" ;# arrived_to -$ns_ at 145.020000 "$node_(78) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 145.030000 "$node_(78) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 0.0 "$node_(89) switch OFF" ;# set_X,Y,Z -$node_(89) set X_ 0.000000 -$node_(89) set Y_ 0.000000 -$node_(89) set Z_ 0.0 -$ns_ at 153.222693 "$node_(89) setdest 565.476191 10.000000 1000000000.000000" ;# init_node -$ns_ at 153.232693 "$node_(89) switch ON" ;# inside -$ns_ at 153.232693 "$node_(89) setdest 344.127931 228.744163 13.735993" ;# -$ns_ at 144.963064 "$node_(58) setdest 611.323732 2181.467741 17.409286" ;# -$ns_ at 145.579785 "$node_(45) setdest 496.265112 2201.108498 18.301437" ;# -$ns_ at 146.931933 "$node_(29) setdest 2187.073134 1622.863078 14.945523" ;# -$ns_ at 148.408339 "$node_(66) setdest 1610.000000 1560.000000 15.791359" ;# -$ns_ at 149.020000 "$node_(50) setdest 1566.539209 2013.187444 15.277260" ;# -$ns_ at 150.002406 "$node_(45) setdest 245.000000 2244.000000 15.913730" ;# -$ns_ at 150.081692 "$node_(79) setdest 3290.000000 1020.000000 14.422586" ;# -$ns_ at 150.956620 "$node_(61) setdest 245.000000 2244.000000 15.305991" ;# -$ns_ at 151.020000 "$node_(10) setdest 10.000000 2297.153203 27.031537" ;# -$ns_ at 159.933153 "$node_(10) switch OFF" ;# leaving_area -$ns_ at 151.261294 "$node_(38) setdest 2660.000000 2730.000000 10.129306" ;# -$ns_ at 152.020000 "$node_(66) setdest 1686.208867 1681.934187 14.721891" ;# -$ns_ at 152.127578 "$node_(86) setdest 1424.637256 839.959382 15.416120" ;# -$ns_ at 0.0 "$node_(90) switch OFF" ;# set_X,Y,Z -$node_(90) set X_ 0.000000 -$node_(90) set Y_ 0.000000 -$node_(90) set Z_ 0.0 -$ns_ at 169.168944 "$node_(90) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 169.178944 "$node_(90) switch ON" ;# inside -$ns_ at 169.178944 "$node_(90) setdest 1629.907162 458.743842 15.463030" ;# -$ns_ at 153.763009 "$node_(37) setdest 1981.588388 1834.670431 14.570408" ;# -$ns_ at 153.871196 "$node_(58) setdest 245.000000 2244.000000 16.053642" ;# -$ns_ at 0.0 "$node_(91) switch OFF" ;# set_X,Y,Z -$node_(91) set X_ 0.000000 -$node_(91) set Y_ 0.000000 -$node_(91) set Z_ 0.0 -$ns_ at 170.418030 "$node_(91) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 170.428030 "$node_(91) switch ON" ;# inside -$ns_ at 170.428030 "$node_(91) setdest 1630.537227 457.573722 16.216624" ;# -$ns_ at 156.817916 "$node_(85) setdest 3310.000000 610.000000 14.702074" ;# -$ns_ at 157.302391 "$node_(36) setdest 1393.080306 2044.625496 17.971882" ;# -$ns_ at 159.020000 "$node_(33) setdest 1860.000000 1960.000000 13.528813" ;# -$ns_ at 159.214389 "$node_(29) setdest 1860.000000 1960.000000 12.104470" ;# -$ns_ at 159.772887 "$node_(21) setdest 1860.000000 1960.000000 15.115415" ;# -$ns_ at 159.921934 "$node_(37) setdest 1860.000000 1960.000000 13.331542" ;# -#$ns_ at 160.020000 $node_(55) arrived_to 2660.000000 2730.000000 -$ns_ at 160.020000 "$node_(55) switch OFF" ;# arrived_to -$ns_ at 161.020000 "$node_(55) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 161.030000 "$node_(55) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 160.020000 "$node_(79) setdest 3244.927850 1081.144389 17.520934" ;# -$ns_ at 161.020000 "$node_(75) setdest 3298.796385 839.674115 13.400949" ;# -$ns_ at 161.601850 "$node_(39) setdest 3090.000000 2030.000000 12.557045" ;# -$ns_ at 161.787129 "$node_(66) setdest 1860.000000 1960.000000 13.531556" ;# -$ns_ at 162.020000 "$node_(73) setdest 2448.642014 1824.708696 16.241331" ;# -$ns_ at 162.020000 "$node_(49) setdest 245.000000 2244.000000 16.430355" ;# -$ns_ at 163.020000 "$node_(51) setdest 2841.276329 2784.804471 15.762089" ;# -$ns_ at 163.020000 "$node_(69) setdest 2192.066548 1617.716019 12.965112" ;# -#$ns_ at 163.020000 $node_(83) arrived_to 100.000000 470.000000 -$ns_ at 163.020000 "$node_(83) switch OFF" ;# arrived_to -$ns_ at 164.020000 "$node_(83) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 164.030000 "$node_(83) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 164.020000 "$node_(57) setdest 2196.107831 1613.550389 14.321469" ;# -$ns_ at 164.355465 "$node_(79) setdest 3032.000000 1370.000000 15.833262" ;# -$ns_ at 165.238012 "$node_(36) setdest 1071.000000 2103.000000 15.750539" ;# -#$ns_ at 167.020000 $node_(45) arrived_to 245.000000 2244.000000 -$ns_ at 167.020000 "$node_(45) switch OFF" ;# arrived_to -$ns_ at 168.020000 "$node_(45) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 168.030000 "$node_(45) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 168.020000 $node_(81) arrived_to 4660.000000 400.000000 -$ns_ at 168.020000 "$node_(81) switch OFF" ;# arrived_to -$ns_ at 169.020000 "$node_(81) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 169.030000 "$node_(81) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 168.541939 "$node_(50) setdest 1303.139455 2060.926563 17.773443" ;# -$ns_ at 169.391530 "$node_(82) setdest 2894.107066 963.508994 14.864930" ;# -$ns_ at 169.538594 "$node_(65) setdest 3168.634794 1632.894289 14.854433" ;# -$ns_ at 170.055887 "$node_(88) setdest 359.817155 213.239517 15.485932" ;# -$ns_ at 170.200765 "$node_(24) setdest 3803.601631 2433.357008 15.356627" ;# -#$ns_ at 171.020000 $node_(61) arrived_to 245.000000 2244.000000 -$ns_ at 171.020000 "$node_(61) switch OFF" ;# arrived_to -$ns_ at 172.020000 "$node_(61) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 172.030000 "$node_(61) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 0.0 "$node_(92) switch OFF" ;# set_X,Y,Z -$node_(92) set X_ 0.000000 -$node_(92) set Y_ 0.000000 -$node_(92) set Z_ 0.0 -$ns_ at 186.522795 "$node_(92) setdest 1871.538461 10.000000 1000000000.000000" ;# init_node -$ns_ at 186.532795 "$node_(92) switch ON" ;# inside -$ns_ at 186.532795 "$node_(92) setdest 1757.062373 222.598450 16.107106" ;# -$ns_ at 171.891756 "$node_(67) setdest 3158.620839 1683.464762 14.102316" ;# -$ns_ at 172.335722 "$node_(80) setdest 2604.125521 1209.993307 13.815163" ;# -$ns_ at 172.979814 "$node_(68) setdest 40.534746 1366.908516 18.195136" ;# -$ns_ at 173.020000 "$node_(63) setdest 2347.931038 1457.055700 14.766618" ;# -$ns_ at 0.0 "$node_(93) switch OFF" ;# set_X,Y,Z -$node_(93) set X_ 0.000000 -$node_(93) set Y_ 0.000000 -$node_(93) set Z_ 0.0 -$ns_ at 207.010001 "$node_(93) setdest 2560.000000 10.000000 1000000000.000000" ;# init_node -$ns_ at 207.020001 "$node_(93) switch ON" ;# inside -$ns_ at 207.020001 "$node_(93) setdest 2560.000000 10.000000 16.187162" ;# -#$ns_ at 174.020000 $node_(41) arrived_to 3090.000000 2030.000000 -$ns_ at 174.020000 "$node_(41) switch OFF" ;# arrived_to -$ns_ at 175.020000 "$node_(41) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 175.030000 "$node_(41) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 174.020000 $node_(37) arrived_to 1860.000000 1960.000000 -$ns_ at 174.020000 "$node_(37) switch OFF" ;# arrived_to -$ns_ at 175.020000 "$node_(37) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 175.030000 "$node_(37) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 174.842400 "$node_(27) setdest 625.319656 2906.349292 19.152866" ;# -$ns_ at 175.034880 "$node_(51) setdest 3007.934440 2835.189482 16.637835" ;# -$ns_ at 175.559423 "$node_(86) setdest 1290.000000 1090.000000 18.368335" ;# -$ns_ at 175.888338 "$node_(89) setdest 100.000000 470.000000 15.508288" ;# -#$ns_ at 177.020000 $node_(38) arrived_to 2660.000000 2730.000000 -$ns_ at 177.020000 "$node_(38) switch OFF" ;# arrived_to -$ns_ at 178.020000 "$node_(38) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 178.030000 "$node_(38) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 177.579667 "$node_(44) setdest 1071.000000 2103.000000 17.835412" ;# -$ns_ at 177.692389 "$node_(60) setdest 651.781274 2892.356499 16.620014" ;# -$ns_ at 178.005501 "$node_(88) setdest 100.000000 470.000000 13.039032" ;# -$ns_ at 178.020000 "$node_(76) setdest 3152.346236 1206.739603 16.104256" ;# -$ns_ at 178.020000 "$node_(58) setdest 46.380318 2288.924563 31.751156" ;# -$ns_ at 178.179025 "$node_(75) setdest 3293.177795 954.855207 13.682917" ;# -$ns_ at 179.020000 "$node_(21) setdest 1734.363809 1982.770564 17.710129" ;# -$ns_ at 180.020000 "$node_(85) setdest 2946.994541 918.554640 13.815163" ;# -$ns_ at 180.389193 "$node_(77) setdest 2733.002404 1100.447957 15.201584" ;# -$ns_ at 181.030197 "$node_(65) setdest 3090.000000 2030.000000 13.062893" ;# -$ns_ at 181.601997 "$node_(82) setdest 2510.000000 1290.000000 13.472597" ;# -$ns_ at 183.020000 "$node_(8) setdest 3802.644628 3010.000000 14.845359" ;# -$ns_ at 185.720327 "$node_(8) switch OFF" ;# leaving_area -$ns_ at 183.020000 "$node_(19) setdest 10.000000 2297.153203 32.044586" ;# -$ns_ at 190.538781 "$node_(19) switch OFF" ;# leaving_area -$ns_ at 183.603229 "$node_(50) setdest 1235.530927 2073.180073 17.527362" ;# -$ns_ at 184.433528 "$node_(58) setdest 10.000000 2297.153203 24.610297" ;# -$ns_ at 185.949125 "$node_(58) switch OFF" ;# leaving_area -$ns_ at 185.499459 "$node_(51) setdest 3090.000000 2860.000000 18.965428" ;# -$ns_ at 0.0 "$node_(94) switch OFF" ;# set_X,Y,Z -$node_(94) set X_ 0.000000 -$node_(94) set Y_ 0.000000 -$node_(94) set Z_ 0.0 -$ns_ at 200.082699 "$node_(94) setdest 1871.538462 10.000000 1000000000.000000" ;# init_node -$ns_ at 200.092699 "$node_(94) switch ON" ;# inside -$ns_ at 200.092699 "$node_(94) setdest 1847.554641 54.541381 17.755388" ;# -$ns_ at 186.229604 "$node_(21) setdest 1071.000000 2103.000000 16.132201" ;# -$ns_ at 186.606909 "$node_(75) setdest 3290.000000 1020.000000 14.779268" ;# -$ns_ at 187.020000 "$node_(66) setdest 1900.692120 2037.993230 15.154980" ;# -$ns_ at 187.020000 "$node_(36) setdest 719.708692 2162.966192 17.382919" ;# -$ns_ at 187.523384 "$node_(50) setdest 1071.000000 2103.000000 15.930028" ;# -$ns_ at 188.020000 "$node_(79) setdest 2665.592034 1655.603167 16.467044" ;# -$ns_ at 188.189331 "$node_(27) setdest 429.306931 3010.000000 15.771276" ;# -$ns_ at 202.248472 "$node_(27) switch OFF" ;# leaving_area -$ns_ at 188.418674 "$node_(24) setdest 3800.000000 2970.000000 12.597146" ;# -$ns_ at 188.782106 "$node_(63) setdest 2146.724027 1664.453696 12.991574" ;# -$ns_ at 189.631525 "$node_(67) setdest 3090.000000 2030.000000 12.898274" ;# -$ns_ at 190.020000 "$node_(44) setdest 776.761613 2153.227134 16.430355" ;# -$ns_ at 190.020000 "$node_(1) setdest 1071.000000 2103.000000 16.364369" ;# -$ns_ at 190.614373 "$node_(76) setdest 3199.271293 1143.081579 18.258249" ;# -#$ns_ at 191.020000 $node_(51) arrived_to 3090.000000 2860.000000 -$ns_ at 191.020000 "$node_(51) switch OFF" ;# arrived_to -$ns_ at 192.020000 "$node_(51) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 192.030000 "$node_(51) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 192.020000 "$node_(75) setdest 3216.505296 1119.702118 17.758994" ;# -$ns_ at 192.020000 "$node_(86) setdest 1610.000000 1560.000000 13.868165" ;# -$ns_ at 192.824720 "$node_(66) setdest 1980.000000 2190.000000 12.993435" ;# -$ns_ at 193.108798 "$node_(68) setdest 10.000000 1373.675676 15.807939" ;# -$ns_ at 195.087274 "$node_(68) switch OFF" ;# leaving_area -$ns_ at 193.517299 "$node_(77) setdest 2510.000000 1290.000000 13.006323" ;# -$ns_ at 194.945794 "$node_(76) setdest 3290.000000 1020.000000 15.178143" ;# -$ns_ at 195.496637 "$node_(57) setdest 1860.000000 1960.000000 11.624694" ;# -$ns_ at 0.0 "$node_(95) switch OFF" ;# set_X,Y,Z -$node_(95) set X_ 0.000000 -$node_(95) set Y_ 0.000000 -$node_(95) set Z_ 0.0 -$ns_ at 200.540141 "$node_(95) setdest 3917.755102 10.000000 1000000000.000000" ;# init_node -$ns_ at 200.550141 "$node_(95) switch ON" ;# inside -$ns_ at 200.550141 "$node_(95) setdest 3930.000000 210.000000 11.469727" ;# -$ns_ at 197.712478 "$node_(80) setdest 2510.000000 1290.000000 14.870156" ;# -$ns_ at 198.237245 "$node_(69) setdest 2043.885022 1770.456977 15.035831" ;# -$ns_ at 198.994650 "$node_(75) setdest 3032.000000 1370.000000 15.527926" ;# -$ns_ at 199.020000 "$node_(50) setdest 851.594504 2140.452996 18.543827" ;# -#$ns_ at 199.020000 $node_(89) arrived_to 100.000000 470.000000 -$ns_ at 199.020000 "$node_(89) switch OFF" ;# arrived_to -$ns_ at 200.020000 "$node_(89) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 200.030000 "$node_(89) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 199.020000 "$node_(29) setdest 1776.442635 1975.144111 19.043520" ;# -$ns_ at 201.523686 "$node_(92) setdest 1522.902019 657.467680 15.764942" ;# -$ns_ at 201.774529 "$node_(91) setdest 1388.150347 907.720784 16.589689" ;# -$ns_ at 202.139067 "$node_(90) setdest 1290.000000 1090.000000 17.977331" ;# -$ns_ at 202.941870 "$node_(94) setdest 1290.000000 1090.000000 16.316016" ;# -$ns_ at 203.479189 "$node_(29) setdest 1506.457950 2024.076696 15.681582" ;# -#$ns_ at 206.020000 $node_(76) arrived_to 3290.000000 1020.000000 -$ns_ at 206.020000 "$node_(76) switch OFF" ;# arrived_to -$ns_ at 207.020000 "$node_(76) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 207.030000 "$node_(76) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 206.020000 $node_(39) arrived_to 3090.000000 2030.000000 -$ns_ at 206.020000 "$node_(39) switch OFF" ;# arrived_to -$ns_ at 207.020000 "$node_(39) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 207.030000 "$node_(39) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 207.020000 $node_(66) arrived_to 1980.000000 2190.000000 -$ns_ at 207.020000 "$node_(66) switch OFF" ;# arrived_to -$ns_ at 208.020000 "$node_(66) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 208.030000 "$node_(66) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 207.020000 "$node_(80) setdest 2324.258074 1481.457062 11.783104" ;# -#$ns_ at 207.020000 $node_(88) arrived_to 100.000000 470.000000 -$ns_ at 207.020000 "$node_(88) switch OFF" ;# arrived_to -$ns_ at 208.020000 "$node_(88) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 208.030000 "$node_(88) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 207.521317 "$node_(36) setdest 245.000000 2244.000000 15.790038" ;# -$ns_ at 207.560570 "$node_(73) setdest 2119.973365 2080.895286 16.467044" ;# -$ns_ at 208.020000 "$node_(93) setdest 2989.140807 353.312646 13.088646" ;# -$ns_ at 208.187261 "$node_(44) setdest 623.790512 2179.339634 18.470348" ;# -$ns_ at 211.022873 "$node_(50) setdest 245.000000 2244.000000 15.779852" ;# -$ns_ at 211.024255 "$node_(63) setdest 2056.747297 1757.198940 14.688254" ;# -$ns_ at 212.390686 "$node_(69) setdest 1860.000000 1960.000000 11.669987" ;# -#$ns_ at 213.020000 $node_(65) arrived_to 3090.000000 2030.000000 -$ns_ at 213.020000 "$node_(65) switch OFF" ;# arrived_to -$ns_ at 214.020000 "$node_(65) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 214.030000 "$node_(65) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 214.020000 "$node_(49) setdest 10.000000 2297.153203 25.061238" ;# -$ns_ at 223.633899 "$node_(49) switch OFF" ;# leaving_area -$ns_ at 214.505518 "$node_(85) setdest 2880.706633 974.899362 15.931866" ;# -$ns_ at 216.232020 "$node_(79) setdest 2341.346270 1908.342261 17.761994" ;# -$ns_ at 216.589042 "$node_(44) setdest 245.000000 2244.000000 15.728803" ;# -$ns_ at 217.020000 "$node_(87) setdest 1440.191417 1310.593644 15.030777" ;# -$ns_ at 217.020000 "$node_(77) setdest 1860.000000 1960.000000 13.528813" ;# -$ns_ at 218.020000 "$node_(67) setdest 2974.599224 2217.861728 11.270777" ;# -$ns_ at 219.020000 "$node_(95) setdest 4660.000000 400.000000 10.932187" ;# -$ns_ at 219.733258 "$node_(60) setdest 429.306931 3010.000000 19.194417" ;# -$ns_ at 232.844577 "$node_(60) switch OFF" ;# leaving_area -$ns_ at 219.821678 "$node_(63) setdest 1860.000000 1960.000000 13.329158" ;# -$ns_ at 219.966205 "$node_(85) setdest 2510.000000 1290.000000 13.494568" ;# -$ns_ at 220.020000 "$node_(75) setdest 3335.449131 2002.185689 16.743154" ;# -$ns_ at 220.020000 "$node_(82) setdest 2225.249532 1583.512021 13.528813" ;# -$ns_ at 220.976351 "$node_(29) setdest 1447.052342 2034.843492 19.129141" ;# -$ns_ at 224.132448 "$node_(29) setdest 1071.000000 2103.000000 15.999079" ;# -$ns_ at 229.020000 "$node_(21) setdest 892.985050 2133.387540 18.885850" ;# -$ns_ at 229.020000 "$node_(33) setdest 1598.308715 2007.429472 15.682055" ;# -$ns_ at 229.658395 "$node_(80) setdest 2153.802027 1657.157910 13.260012" ;# -$ns_ at 232.020000 "$node_(24) setdest 3838.461538 3010.000000 30.389856" ;# -$ns_ at 233.845983 "$node_(24) switch OFF" ;# leaving_area -$ns_ at 232.592289 "$node_(91) setdest 1290.000000 1090.000000 18.116021" ;# -$ns_ at 232.853023 "$node_(92) setdest 1356.793484 965.954958 17.910555" ;# -$ns_ at 232.866807 "$node_(73) setdest 1980.000000 2190.000000 17.479445" ;# -$ns_ at 234.020000 "$node_(86) setdest 1786.643491 1842.629586 13.424032" ;# -$ns_ at 234.774832 "$node_(87) setdest 1610.000000 1560.000000 12.980153" ;# -$ns_ at 236.020000 "$node_(69) setdest 1071.000000 2103.000000 16.364369" ;# -$ns_ at 237.581680 "$node_(67) setdest 2818.392033 2472.152504 10.264343" ;# -$ns_ at 238.020000 "$node_(57) setdest 1707.400414 1987.657466 19.200321" ;# -$ns_ at 238.582182 "$node_(21) setdest 685.403262 2168.822203 14.782163" ;# -$ns_ at 239.020000 "$node_(36) setdest 10.000000 2297.153204 29.240031" ;# -$ns_ at 247.259944 "$node_(36) switch OFF" ;# leaving_area -$ns_ at 239.377571 "$node_(79) setdest 1980.000000 2190.000000 15.455914" ;# -$ns_ at 240.020000 "$node_(1) setdest 602.456318 2182.981427 16.430355" ;# -$ns_ at 242.020000 "$node_(44) setdest 10.000000 2297.153203 26.264286" ;# -$ns_ at 251.193530 "$node_(44) switch OFF" ;# leaving_area -#$ns_ at 242.020000 $node_(63) arrived_to 1860.000000 1960.000000 -$ns_ at 242.020000 "$node_(63) switch OFF" ;# arrived_to -$ns_ at 243.020000 "$node_(63) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 243.030000 "$node_(63) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 243.020000 $node_(90) arrived_to 1290.000000 1090.000000 -$ns_ at 243.020000 "$node_(90) switch OFF" ;# arrived_to -$ns_ at 244.020000 "$node_(90) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 244.030000 "$node_(90) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -#$ns_ at 244.020000 $node_(73) arrived_to 1980.000000 2190.000000 -$ns_ at 244.020000 "$node_(73) switch OFF" ;# arrived_to -$ns_ at 245.020000 "$node_(73) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 245.030000 "$node_(73) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 245.020000 "$node_(91) setdest 652.346233 1231.317862 16.621823" ;# -$ns_ at 245.979172 "$node_(33) setdest 1347.377906 2052.908694 15.278138" ;# -$ns_ at 246.097244 "$node_(57) setdest 1477.003253 2029.415127 14.906121" ;# -$ns_ at 248.119765 "$node_(80) setdest 2022.303833 1792.702203 13.262811" ;# -$ns_ at 249.020000 "$node_(29) setdest 788.024513 2151.304532 17.646027" ;# -$ns_ at 250.008177 "$node_(93) setdest 3310.000000 610.000000 14.668817" ;# -$ns_ at 250.247357 "$node_(82) setdest 2091.946353 1720.916836 15.145760" ;# -$ns_ at 251.020000 "$node_(50) setdest 10.000000 2297.153203 31.914843" ;# -$ns_ at 258.569347 "$node_(50) switch OFF" ;# leaving_area -$ns_ at 252.415016 "$node_(92) setdest 1290.000000 1090.000000 18.525334" ;# -$ns_ at 252.828031 "$node_(21) setdest 444.675750 2209.914914 15.036167" ;# -#$ns_ at 257.020000 $node_(85) arrived_to 2510.000000 1290.000000 -$ns_ at 257.020000 "$node_(85) switch OFF" ;# arrived_to -$ns_ at 258.020000 "$node_(85) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 258.030000 "$node_(85) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 258.847881 "$node_(86) setdest 1860.000000 1960.000000 15.090166" ;# -$ns_ at 259.020000 "$node_(87) setdest 1294.979871 1877.357940 16.121572" ;# -#$ns_ at 261.020000 $node_(92) arrived_to 1290.000000 1090.000000 -$ns_ at 261.020000 "$node_(92) switch OFF" ;# arrived_to -$ns_ at 262.020000 "$node_(92) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 262.030000 "$node_(92) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 261.805603 "$node_(57) setdest 1282.120421 2064.736096 17.465197" ;# -$ns_ at 261.902303 "$node_(75) setdest 3558.437585 2466.744969 17.642329" ;# -$ns_ at 262.358770 "$node_(80) setdest 1860.000000 1960.000000 11.855327" ;# -$ns_ at 262.670923 "$node_(33) setdest 1148.444158 2088.963860 17.976508" ;# -$ns_ at 262.887292 "$node_(82) setdest 1860.000000 1960.000000 12.746724" ;# -$ns_ at 265.288179 "$node_(29) setdest 245.000000 2244.000000 15.860941" ;# -$ns_ at 300.010000 "$node_(29) switch OFF" ;# T_max_OFF -$ns_ at 266.656773 "$node_(67) setdest 2784.048966 2528.059823 11.611108" ;# -$ns_ at 0.0 "$node_(96) switch OFF" ;# set_X,Y,Z -$node_(96) set X_ 0.000000 -$node_(96) set Y_ 0.000000 -$node_(96) set Z_ 0.0 -$ns_ at 272.965033 "$node_(96) setdest 3838.461539 3010.000000 1000000000.000000" ;# init_node -$ns_ at 272.975033 "$node_(96) switch ON" ;# inside -$ns_ at 272.975033 "$node_(96) setdest 3800.000000 2970.000000 27.135580" ;# -$ns_ at 268.949452 "$node_(1) setdest 557.162097 2190.713250 17.426686" ;# -$ns_ at 269.020000 "$node_(86) setdest 1949.861359 2132.234271 13.400689" ;# -$ns_ at 269.069512 "$node_(21) setdest 245.000000 2244.000000 18.498178" ;# -$ns_ at 270.020000 "$node_(79) setdest 1527.825258 2429.108110 15.340410" ;# -$ns_ at 300.010000 "$node_(79) switch OFF" ;# T_max_OFF -$ns_ at 271.586178 "$node_(1) setdest 245.000000 2244.000000 16.295176" ;# -$ns_ at 272.307661 "$node_(67) setdest 2660.000000 2730.000000 10.434763" ;# -$ns_ at 273.145744 "$node_(57) setdest 1071.000000 2103.000000 15.464606" ;# -$ns_ at 0.0 "$node_(97) switch OFF" ;# set_X,Y,Z -$node_(97) set X_ 0.000000 -$node_(97) set Y_ 0.000000 -$node_(97) set Z_ 0.0 -$ns_ at 279.010000 "$node_(97) setdest 2560.000000 10.000000 1000000000.000000" ;# init_node -$ns_ at 279.020000 "$node_(97) switch ON" ;# inside -$ns_ at 279.020000 "$node_(97) setdest 2560.000000 10.000000 14.938944" ;# -$ns_ at 273.917529 "$node_(33) setdest 1071.000000 2103.000000 19.184982" ;# -$ns_ at 0.0 "$node_(98) switch OFF" ;# set_X,Y,Z -$node_(98) set X_ 0.000000 -$node_(98) set Y_ 0.000000 -$node_(98) set Z_ 0.0 -$ns_ at 282.925931 "$node_(98) setdest 3838.461539 3010.000000 1000000000.000000" ;# init_node -$ns_ at 282.935931 "$node_(98) switch ON" ;# inside -$ns_ at 282.935931 "$node_(98) setdest 3800.000000 2970.000000 26.626446" ;# -$ns_ at 276.020000 "$node_(96) setdest 3474.475390 2291.823728 16.199655" ;# -$ns_ at 300.010000 "$node_(96) switch OFF" ;# T_max_OFF -$ns_ at 276.020000 "$node_(94) setdest 1339.605990 1162.858798 15.675509" ;# -$ns_ at 279.020000 "$node_(93) setdest 3298.774462 840.123521 13.682917" ;# -$ns_ at 279.020000 "$node_(33) setdest 758.868100 2156.281595 15.403528" ;# -$ns_ at 280.020000 "$node_(97) setdest 3310.000000 610.000000 13.527727" ;# -$ns_ at 300.010000 "$node_(97) switch OFF" ;# T_max_OFF -$ns_ at 281.020000 "$node_(21) setdest 10.000000 2297.153203 30.398557" ;# -$ns_ at 288.945910 "$node_(21) switch OFF" ;# leaving_area -$ns_ at 281.642965 "$node_(94) setdest 1484.258241 1375.316791 13.340685" ;# -$ns_ at 300.010000 "$node_(94) switch OFF" ;# T_max_OFF -$ns_ at 283.020000 "$node_(80) setdest 1502.174391 2024.853057 16.364369" ;# -$ns_ at 300.010000 "$node_(80) switch OFF" ;# T_max_OFF -$ns_ at 283.516799 "$node_(86) setdest 1980.000000 2190.000000 14.468669" ;# -$ns_ at 284.313260 "$node_(91) setdest 431.300048 1280.306476 17.867474" ;# -$ns_ at 286.020000 "$node_(98) setdest 3801.473672 2750.422828 15.669625" ;# -$ns_ at 300.010000 "$node_(98) switch OFF" ;# T_max_OFF -$ns_ at 286.020000 "$node_(69) setdest 918.365533 2129.055036 18.384042" ;# -$ns_ at 286.756865 "$node_(87) setdest 1142.462024 2031.007645 16.632495" ;# -$ns_ at 287.020000 "$node_(77) setdest 1551.772884 2015.863723 14.961985" ;# -$ns_ at 300.010000 "$node_(77) switch OFF" ;# T_max_OFF -$ns_ at 288.020000 "$node_(57) setdest 803.748295 2148.620448 15.729994" ;# -$ns_ at 300.010000 "$node_(57) switch OFF" ;# T_max_OFF -$ns_ at 289.020000 "$node_(86) setdest 2353.960580 2486.968696 16.383618" ;# -$ns_ at 300.010000 "$node_(86) switch OFF" ;# T_max_OFF -#$ns_ at 289.020000 $node_(95) arrived_to 4660.000000 400.000000 -$ns_ at 289.020000 "$node_(95) switch OFF" ;# arrived_to -$ns_ at 290.020000 "$node_(95) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 290.030000 "$node_(95) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 290.020000 "$node_(82) setdest 1540.540627 2017.899481 16.364369" ;# -$ns_ at 300.010000 "$node_(82) switch OFF" ;# T_max_OFF -$ns_ at 291.110744 "$node_(75) setdest 3800.000000 2970.000000 15.990818" ;# -$ns_ at 300.010000 "$node_(75) switch OFF" ;# T_max_OFF -$ns_ at 292.020000 "$node_(1) setdest 10.000000 2297.153204 31.068618" ;# -$ns_ at 299.774971 "$node_(1) switch OFF" ;# leaving_area -$ns_ at 294.442649 "$node_(69) setdest 667.501399 2171.878090 15.432507" ;# -$ns_ at 300.010000 "$node_(69) switch OFF" ;# T_max_OFF -$ns_ at 295.858307 "$node_(93) setdest 3296.273248 891.398413 15.927207" ;# -#$ns_ at 296.020000 $node_(67) arrived_to 2660.000000 2730.000000 -$ns_ at 296.020000 "$node_(67) switch OFF" ;# arrived_to -$ns_ at 297.020000 "$node_(67) setdest 0.010000 0.010000 1000000001.000000" ;# remove_from_area_upon__arrived_to -$ns_ at 297.030000 "$node_(67) setdest 0.020000 0.020000 1000000001.000000" ;# nam_hack__force_remove -$ns_ at 296.984866 "$node_(91) setdest 10.000000 1373.675676 16.367380" ;# -$ns_ at 300.010000 "$node_(91) switch OFF" ;# T_max_OFF -$ns_ at 299.081462 "$node_(93) setdest 3290.000000 1020.000000 12.955074" ;# -$ns_ at 300.010000 "$node_(93) switch OFF" ;# T_max_OFF -$ns_ at 299.576777 "$node_(33) setdest 597.299018 2183.861790 18.859074" ;# -$ns_ at 300.010000 "$node_(33) switch OFF" ;# T_max_OFF -$ns_ at 299.773230 "$node_(87) setdest 1071.000000 2103.000000 19.333470" ;# -$ns_ at 300.010000 "$node_(87) switch OFF" ;# T_max_OFF diff --git a/src/wave/examples/vanet-routing-compare.cc b/src/wave/examples/vanet-routing-compare.cc deleted file mode 100644 index fe0854b3b..000000000 --- a/src/wave/examples/vanet-routing-compare.cc +++ /dev/null @@ -1,2500 +0,0 @@ -/* - * Copyright (c) 2014 North Carolina State University - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Scott E. Carpenter - * - */ - -/* - * This example program allows one to run vehicular ad hoc - * network (VANET) simulation scenarios in ns-3 to assess - * performance by evaluating different 802.11p MAC/PHY - * characteristics, propagation loss models (e.g. Friss, - * Two-Ray Ground, or ITU R-P.1411), and application traffic - * (e.g. Basic Safety Message) and/or routing traffic (e.g. - * DSDV, AODV, OLSR, or DSR) under either a synthetic highway - * scenario (i.e. a random waypoint mobility model) or by - * playing back mobility trace files (i.e. ns-2 movement files). - * - * The script draws from several ns-3 examples, including: - * /examples/routing/manet-routing-compare.cc - * /src/propagation/model/itu-r-1411-los-propagation-loss-model.cc - * /src/mobility/examples/ns2-mobility-trace.cc - * /src/wave/examples/wave-simple-80211p.cc - * - * The script allows many parameters to be modified and - * includes two predefined scenarios. By default - * scenario=1 runs for 10 simulated seconds with 40 nodes - * (i.e. vehicles) moving according to RandomWaypointMobilityModel - * with a speed of 20 m/s and no pause time within a 300x1500 m - * region. The WiFi is 802.11p with continuous access to a 10 MHz - * Control Channel (CH) for all traffic. All nodes transmit a - * 200-byte safety message 10 times per second at 6 Mbps. - * Additionally, all nodes (optionally) attempt to - * continuously route 64-byte packets at an application - * rate of 2.048 Kbps to one of 10 other nodes, - * selected as sink nodes. The default routing protocol is AODV - * and the Two-Ray Ground loss model is used. - * The transmit power is set to 20 dBm and the transmission range - * for safety message packet delivery is 145 m. - * - * Scenario 2 plays back vehicular trace files in - * ns-2 movement format, and are taken from: - * https://web.archive.org/web/20150218095728/http://www.lst.inf.ethz.ch/research/ad-hoc/car-traces - * This scenario is 300 simulation seconds of 99 - * vehicles respectively within the Unterstrass - * section of Zurich Switzerland that travel based on - * models derived from real traffic data. Note that these - * scenarios can require a lot of clock time to complete. - * - * All parameters can be changed from their defaults (see - * --help) and changing simulation parameters can have dramatic - * impact on network performance. - * - * Several items can be output: - * - a CSV file of data reception statistics, output once per - * second - * - final statistics, in a CSV file - * - dump of routing tables at 5 seconds into the simulation - * - ASCII trace file - * - PCAP trace files for each node - * - * Simulation scenarios can be defined and configuration - * settings can be saved using config-store (raw text) - * which can they be replayed again. This is an easy way - * to define and save the settings for a scenario, and then - * re-execute the same scenario exactly, or to set up - * several different simulation scenarios. - * For example, to set up a scenario and save the configuration - * as "scenario1.txt": - * ./ns3 run "vanet-routing-compare --scenario=1 --saveconfig=scenario1.txt" - * Then, to re-play the scenario using the save configuration - * settings: - * ./ns3 run "vanet-routing-compare --loadconfig=scenario1.txt" - * - * Class Diagram: - * main() - * +--uses-- VanetRoutingExperiment - * +--is_a--- WifiApp - * +--uses--- ConfigStoreHelper - * +--has_a-- WaveBsmHelper - * | +--has_a-- WaveBsmStats - * +--has_a-- RoutingHelper - * | +--has_a--RoutingStats - * +--has_a-- WifiPhyStats - * - */ - -#include "ns3/aodv-module.h" -#include "ns3/applications-module.h" -#include "ns3/config-store-module.h" -#include "ns3/core-module.h" -#include "ns3/dsdv-module.h" -#include "ns3/dsr-module.h" -#include "ns3/flow-monitor-module.h" -#include "ns3/integer.h" -#include "ns3/internet-module.h" -#include "ns3/itu-r-1411-los-propagation-loss-model.h" -#include "ns3/mobility-module.h" -#include "ns3/network-module.h" -#include "ns3/ocb-wifi-mac.h" -#include "ns3/olsr-module.h" -#include "ns3/wave-bsm-helper.h" -#include "ns3/wave-helper.h" -#include "ns3/wave-mac-helper.h" -#include "ns3/wifi-80211p-helper.h" -#include "ns3/yans-wifi-helper.h" - -#include -#include - -using namespace ns3; -using namespace dsr; - -NS_LOG_COMPONENT_DEFINE("vanet-routing-compare"); - -/** - * \ingroup wave - * \brief The RoutingStats class manages collects statistics - * on routing data (application-data packet and byte counts) - * for the vehicular network - */ -class RoutingStats -{ - public: - /** - * \brief Constructor - */ - RoutingStats(); - - /** - * \brief Returns the number of bytes received - * \return the number of bytes received - */ - uint32_t GetRxBytes() const; - - /** - * \brief Returns the cumulative number of bytes received - * \return the cumulative number of bytes received - */ - uint32_t GetCumulativeRxBytes() const; - - /** - * \brief Returns the count of packets received - * \return the count of packets received - */ - uint32_t GetRxPkts() const; - - /** - * \brief Returns the cumulative count of packets received - * \return the cumulative count of packets received - */ - uint32_t GetCumulativeRxPkts() const; - - /** - * \brief Increments the number of (application-data) - * bytes received, not including MAC/PHY overhead - * \param rxBytes the number of bytes received - */ - void IncRxBytes(uint32_t rxBytes); - - /** - * \brief Increments the count of packets received - */ - void IncRxPkts(); - - /** - * \brief Sets the number of bytes received. - * \param rxBytes the number of bytes received - */ - void SetRxBytes(uint32_t rxBytes); - - /** - * \brief Sets the number of packets received - * \param rxPkts the number of packets received - */ - void SetRxPkts(uint32_t rxPkts); - - /** - * \brief Returns the number of bytes transmitted - * \return the number of bytes transmitted - */ - uint32_t GetTxBytes() const; - - /** - * \brief Returns the cumulative number of bytes transmitted - * \return the cumulative number of bytes transmitted - */ - uint32_t GetCumulativeTxBytes() const; - - /** - * \brief Returns the number of packets transmitted - * \return the number of packets transmitted - */ - uint32_t GetTxPkts() const; - - /** - * \brief Returns the cumulative number of packets transmitted - * \return the cumulative number of packets transmitted - */ - uint32_t GetCumulativeTxPkts() const; - - /** - * \brief Increment the number of bytes transmitted - * \param txBytes the number of additional bytes transmitted - */ - void IncTxBytes(uint32_t txBytes); - - /** - * \brief Increment the count of packets transmitted - */ - void IncTxPkts(); - - /** - * \brief Sets the number of bytes transmitted - * \param txBytes the number of bytes transmitted - */ - void SetTxBytes(uint32_t txBytes); - - /** - * \brief Sets the number of packets transmitted - * \param txPkts the number of packets transmitted - */ - void SetTxPkts(uint32_t txPkts); - - private: - uint32_t m_RxBytes; ///< receive bytes - uint32_t m_cumulativeRxBytes; ///< cumulative receive bytes - uint32_t m_RxPkts; ///< receive packets - uint32_t m_cumulativeRxPkts; ///< cumulative receive packets - uint32_t m_TxBytes; ///< transmit bytes - uint32_t m_cumulativeTxBytes; ///< cumulative transmit bytes - uint32_t m_TxPkts; ///< transmit packets - uint32_t m_cumulativeTxPkts; ///< cumulative transmit packets -}; - -RoutingStats::RoutingStats() - : m_RxBytes(0), - m_cumulativeRxBytes(0), - m_RxPkts(0), - m_cumulativeRxPkts(0), - m_TxBytes(0), - m_cumulativeTxBytes(0), - m_TxPkts(0), - m_cumulativeTxPkts(0) -{ -} - -uint32_t -RoutingStats::GetRxBytes() const -{ - return m_RxBytes; -} - -uint32_t -RoutingStats::GetCumulativeRxBytes() const -{ - return m_cumulativeRxBytes; -} - -uint32_t -RoutingStats::GetRxPkts() const -{ - return m_RxPkts; -} - -uint32_t -RoutingStats::GetCumulativeRxPkts() const -{ - return m_cumulativeRxPkts; -} - -void -RoutingStats::IncRxBytes(uint32_t rxBytes) -{ - m_RxBytes += rxBytes; - m_cumulativeRxBytes += rxBytes; -} - -void -RoutingStats::IncRxPkts() -{ - m_RxPkts++; - m_cumulativeRxPkts++; -} - -void -RoutingStats::SetRxBytes(uint32_t rxBytes) -{ - m_RxBytes = rxBytes; -} - -void -RoutingStats::SetRxPkts(uint32_t rxPkts) -{ - m_RxPkts = rxPkts; -} - -uint32_t -RoutingStats::GetTxBytes() const -{ - return m_TxBytes; -} - -uint32_t -RoutingStats::GetCumulativeTxBytes() const -{ - return m_cumulativeTxBytes; -} - -uint32_t -RoutingStats::GetTxPkts() const -{ - return m_TxPkts; -} - -uint32_t -RoutingStats::GetCumulativeTxPkts() const -{ - return m_cumulativeTxPkts; -} - -void -RoutingStats::IncTxBytes(uint32_t txBytes) -{ - m_TxBytes += txBytes; - m_cumulativeTxBytes += txBytes; -} - -void -RoutingStats::IncTxPkts() -{ - m_TxPkts++; - m_cumulativeTxPkts++; -} - -void -RoutingStats::SetTxBytes(uint32_t txBytes) -{ - m_TxBytes = txBytes; -} - -void -RoutingStats::SetTxPkts(uint32_t txPkts) -{ - m_TxPkts = txPkts; -} - -/** - * \ingroup wave - * \brief The RoutingHelper class generates routing data between - * nodes (vehicles) and uses the RoutingStats class to collect statistics - * on routing data (application-data packet and byte counts). - * A routing protocol is configured, and all nodes attempt to send - * (i.e. route) small packets to another node, which acts as - * data sinks. Not all nodes act as data sinks. - * for the vehicular network - */ -class RoutingHelper : public Object -{ - public: - /** - * \brief Get class TypeId - * \return the TypeId for the class - */ - static TypeId GetTypeId(); - - /** - * \brief Constructor - */ - RoutingHelper(); - - /** - * \brief Destructor - */ - ~RoutingHelper() override; - - /** - * \brief Installs routing functionality on nodes and their - * devices and interfaces. - * \param c node container - * \param d net device container - * \param i IPv4 interface container - * \param totalTime the total time that nodes should attempt to - * route data - * \param protocol the routing protocol (1=OLSR;2=AODV;3=DSDV;4=DSR) - * \param nSinks the number of nodes which will act as data sinks - * \param routingTables whether to dump routing tables at t=5 seconds - */ - void Install(NodeContainer& c, - NetDeviceContainer& d, - Ipv4InterfaceContainer& i, - double totalTime, - int protocol, - uint32_t nSinks, - bool routingTables); - - /** - * \brief Trace the receipt of an on-off-application generated packet - * \param context this object - * \param packet a received packet - */ - void OnOffTrace(std::string context, Ptr packet); - - /** - * \brief Returns the RoutingStats instance - * \return the RoutingStats instance - */ - RoutingStats& GetRoutingStats(); - - /** - * \brief Enable/disable logging - * \param log whether to enable logging - */ - void SetLogging(bool log); - - private: - /** - * \brief Sets up the protocol protocol on the nodes - * \param c node container - */ - void SetupRoutingProtocol(NodeContainer& c); - - /** - * \brief Assigns IPv4 addresses to net devices and their interfaces - * \param d net device container - * \param adhocTxInterfaces IPv4 interface container - */ - void AssignIpAddresses(NetDeviceContainer& d, Ipv4InterfaceContainer& adhocTxInterfaces); - - /** - * \brief Sets up routing messages on the nodes and their interfaces - * \param c node container - * \param adhocTxInterfaces IPv4 interface container - */ - void SetupRoutingMessages(NodeContainer& c, Ipv4InterfaceContainer& adhocTxInterfaces); - - /** - * \brief Sets up a routing packet for transmission - * \param addr destination address - * \param node source node - * \return Socket to be used for sending/receiving a routed data packet - */ - Ptr SetupRoutingPacketReceive(Ipv4Address addr, Ptr node); - - /** - * \brief Process a received routing packet - * \param socket the receiving socket - */ - void ReceiveRoutingPacket(Ptr socket); - - double m_TotalSimTime; ///< seconds - uint32_t m_protocol; ///< routing protocol; 0=NONE, 1=OLSR, 2=AODV, 3=DSDV, 4=DSR - uint32_t m_port; ///< port - uint32_t m_nSinks; ///< number of sink nodes (< all nodes) - bool m_routingTables; ///< dump routing table (at t=5 sec). 0=No, 1=Yes - RoutingStats routingStats; ///< routing statistics - std::string m_protocolName; ///< protocol name - bool m_log; ///< log -}; - -NS_OBJECT_ENSURE_REGISTERED(RoutingHelper); - -TypeId -RoutingHelper::GetTypeId() -{ - static TypeId tid = - TypeId("ns3::RoutingHelper").SetParent().AddConstructor(); - return tid; -} - -RoutingHelper::RoutingHelper() - : m_TotalSimTime(300.01), - m_protocol(0), - m_port(9), - m_nSinks(0), - m_routingTables(false), - m_log(false) -{ -} - -RoutingHelper::~RoutingHelper() -{ -} - -void -RoutingHelper::Install(NodeContainer& c, - NetDeviceContainer& d, - Ipv4InterfaceContainer& i, - double totalTime, - int protocol, - uint32_t nSinks, - bool routingTables) -{ - m_TotalSimTime = totalTime; - m_protocol = protocol; - m_nSinks = nSinks; - m_routingTables = routingTables; - - SetupRoutingProtocol(c); - AssignIpAddresses(d, i); - SetupRoutingMessages(c, i); -} - -Ptr -RoutingHelper::SetupRoutingPacketReceive(Ipv4Address addr, Ptr node) -{ - TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory"); - Ptr sink = Socket::CreateSocket(node, tid); - InetSocketAddress local = InetSocketAddress(addr, m_port); - sink->Bind(local); - sink->SetRecvCallback(MakeCallback(&RoutingHelper::ReceiveRoutingPacket, this)); - - return sink; -} - -void -RoutingHelper::SetupRoutingProtocol(NodeContainer& c) -{ - AodvHelper aodv; - OlsrHelper olsr; - DsdvHelper dsdv; - DsrHelper dsr; - DsrMainHelper dsrMain; - Ipv4ListRoutingHelper list; - InternetStackHelper internet; - - Time rtt = Time(5.0); - AsciiTraceHelper ascii; - Ptr rtw = ascii.CreateFileStream("routing_table"); - - switch (m_protocol) - { - case 0: - m_protocolName = "NONE"; - break; - case 1: - if (m_routingTables) - { - Ipv4RoutingHelper::PrintRoutingTableAllAt(rtt, rtw); - } - list.Add(olsr, 100); - m_protocolName = "OLSR"; - break; - case 2: - if (m_routingTables) - { - Ipv4RoutingHelper::PrintRoutingTableAllAt(rtt, rtw); - } - list.Add(aodv, 100); - m_protocolName = "AODV"; - break; - case 3: - if (m_routingTables) - { - ns3::DsdvHelper::PrintRoutingTableAllAt(rtt, rtw); - } - list.Add(dsdv, 100); - m_protocolName = "DSDV"; - break; - case 4: - // setup is later - m_protocolName = "DSR"; - break; - default: - NS_FATAL_ERROR("No such protocol:" << m_protocol); - break; - } - - if (m_protocol < 4) - { - internet.SetRoutingHelper(list); - internet.Install(c); - } - else if (m_protocol == 4) - { - internet.Install(c); - dsrMain.Install(dsr, c); - } - - if (m_log) - { - NS_LOG_UNCOND("Routing Setup for " << m_protocolName); - } -} - -void -RoutingHelper::AssignIpAddresses(NetDeviceContainer& d, Ipv4InterfaceContainer& adhocTxInterfaces) -{ - NS_LOG_INFO("Assigning IP addresses"); - Ipv4AddressHelper addressAdhoc; - // we may have a lot of nodes, and want them all - // in same subnet, to support broadcast - addressAdhoc.SetBase("10.1.0.0", "255.255.0.0"); - adhocTxInterfaces = addressAdhoc.Assign(d); -} - -void -RoutingHelper::SetupRoutingMessages(NodeContainer& c, Ipv4InterfaceContainer& adhocTxInterfaces) -{ - // Setup routing transmissions - OnOffHelper onoff1("ns3::UdpSocketFactory", Address()); - onoff1.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1.0]")); - onoff1.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0.0]")); - - Ptr var = CreateObject(); - int64_t stream = 2; - var->SetStream(stream); - for (uint32_t i = 0; i < m_nSinks; i++) - { - // protocol == 0 means no routing data, WAVE BSM only - // so do not set up sink - if (m_protocol != 0) - { - Ptr sink = SetupRoutingPacketReceive(adhocTxInterfaces.GetAddress(i), c.Get(i)); - } - - AddressValue remoteAddress(InetSocketAddress(adhocTxInterfaces.GetAddress(i), m_port)); - onoff1.SetAttribute("Remote", remoteAddress); - - ApplicationContainer temp = onoff1.Install(c.Get(i + m_nSinks)); - temp.Start(Seconds(var->GetValue(1.0, 2.0))); - temp.Stop(Seconds(m_TotalSimTime)); - } -} - -/** - * Print a received routing packet on a string - * \param socket Rx socket - * \param packet Rx packet - * \param srcAddress source address - * \return the built string - */ -static inline std::string -PrintReceivedRoutingPacket(Ptr socket, Ptr packet, Address srcAddress) -{ - std::ostringstream oss; - - oss << Simulator::Now().As(Time::S) << " " << socket->GetNode()->GetId(); - - if (InetSocketAddress::IsMatchingType(srcAddress)) - { - InetSocketAddress addr = InetSocketAddress::ConvertFrom(srcAddress); - oss << " received one packet from " << addr.GetIpv4(); - } - else - { - oss << " received one packet!"; - } - return oss.str(); -} - -void -RoutingHelper::ReceiveRoutingPacket(Ptr socket) -{ - Ptr packet; - Address srcAddress; - while ((packet = socket->RecvFrom(srcAddress))) - { - // application data, for goodput - uint32_t RxRoutingBytes = packet->GetSize(); - GetRoutingStats().IncRxBytes(RxRoutingBytes); - GetRoutingStats().IncRxPkts(); - if (m_log) - { - NS_LOG_UNCOND(m_protocolName + " " + - PrintReceivedRoutingPacket(socket, packet, srcAddress)); - } - } -} - -void -RoutingHelper::OnOffTrace(std::string context, Ptr packet) -{ - uint32_t pktBytes = packet->GetSize(); - routingStats.IncTxBytes(pktBytes); -} - -RoutingStats& -RoutingHelper::GetRoutingStats() -{ - return routingStats; -} - -void -RoutingHelper::SetLogging(bool log) -{ - m_log = log; -} - -/** - * \ingroup wave - * \brief The WifiPhyStats class collects Wifi MAC/PHY statistics - */ -class WifiPhyStats : public Object -{ - public: - /** - * \brief Gets the class TypeId - * \return the class TypeId - */ - static TypeId GetTypeId(); - - /** - * \brief Constructor - */ - WifiPhyStats(); - - /** - * \brief Destructor - */ - ~WifiPhyStats() override; - - /** - * \brief Returns the number of bytes that have been transmitted - * (this includes MAC/PHY overhead) - * \return the number of bytes transmitted - */ - uint32_t GetTxBytes() const; - - /** - * \brief Callback signature for Phy/Tx trace - * \param context this object - * \param packet packet transmitted - * \param mode wifi mode - * \param preamble wifi preamble - * \param txPower transmission power - */ - void PhyTxTrace(std::string context, - Ptr packet, - WifiMode mode, - WifiPreamble preamble, - uint8_t txPower); - - /** - * \brief Callback signature for Phy/TxDrop - * \param context this object - * \param packet the tx packet being dropped - */ - void PhyTxDrop(std::string context, Ptr packet); - - /** - * \brief Callback signature for Phy/RxDrop - * \param context this object - * \param packet the rx packet being dropped - * \param reason the reason for the drop - */ - void PhyRxDrop(std::string context, Ptr packet, WifiPhyRxfailureReason reason); - - private: - uint32_t m_phyTxPkts; ///< phy transmit packets - uint32_t m_phyTxBytes; ///< phy transmit bytes -}; - -NS_OBJECT_ENSURE_REGISTERED(WifiPhyStats); - -TypeId -WifiPhyStats::GetTypeId() -{ - static TypeId tid = - TypeId("ns3::WifiPhyStats").SetParent().AddConstructor(); - return tid; -} - -WifiPhyStats::WifiPhyStats() - : m_phyTxPkts(0), - m_phyTxBytes(0) -{ -} - -WifiPhyStats::~WifiPhyStats() -{ -} - -void -WifiPhyStats::PhyTxTrace(std::string context, - Ptr packet, - WifiMode mode, - WifiPreamble preamble, - uint8_t txPower) -{ - NS_LOG_FUNCTION(this << context << packet << "PHYTX mode=" << mode); - ++m_phyTxPkts; - uint32_t pktSize = packet->GetSize(); - m_phyTxBytes += pktSize; - - // NS_LOG_UNCOND ("Received PHY size=" << pktSize); -} - -void -WifiPhyStats::PhyTxDrop(std::string context, Ptr packet) -{ - NS_LOG_UNCOND("PHY Tx Drop"); -} - -void -WifiPhyStats::PhyRxDrop(std::string context, - Ptr packet, - WifiPhyRxfailureReason reason) -{ - NS_LOG_UNCOND("PHY Rx Drop"); -} - -uint32_t -WifiPhyStats::GetTxBytes() const -{ - return m_phyTxBytes; -} - -/** - * \ingroup wave - * \brief The WifiApp class enforces program flow for ns-3 wifi applications - */ -class WifiApp -{ - public: - /** - * \brief Constructor - */ - WifiApp(); - - /** - * \brief Destructor - */ - virtual ~WifiApp(); - - /** - * \brief Enacts simulation of an ns-3 wifi application - * \param argc program arguments count - * \param argv program arguments - */ - void Simulate(int argc, char** argv); - - protected: - /** - * \brief Sets default attribute values - */ - virtual void SetDefaultAttributeValues(); - - /** - * \brief Process command line arguments - * \param argc program arguments count - * \param argv program arguments - */ - virtual void ParseCommandLineArguments(int argc, char** argv); - - /** - * \brief Configure nodes - */ - virtual void ConfigureNodes(); - - /** - * \brief Configure channels - */ - virtual void ConfigureChannels(); - - /** - * \brief Configure devices - */ - virtual void ConfigureDevices(); - - /** - * \brief Configure mobility - */ - virtual void ConfigureMobility(); - - /** - * \brief Configure applications - */ - virtual void ConfigureApplications(); - - /** - * \brief Configure tracing - */ - virtual void ConfigureTracing(); - - /** - * \brief Run the simulation - */ - virtual void RunSimulation(); - - /** - * \brief Process outputs - */ - virtual void ProcessOutputs(); -}; - -WifiApp::WifiApp() -{ -} - -WifiApp::~WifiApp() -{ -} - -void -WifiApp::Simulate(int argc, char** argv) -{ - // Simulator Program Flow: - // (source: NS-3 Annual Meeting, May, 2014, session 2 slides 6, 28) - // (HandleProgramInputs:) - // SetDefaultAttributeValues - // ParseCommandLineArguments - // (ConfigureTopology:) - // ConfigureNodes - // ConfigureChannels - // ConfigureDevices - // ConfigureMobility - // ConfigureApplications - // e.g AddInternetStackToNodes - // ConfigureIpAddressingAndRouting - // configureSendMessages - // ConfigureTracing - // RunSimulation - // ProcessOutputs - - SetDefaultAttributeValues(); - ParseCommandLineArguments(argc, argv); - ConfigureNodes(); - ConfigureChannels(); - ConfigureDevices(); - ConfigureMobility(); - ConfigureApplications(); - ConfigureTracing(); - RunSimulation(); - ProcessOutputs(); -} - -void -WifiApp::SetDefaultAttributeValues() -{ -} - -void -WifiApp::ParseCommandLineArguments(int argc, char** argv) -{ -} - -void -WifiApp::ConfigureNodes() -{ -} - -void -WifiApp::ConfigureChannels() -{ -} - -void -WifiApp::ConfigureDevices() -{ -} - -void -WifiApp::ConfigureMobility() -{ -} - -void -WifiApp::ConfigureApplications() -{ -} - -void -WifiApp::ConfigureTracing() -{ -} - -void -WifiApp::RunSimulation() -{ -} - -void -WifiApp::ProcessOutputs() -{ -} - -/** - * \ingroup wave - * \brief The ConfigStoreHelper class simplifies config-store raw text load and save - */ -class ConfigStoreHelper -{ - public: - /** - * \brief Constructor - */ - ConfigStoreHelper(); - - /** - * \brief Loads a saved config-store raw text configuration from a given named file - * \param configFilename the name of the config-store raw text file - */ - void LoadConfig(std::string configFilename); - - /** - * \brief Saves a configuration to a given named config-store raw text configuration file - * \param configFilename the name of the config-store raw text file - */ - void SaveConfig(std::string configFilename); -}; - -ConfigStoreHelper::ConfigStoreHelper() -{ -} - -void -ConfigStoreHelper::LoadConfig(std::string configFilename) -{ - // Input config store from txt format - Config::SetDefault("ns3::ConfigStore::Filename", StringValue(configFilename)); - Config::SetDefault("ns3::ConfigStore::FileFormat", StringValue("RawText")); - Config::SetDefault("ns3::ConfigStore::Mode", StringValue("Load")); - ConfigStore inputConfig; - inputConfig.ConfigureDefaults(); - // inputConfig.ConfigureAttributes (); -} - -void -ConfigStoreHelper::SaveConfig(std::string configFilename) -{ - // only save if a non-empty filename has been specified - if (!configFilename.empty()) - { - // Output config store to txt format - Config::SetDefault("ns3::ConfigStore::Filename", StringValue(configFilename)); - Config::SetDefault("ns3::ConfigStore::FileFormat", StringValue("RawText")); - Config::SetDefault("ns3::ConfigStore::Mode", StringValue("Save")); - ConfigStore outputConfig; - outputConfig.ConfigureDefaults(); - // outputConfig.ConfigureAttributes (); - } -} - -/** - * \ingroup wave - * \brief The VanetRoutingExperiment class implements a wifi app that - * allows VANET routing experiments to be simulated - */ -class VanetRoutingExperiment : public WifiApp -{ - public: - /** - * \brief Constructor - */ - VanetRoutingExperiment(); - - protected: - /** - * \brief Sets default attribute values - */ - void SetDefaultAttributeValues() override; - - /** - * \brief Process command line arguments - * \param argc program arguments count - * \param argv program arguments - */ - void ParseCommandLineArguments(int argc, char** argv) override; - - /** - * \brief Configure nodes - */ - void ConfigureNodes() override; - - /** - * \brief Configure channels - */ - void ConfigureChannels() override; - - /** - * \brief Configure devices - */ - void ConfigureDevices() override; - - /** - * \brief Configure mobility - */ - void ConfigureMobility() override; - - /** - * \brief Configure applications - */ - void ConfigureApplications() override; - - /** - * \brief Configure tracing - */ - void ConfigureTracing() override; - - /** - * \brief Run the simulation - */ - void RunSimulation() override; - - /** - * \brief Process outputs - */ - void ProcessOutputs() override; - - private: - /** - * \brief Run the simulation - */ - void Run(); - - /** - * \brief Run the simulation - * \param argc command line argument count - * \param argv command line parameters - */ - void CommandSetup(int argc, char** argv); - - /** - * \brief Checks the throughput and outputs summary to CSV file1. - * This is scheduled and called once per second - */ - void CheckThroughput(); - - /** - * \brief Set up log file - */ - void SetupLogFile(); - - /** - * \brief Set up logging - */ - void SetupLogging(); - - /** - * \brief Configure default attributes - */ - void ConfigureDefaults(); - - /** - * \brief Set up the adhoc mobility nodes - */ - void SetupAdhocMobilityNodes(); - - /** - * \brief Set up the adhoc devices - */ - void SetupAdhocDevices(); - - /** - * \brief Set up generation of IEEE 1609 WAVE messages, - * as a Basic Safety Message (BSM). The BSM is typically - * a ~200-byte packets broadcast by all vehicles at a nominal - * rate of 10 Hz - */ - void SetupWaveMessages(); - - /** - * \brief Set up generation of packets to be routed - * through the vehicular network - */ - void SetupRoutingMessages(); - - /** - * \brief Set up a prescribed scenario - */ - void SetupScenario(); - - /** - * \brief Write the header line to the CSV file1 - */ - void WriteCsvHeader(); - - /** - * \brief Set up configuration parameter from the global variables - */ - void SetConfigFromGlobals(); - - /** - * \brief Set up the global variables from the configuration parameters - */ - void SetGlobalsFromConfig(); - - /** - * Course change function - * \param os the output stream - * \param context trace source context (unused) - * \param mobility the mobility model - */ - static void CourseChange(std::ostream* os, - std::string context, - Ptr mobility); - - uint32_t m_port; ///< port - std::string m_CSVfileName; ///< CSV file name - std::string m_CSVfileName2; ///< CSV file name - uint32_t m_nSinks; ///< number of sinks - std::string m_protocolName; ///< protocol name - double m_txp; ///< distance - bool m_traceMobility; ///< trace mobility - uint32_t m_protocol; ///< protocol - - uint32_t m_lossModel; ///< loss model - uint32_t m_fading; ///< fading - std::string m_lossModelName; ///< loss model name - - std::string m_phyMode; ///< phy mode - uint32_t m_80211mode; ///< 80211 mode - - std::string m_traceFile; ///< trace file - std::string m_logFile; ///< log file - uint32_t m_mobility; ///< mobility - uint32_t m_nNodes; ///< number of nodes - double m_TotalSimTime; ///< total sim time - std::string m_rate; ///< rate - std::string m_phyModeB; ///< phy mode - std::string m_trName; ///< trace file name - int m_nodeSpeed; ///< in m/s - int m_nodePause; ///< in s - uint32_t m_wavePacketSize; ///< bytes - double m_waveInterval; ///< seconds - bool m_verbose; ///< verbose - std::ofstream m_os; ///< output stream - NetDeviceContainer m_adhocTxDevices; ///< adhoc transmit devices - Ipv4InterfaceContainer m_adhocTxInterfaces; ///< adhoc transmit interfaces - uint32_t m_scenario; ///< scenario - double m_gpsAccuracyNs; ///< GPS accuracy - double m_txMaxDelayMs; ///< transmit maximum delay - bool m_routingTables; ///< routing tables - bool m_asciiTrace; ///< ascii trace - bool m_pcap; ///< PCAP - std::string m_loadConfigFilename; ///< load config file name - std::string m_saveConfigFilename; ///< save config file name - - WaveBsmHelper m_waveBsmHelper; ///< helper - Ptr m_routingHelper; ///< routing helper - Ptr m_wifiPhyStats; ///< wifi phy statistics - bool m_log; ///< log - int64_t m_streamIndex; ///< used to get consistent random numbers across scenarios - NodeContainer m_adhocTxNodes; ///< adhoc transmit nodes - double m_txSafetyRange1; ///< range 1 - double m_txSafetyRange2; ///< range 2 - double m_txSafetyRange3; ///< range 3 - double m_txSafetyRange4; ///< range 4 - double m_txSafetyRange5; ///< range 5 - double m_txSafetyRange6; ///< range 6 - double m_txSafetyRange7; ///< range 7 - double m_txSafetyRange8; ///< range 8 - double m_txSafetyRange9; ///< range 9 - double m_txSafetyRange10; ///< range 10 - std::vector m_txSafetyRanges; ///< list of ranges - std::string m_exp; ///< exp - Time m_cumulativeBsmCaptureStart; ///< capture start -}; - -VanetRoutingExperiment::VanetRoutingExperiment() - : m_port(9), - m_CSVfileName("vanet-routing.output.csv"), - m_CSVfileName2("vanet-routing.output2.csv"), - m_nSinks(10), - m_protocolName("protocol"), - m_txp(20), - m_traceMobility(false), - // AODV - m_protocol(2), - // Two-Ray ground - m_lossModel(3), - m_fading(0), - m_lossModelName(""), - m_phyMode("OfdmRate6MbpsBW10MHz"), - // 1=802.11p - m_80211mode(1), - m_traceFile(""), - m_logFile("low99-ct-unterstrass-1day.filt.7.adj.log"), - m_mobility(1), - m_nNodes(156), - m_TotalSimTime(300.01), - m_rate("2048bps"), - m_phyModeB("DsssRate11Mbps"), - m_trName("vanet-routing-compare"), - m_nodeSpeed(20), - m_nodePause(0), - m_wavePacketSize(200), - m_waveInterval(0.1), - m_verbose(false), - m_scenario(1), - m_gpsAccuracyNs(40), - m_txMaxDelayMs(10), - m_routingTables(false), - m_asciiTrace(false), - m_pcap(false), - m_loadConfigFilename("load-config.txt"), - m_saveConfigFilename(""), - m_log(false), - m_streamIndex(0), - m_adhocTxNodes(), - m_txSafetyRange1(50.0), - m_txSafetyRange2(100.0), - m_txSafetyRange3(150.0), - m_txSafetyRange4(200.0), - m_txSafetyRange5(250.0), - m_txSafetyRange6(300.0), - m_txSafetyRange7(350.0), - m_txSafetyRange8(400.0), - m_txSafetyRange9(450.0), - m_txSafetyRange10(500.0), - m_txSafetyRanges(), - m_exp(""), - m_cumulativeBsmCaptureStart(0) -{ - m_wifiPhyStats = CreateObject(); - m_routingHelper = CreateObject(); - - // simply uncond logging during simulation run - m_log = true; -} - -void -VanetRoutingExperiment::SetDefaultAttributeValues() -{ - // handled in constructor -} - -// important configuration items stored in global values - -/// Port -static ns3::GlobalValue g_port("VRCport", - "Port", - ns3::UintegerValue(9), - ns3::MakeUintegerChecker()); - -/// Number of sink nodes for routing non-BSM traffic -static ns3::GlobalValue g_nSinks("VRCnSinks", - "Number of sink nodes for routing non-BSM traffic", - ns3::UintegerValue(10), - ns3::MakeUintegerChecker()); - -/// Trace mobility 1=yes;0=no -static ns3::GlobalValue g_traceMobility("VRCtraceMobility", - "Enable trace mobility", - ns3::BooleanValue(false), - ns3::MakeBooleanChecker()); - -/// Routing protocol -static ns3::GlobalValue g_protocol("VRCprotocol", - "Routing protocol", - ns3::UintegerValue(2), - ns3::MakeUintegerChecker()); - -/// Propagation Loss Model -static ns3::GlobalValue g_lossModel("VRClossModel", - "Propagation Loss Model", - ns3::UintegerValue(3), - ns3::MakeUintegerChecker()); - -/// Fast Fading Model -static ns3::GlobalValue g_fading("VRCfading", - "Fast Fading Model", - ns3::UintegerValue(0), - ns3::MakeUintegerChecker()); - -/// 802.11 mode (0=802.11a;1=802.11p) -static ns3::GlobalValue g_80211mode("VRC80211mode", - "802.11 mode (0=802.11a;1=802.11p)", - ns3::UintegerValue(1), - ns3::MakeUintegerChecker()); - -/// Mobility mode 0=random waypoint;1=mobility trace file -static ns3::GlobalValue g_mobility("VRCmobility", - "Mobility mode 0=random waypoint;1=mobility trace file", - ns3::UintegerValue(1), - ns3::MakeUintegerChecker()); - -/// Number of nodes (vehicles) -static ns3::GlobalValue g_nNodes("VRCnNodes", - "Number of nodes (vehicles)", - ns3::UintegerValue(156), - ns3::MakeUintegerChecker()); - -/// Node speed (m/s) for RWP model -static ns3::GlobalValue g_nodeSpeed("VRCnodeSpeed", - "Node speed (m/s) for RWP model", - ns3::UintegerValue(20), - ns3::MakeUintegerChecker()); - -/// Node pause time (s) for RWP model -static ns3::GlobalValue g_nodePause("VRCnodePause", - "Node pause time (s) for RWP model", - ns3::UintegerValue(0), - ns3::MakeUintegerChecker()); - -/// Size in bytes of WAVE BSM -static ns3::GlobalValue g_wavePacketSize("VRCwavePacketSize", - "Size in bytes of WAVE BSM", - ns3::UintegerValue(200), - ns3::MakeUintegerChecker()); - -/// Verbose 0=no;1=yes -static ns3::GlobalValue g_verbose("VRCverbose", - "Enable verbose", - ns3::BooleanValue(false), - ns3::MakeBooleanChecker()); - -/// Scenario -static ns3::GlobalValue g_scenario("VRCscenario", - "Scenario", - ns3::UintegerValue(1), - ns3::MakeUintegerChecker()); - -/// Dump routing tables at t=5 seconds 0=no;1=yes -static ns3::GlobalValue g_routingTables("VRCroutingTables", - "Dump routing tables at t=5 seconds", - ns3::BooleanValue(false), - ns3::MakeBooleanChecker()); - -/// Dump ASCII trace 0=no;1=yes -static ns3::GlobalValue g_asciiTrace("VRCasciiTrace", - "Dump ASCII trace", - ns3::BooleanValue(false), - ns3::MakeBooleanChecker()); - -/// Generate PCAP files 0=no;1=yes -static ns3::GlobalValue g_pcap("VRCpcap", - "Generate PCAP files", - ns3::BooleanValue(false), - ns3::MakeBooleanChecker()); - -/// Simulation start time for capturing cumulative BSM -static ns3::GlobalValue g_cumulativeBsmCaptureStart( - "VRCcumulativeBsmCaptureStart", - "Simulation start time for capturing cumulative BSM", - ns3::TimeValue(Seconds(0)), - ns3::MakeTimeChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange1("VRCtxSafetyRange1", - "BSM range for PDR inclusion", - ns3::DoubleValue(50.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange2("VRCtxSafetyRange2", - "BSM range for PDR inclusion", - ns3::DoubleValue(100.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange3("VRCtxSafetyRange3", - "BSM range for PDR inclusion", - ns3::DoubleValue(150.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange4("VRCtxSafetyRange4", - "BSM range for PDR inclusion", - ns3::DoubleValue(200.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange5("VRCtxSafetyRange5", - "BSM range for PDR inclusion", - ns3::DoubleValue(250.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange6("VRCtxSafetyRange6", - "BSM range for PDR inclusion", - ns3::DoubleValue(300.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange7("VRCtxSafetyRange7", - "BSM range for PDR inclusion", - ns3::DoubleValue(350.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange8("VRCtxSafetyRange8", - "BSM range for PDR inclusion", - ns3::DoubleValue(400.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange9("VRCtxSafetyRange9", - "BSM range for PDR inclusion", - ns3::DoubleValue(450.0), - ns3::MakeDoubleChecker()); - -/// BSM range for PDR inclusion -static ns3::GlobalValue g_txSafetyRange10("VRCtxSafetyRange10", - "BSM range for PDR inclusion", - ns3::DoubleValue(500.0), - ns3::MakeDoubleChecker()); - -/// Transmission power dBm -static ns3::GlobalValue g_txp("VRCtxp", - "Transmission power dBm", - ns3::DoubleValue(7.5), - ns3::MakeDoubleChecker()); - -/// Total simulation time (s) -static ns3::GlobalValue g_totalTime("VRCtotalTime", - "Total simulation time (s)", - ns3::DoubleValue(300.01), - ns3::MakeDoubleChecker()); - -/// Interval (s) between WAVE BSMs -static ns3::GlobalValue g_waveInterval("VRCwaveInterval", - "Interval (s) between WAVE BSMs", - ns3::DoubleValue(0.1), - ns3::MakeDoubleChecker()); - -/// GPS sync accuracy (ns) -static ns3::GlobalValue g_gpsAccuracyNs("VRCgpsAccuracyNs", - "GPS sync accuracy (ns)", - ns3::DoubleValue(40), - ns3::MakeDoubleChecker()); - -/// Tx May Delay (ms) -static ns3::GlobalValue g_txMaxDelayMs("VRCtxMaxDelayMs", - "Tx May Delay (ms)", - ns3::DoubleValue(10), - ns3::MakeDoubleChecker()); - -/// CSV filename (for time series data) -static ns3::GlobalValue g_CSVfileName("VRCCSVfileName", - "CSV filename (for time series data)", - ns3::StringValue("vanet-routing.output.csv"), - ns3::MakeStringChecker()); - -/// CSV filename 2 (for overall simulation scenario results) -static ns3::GlobalValue g_CSVfileName2("VRCCSVfileName2", - "CSV filename 2 (for overall simulation scenario results)", - ns3::StringValue("vanet-routing.output2.csv"), - ns3::MakeStringChecker()); - -/// PHY mode (802.11p) -static ns3::GlobalValue g_phyMode("VRCphyMode", - "PHY mode (802.11p)", - ns3::StringValue("OfdmRate6MbpsBW10MHz"), - ns3::MakeStringChecker()); - -/// Mobility trace filename -static ns3::GlobalValue g_traceFile( - "VRCtraceFile", - "Mobility trace filename", - ns3::StringValue("./src/wave/examples/low99-ct-unterstrass-1day.filt.7.adj.mob"), - ns3::MakeStringChecker()); - -/// Log filename -static ns3::GlobalValue g_logFile("VRClogFile", - "Log filename", - ns3::StringValue("low99-ct-unterstrass-1day.filt.7.adj.log"), - ns3::MakeStringChecker()); - -/// Data rate -static ns3::GlobalValue g_rate("VRCrate", - "Data rate", - ns3::StringValue("2048bps"), - ns3::MakeStringChecker()); - -/// PHY mode (802.11a) -static ns3::GlobalValue g_phyModeB("VRCphyModeB", - "PHY mode (802.11a)", - ns3::StringValue("DsssRate11Mbps"), - ns3::MakeStringChecker()); - -/// Trace name) -static ns3::GlobalValue g_trName("VRCtrName", - "Trace name", - ns3::StringValue("vanet-routing-compare"), - ns3::MakeStringChecker()); - -void -VanetRoutingExperiment::ParseCommandLineArguments(int argc, char** argv) -{ - CommandSetup(argc, argv); - SetupScenario(); - - // user may specify up to 10 different tx distances - // to be used for calculating different values of Packet - // Delivery Ratio (PDR). Used to see the effects of - // fading over distance - m_txSafetyRanges.resize(10, 0); - m_txSafetyRanges[0] = m_txSafetyRange1; - m_txSafetyRanges[1] = m_txSafetyRange2; - m_txSafetyRanges[2] = m_txSafetyRange3; - m_txSafetyRanges[3] = m_txSafetyRange4; - m_txSafetyRanges[4] = m_txSafetyRange5; - m_txSafetyRanges[5] = m_txSafetyRange6; - m_txSafetyRanges[6] = m_txSafetyRange7; - m_txSafetyRanges[7] = m_txSafetyRange8; - m_txSafetyRanges[8] = m_txSafetyRange9; - m_txSafetyRanges[9] = m_txSafetyRange10; - - ConfigureDefaults(); - - // we are done with all configuration - // save config-store, if requested - SetGlobalsFromConfig(); - ConfigStoreHelper configStoreHelper; - configStoreHelper.SaveConfig(m_saveConfigFilename); - - m_waveBsmHelper.GetWaveBsmStats()->SetLogging(m_log); - m_routingHelper->SetLogging(m_log); -} - -void -VanetRoutingExperiment::ConfigureNodes() -{ - m_adhocTxNodes.Create(m_nNodes); -} - -void -VanetRoutingExperiment::ConfigureChannels() -{ - // set up channel and devices - SetupAdhocDevices(); -} - -void -VanetRoutingExperiment::ConfigureDevices() -{ - // devices are set up in SetupAdhocDevices(), - // called by ConfigureChannels() - - // use a PHY callback for tracing - // to determine the total amount of - // data transmitted, and then used to calculate - // the MAC/PHY overhead beyond the app-data - if (m_80211mode == 3) - { - // WAVE - Config::Connect("/NodeList/*/DeviceList/*/$ns3::WaveNetDevice/PhyEntities/*/State/Tx", - MakeCallback(&WifiPhyStats::PhyTxTrace, m_wifiPhyStats)); - Config::Connect("/NodeList/*/DeviceList/*/$ns3::WaveNetDevice/PhyEntities/*/PhyTxDrop", - MakeCallback(&WifiPhyStats::PhyTxDrop, m_wifiPhyStats)); - Config::Connect("/NodeList/*/DeviceList/*/$ns3::WaveNetDevice/PhyEntities/*/PhyRxDrop", - MakeCallback(&WifiPhyStats::PhyRxDrop, m_wifiPhyStats)); - } - else - { - Config::Connect("/NodeList/*/DeviceList/*/Phy/State/Tx", - MakeCallback(&WifiPhyStats::PhyTxTrace, m_wifiPhyStats)); - Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxDrop", - MakeCallback(&WifiPhyStats::PhyTxDrop, m_wifiPhyStats)); - Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop", - MakeCallback(&WifiPhyStats::PhyRxDrop, m_wifiPhyStats)); - } -} - -void -VanetRoutingExperiment::ConfigureMobility() -{ - SetupAdhocMobilityNodes(); -} - -void -VanetRoutingExperiment::ConfigureApplications() -{ - // Traffic mix consists of: - // 1. routing data - // 2. Broadcasting of Basic Safety Message (BSM) - SetupRoutingMessages(); - SetupWaveMessages(); - - // config trace to capture app-data (bytes) for - // routing data, subtracted and used for - // routing overhead - std::ostringstream oss; - oss.str(""); - oss << "/NodeList/*/ApplicationList/*/$ns3::OnOffApplication/Tx"; - Config::Connect(oss.str(), MakeCallback(&RoutingHelper::OnOffTrace, m_routingHelper)); -} - -void -VanetRoutingExperiment::ConfigureTracing() -{ - WriteCsvHeader(); - SetupLogFile(); - SetupLogging(); - - AsciiTraceHelper ascii; - MobilityHelper::EnableAsciiAll(ascii.CreateFileStream(m_trName + ".mob")); -} - -void -VanetRoutingExperiment::RunSimulation() -{ - Run(); -} - -void -VanetRoutingExperiment::ProcessOutputs() -{ - // calculate and output final results - double bsm_pdr1 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(1); - double bsm_pdr2 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(2); - double bsm_pdr3 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(3); - double bsm_pdr4 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(4); - double bsm_pdr5 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(5); - double bsm_pdr6 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(6); - double bsm_pdr7 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(7); - double bsm_pdr8 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(8); - double bsm_pdr9 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(9); - double bsm_pdr10 = m_waveBsmHelper.GetWaveBsmStats()->GetCumulativeBsmPdr(10); - - double averageRoutingGoodputKbps = 0.0; - uint32_t totalBytesTotal = m_routingHelper->GetRoutingStats().GetCumulativeRxBytes(); - averageRoutingGoodputKbps = (((double)totalBytesTotal * 8.0) / m_TotalSimTime) / 1000.0; - - // calculate MAC/PHY overhead (mac-phy-oh) - // total WAVE BSM bytes sent - uint32_t cumulativeWaveBsmBytes = m_waveBsmHelper.GetWaveBsmStats()->GetTxByteCount(); - uint32_t cumulativeRoutingBytes = m_routingHelper->GetRoutingStats().GetCumulativeTxBytes(); - uint32_t totalAppBytes = cumulativeWaveBsmBytes + cumulativeRoutingBytes; - uint32_t totalPhyBytes = m_wifiPhyStats->GetTxBytes(); - // mac-phy-oh = (total-phy-bytes - total-app-bytes) / total-phy-bytes - double mac_phy_oh = 0.0; - if (totalPhyBytes > 0) - { - mac_phy_oh = (double)(totalPhyBytes - totalAppBytes) / (double)totalPhyBytes; - } - - if (m_log) - { - NS_LOG_UNCOND("BSM_PDR1=" << bsm_pdr1 << " BSM_PDR2=" << bsm_pdr2 - << " BSM_PDR3=" << bsm_pdr3 << " BSM_PDR4=" << bsm_pdr4 - << " BSM_PDR5=" << bsm_pdr5 << " BSM_PDR6=" << bsm_pdr6 - << " BSM_PDR7=" << bsm_pdr7 << " BSM_PDR8=" << bsm_pdr8 - << " BSM_PDR9=" << bsm_pdr9 << " BSM_PDR10=" << bsm_pdr10 - << " Goodput=" << averageRoutingGoodputKbps - << "Kbps MAC/PHY-oh=" << mac_phy_oh); - } - - std::ofstream out(m_CSVfileName2, std::ios::app); - - out << bsm_pdr1 << "," << bsm_pdr2 << "," << bsm_pdr3 << "," << bsm_pdr4 << "," << bsm_pdr5 - << "," << bsm_pdr6 << "," << bsm_pdr7 << "," << bsm_pdr8 << "," << bsm_pdr9 << "," - << bsm_pdr10 << "," << averageRoutingGoodputKbps << "," << mac_phy_oh << "" << std::endl; - - out.close(); - - m_os.close(); // close log file -} - -void -VanetRoutingExperiment::Run() -{ - NS_LOG_INFO("Run Simulation."); - - CheckThroughput(); - - Simulator::Stop(Seconds(m_TotalSimTime)); - Simulator::Run(); - Simulator::Destroy(); -} - -// Prints actual position and velocity when a course change event occurs -void -VanetRoutingExperiment::CourseChange(std::ostream* os, - std::string context, - Ptr mobility) -{ - Vector pos = mobility->GetPosition(); // Get position - Vector vel = mobility->GetVelocity(); // Get velocity - - pos.z = 1.5; - - int nodeId = mobility->GetObject()->GetId(); - double t = (Simulator::Now()).GetSeconds(); - if (t >= 1.0) - { - WaveBsmHelper::GetNodesMoving()[nodeId] = 1; - } - - // NS_LOG_UNCOND ("Changing pos for node=" << nodeId << " at " << Simulator::Now () ); - - // Prints position and velocities - *os << Simulator::Now() << " POS: x=" << pos.x << ", y=" << pos.y << ", z=" << pos.z - << "; VEL:" << vel.x << ", y=" << vel.y << ", z=" << vel.z << std::endl; -} - -void -VanetRoutingExperiment::CheckThroughput() -{ - uint32_t bytesTotal = m_routingHelper->GetRoutingStats().GetRxBytes(); - uint32_t packetsReceived = m_routingHelper->GetRoutingStats().GetRxPkts(); - double kbps = (bytesTotal * 8.0) / 1000; - double wavePDR = 0.0; - int wavePktsSent = m_waveBsmHelper.GetWaveBsmStats()->GetTxPktCount(); - int wavePktsReceived = m_waveBsmHelper.GetWaveBsmStats()->GetRxPktCount(); - if (wavePktsSent > 0) - { - int wavePktsReceived = m_waveBsmHelper.GetWaveBsmStats()->GetRxPktCount(); - wavePDR = (double)wavePktsReceived / (double)wavePktsSent; - } - - int waveExpectedRxPktCount = m_waveBsmHelper.GetWaveBsmStats()->GetExpectedRxPktCount(1); - int waveRxPktInRangeCount = m_waveBsmHelper.GetWaveBsmStats()->GetRxPktInRangeCount(1); - double wavePDR1_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(1); - double wavePDR2_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(2); - double wavePDR3_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(3); - double wavePDR4_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(4); - double wavePDR5_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(5); - double wavePDR6_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(6); - double wavePDR7_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(7); - double wavePDR8_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(8); - double wavePDR9_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(9); - double wavePDR10_2 = m_waveBsmHelper.GetWaveBsmStats()->GetBsmPdr(10); - - // calculate MAC/PHY overhead (mac-phy-oh) - // total WAVE BSM bytes sent - uint32_t cumulativeWaveBsmBytes = m_waveBsmHelper.GetWaveBsmStats()->GetTxByteCount(); - uint32_t cumulativeRoutingBytes = m_routingHelper->GetRoutingStats().GetCumulativeTxBytes(); - uint32_t totalAppBytes = cumulativeWaveBsmBytes + cumulativeRoutingBytes; - uint32_t totalPhyBytes = m_wifiPhyStats->GetTxBytes(); - // mac-phy-oh = (total-phy-bytes - total-app-bytes) / total-phy-bytes - double mac_phy_oh = 0.0; - if (totalPhyBytes > 0) - { - mac_phy_oh = (double)(totalPhyBytes - totalAppBytes) / (double)totalPhyBytes; - } - - std::ofstream out(m_CSVfileName, std::ios::app); - - if (m_log) - { - NS_LOG_UNCOND("At t=" << (Simulator::Now()).As(Time::S) << " BSM_PDR1=" << wavePDR1_2 - << " BSM_PDR1=" << wavePDR2_2 << " BSM_PDR3=" << wavePDR3_2 - << " BSM_PDR4=" << wavePDR4_2 << " BSM_PDR5=" << wavePDR5_2 - << " BSM_PDR6=" << wavePDR6_2 << " BSM_PDR7=" << wavePDR7_2 - << " BSM_PDR8=" << wavePDR8_2 << " BSM_PDR9=" << wavePDR9_2 - << " BSM_PDR10=" << wavePDR10_2 << " Goodput=" << kbps - << "Kbps" /*<< " MAC/PHY-OH=" << mac_phy_oh*/); - } - - out << (Simulator::Now()).As(Time::S) << "," << kbps << "," << packetsReceived << "," - << m_nSinks << "," << m_protocolName << "," << m_txp << "," << wavePktsSent << "," - << wavePktsReceived << "," << wavePDR << "," << waveExpectedRxPktCount << "," - << waveRxPktInRangeCount << "," << wavePDR1_2 << "," << wavePDR2_2 << "," << wavePDR3_2 - << "," << wavePDR4_2 << "," << wavePDR5_2 << "," << wavePDR6_2 << "," << wavePDR7_2 << "," - << wavePDR8_2 << "," << wavePDR9_2 << "," << wavePDR10_2 << "," << mac_phy_oh << "" - << std::endl; - - out.close(); - - m_routingHelper->GetRoutingStats().SetRxBytes(0); - m_routingHelper->GetRoutingStats().SetRxPkts(0); - m_waveBsmHelper.GetWaveBsmStats()->SetRxPktCount(0); - m_waveBsmHelper.GetWaveBsmStats()->SetTxPktCount(0); - for (int index = 1; index <= 10; index++) - { - m_waveBsmHelper.GetWaveBsmStats()->SetExpectedRxPktCount(index, 0); - m_waveBsmHelper.GetWaveBsmStats()->SetRxPktInRangeCount(index, 0); - } - - Time currentTime = Simulator::Now(); - if (currentTime <= m_cumulativeBsmCaptureStart) - { - for (int index = 1; index <= 10; index++) - { - m_waveBsmHelper.GetWaveBsmStats()->ResetTotalRxPktCounts(index); - } - } - - Simulator::Schedule(Seconds(1.0), &VanetRoutingExperiment::CheckThroughput, this); -} - -void -VanetRoutingExperiment::SetConfigFromGlobals() -{ - // get settings saved from config-store - UintegerValue uintegerValue; - DoubleValue doubleValue; - StringValue stringValue; - TimeValue timeValue; - BooleanValue booleanValue; - - // This may not be the best way to manage program configuration - // (directing them through global values), but management - // through the config-store here is copied from - // src/lte/examples/lena-dual-stripe.cc - - GlobalValue::GetValueByName("VRCport", uintegerValue); - m_port = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCnSinks", uintegerValue); - m_nSinks = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCtraceMobility", booleanValue); - m_traceMobility = booleanValue.Get(); - GlobalValue::GetValueByName("VRCprotocol", uintegerValue); - m_protocol = uintegerValue.Get(); - GlobalValue::GetValueByName("VRClossModel", uintegerValue); - m_lossModel = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCfading", uintegerValue); - m_fading = uintegerValue.Get(); - GlobalValue::GetValueByName("VRC80211mode", uintegerValue); - m_80211mode = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCmobility", uintegerValue); - m_mobility = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCnNodes", uintegerValue); - m_nNodes = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCnodeSpeed", uintegerValue); - m_nodeSpeed = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCnodePause", uintegerValue); - m_nodePause = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCwavePacketSize", uintegerValue); - m_wavePacketSize = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCverbose", booleanValue); - m_verbose = booleanValue.Get(); - GlobalValue::GetValueByName("VRCscenario", uintegerValue); - m_scenario = uintegerValue.Get(); - GlobalValue::GetValueByName("VRCroutingTables", booleanValue); - m_routingTables = booleanValue.Get(); - GlobalValue::GetValueByName("VRCasciiTrace", booleanValue); - m_asciiTrace = booleanValue.Get(); - GlobalValue::GetValueByName("VRCpcap", booleanValue); - m_pcap = booleanValue.Get(); - GlobalValue::GetValueByName("VRCcumulativeBsmCaptureStart", timeValue); - m_cumulativeBsmCaptureStart = timeValue.Get(); - - GlobalValue::GetValueByName("VRCtxSafetyRange1", doubleValue); - m_txSafetyRange1 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange2", doubleValue); - m_txSafetyRange2 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange3", doubleValue); - m_txSafetyRange3 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange4", doubleValue); - m_txSafetyRange4 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange5", doubleValue); - m_txSafetyRange5 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange6", doubleValue); - m_txSafetyRange6 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange7", doubleValue); - m_txSafetyRange7 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange8", doubleValue); - m_txSafetyRange8 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange9", doubleValue); - m_txSafetyRange9 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxSafetyRange10", doubleValue); - m_txSafetyRange10 = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxp", doubleValue); - m_txp = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtotalTime", doubleValue); - m_TotalSimTime = doubleValue.Get(); - GlobalValue::GetValueByName("VRCwaveInterval", doubleValue); - m_waveInterval = doubleValue.Get(); - GlobalValue::GetValueByName("VRCgpsAccuracyNs", doubleValue); - m_gpsAccuracyNs = doubleValue.Get(); - GlobalValue::GetValueByName("VRCtxMaxDelayMs", doubleValue); - m_txMaxDelayMs = doubleValue.Get(); - - GlobalValue::GetValueByName("VRCCSVfileName", stringValue); - m_CSVfileName = stringValue.Get(); - GlobalValue::GetValueByName("VRCCSVfileName2", stringValue); - m_CSVfileName2 = stringValue.Get(); - GlobalValue::GetValueByName("VRCphyMode", stringValue); - m_phyMode = stringValue.Get(); - GlobalValue::GetValueByName("VRCtraceFile", stringValue); - m_traceFile = stringValue.Get(); - GlobalValue::GetValueByName("VRClogFile", stringValue); - m_logFile = stringValue.Get(); - GlobalValue::GetValueByName("VRCrate", stringValue); - m_rate = stringValue.Get(); - GlobalValue::GetValueByName("VRCphyModeB", stringValue); - m_phyModeB = stringValue.Get(); - GlobalValue::GetValueByName("VRCtrName", stringValue); - m_trName = stringValue.Get(); -} - -void -VanetRoutingExperiment::SetGlobalsFromConfig() -{ - // get settings saved from config-store - UintegerValue uintegerValue; - DoubleValue doubleValue; - StringValue stringValue; - - g_port.SetValue(UintegerValue(m_port)); - g_nSinks.SetValue(UintegerValue(m_nSinks)); - g_traceMobility.SetValue(BooleanValue(m_traceMobility)); - g_protocol.SetValue(UintegerValue(m_protocol)); - g_lossModel.SetValue(UintegerValue(m_lossModel)); - g_fading.SetValue(UintegerValue(m_fading)); - g_80211mode.SetValue(UintegerValue(m_80211mode)); - g_mobility.SetValue(UintegerValue(m_mobility)); - g_nNodes.SetValue(UintegerValue(m_nNodes)); - g_nodeSpeed.SetValue(UintegerValue(m_nodeSpeed)); - g_nodePause.SetValue(UintegerValue(m_nodePause)); - g_wavePacketSize.SetValue(UintegerValue(m_wavePacketSize)); - g_verbose.SetValue(BooleanValue(m_verbose)); - g_scenario.SetValue(UintegerValue(m_scenario)); - g_routingTables.SetValue(BooleanValue(m_routingTables)); - g_asciiTrace.SetValue(BooleanValue(m_asciiTrace)); - g_pcap.SetValue(BooleanValue(m_pcap)); - g_cumulativeBsmCaptureStart.SetValue(TimeValue(m_cumulativeBsmCaptureStart)); - - g_txSafetyRange1.SetValue(DoubleValue(m_txSafetyRange1)); - g_txSafetyRange2.SetValue(DoubleValue(m_txSafetyRange2)); - g_txSafetyRange3.SetValue(DoubleValue(m_txSafetyRange3)); - g_txSafetyRange4.SetValue(DoubleValue(m_txSafetyRange4)); - g_txSafetyRange5.SetValue(DoubleValue(m_txSafetyRange5)); - g_txSafetyRange6.SetValue(DoubleValue(m_txSafetyRange6)); - g_txSafetyRange7.SetValue(DoubleValue(m_txSafetyRange7)); - g_txSafetyRange8.SetValue(DoubleValue(m_txSafetyRange8)); - g_txSafetyRange9.SetValue(DoubleValue(m_txSafetyRange9)); - g_txSafetyRange10.SetValue(DoubleValue(m_txSafetyRange10)); - g_txp.SetValue(DoubleValue(m_txp)); - g_totalTime.SetValue(DoubleValue(m_TotalSimTime)); - g_waveInterval.SetValue(DoubleValue(m_waveInterval)); - g_gpsAccuracyNs.SetValue(DoubleValue(m_gpsAccuracyNs)); - g_txMaxDelayMs.SetValue(DoubleValue(m_txMaxDelayMs)); - - g_CSVfileName.SetValue(StringValue(m_CSVfileName)); - g_CSVfileName2.SetValue(StringValue(m_CSVfileName2)); - g_phyMode.SetValue(StringValue(m_phyMode)); - g_traceFile.SetValue(StringValue(m_traceFile)); - g_logFile.SetValue(StringValue(m_logFile)); - g_rate.SetValue(StringValue(m_rate)); - g_phyModeB.SetValue(StringValue(m_phyModeB)); - g_trName.SetValue(StringValue(m_trName)); - GlobalValue::GetValueByName("VRCtrName", stringValue); - m_trName = stringValue.Get(); -} - -void -VanetRoutingExperiment::CommandSetup(int argc, char** argv) -{ - CommandLine cmd(__FILE__); - double txDist1 = 50.0; - double txDist2 = 100.0; - double txDist3 = 150.0; - double txDist4 = 200.0; - double txDist5 = 250.0; - double txDist6 = 300.0; - double txDist7 = 350.0; - double txDist8 = 350.0; - double txDist9 = 350.0; - double txDist10 = 350.0; - - // allow command line overrides - cmd.AddValue("CSVfileName", "The name of the CSV output file name", m_CSVfileName); - cmd.AddValue("CSVfileName2", "The name of the CSV output file name2", m_CSVfileName2); - cmd.AddValue("totaltime", "Simulation end time", m_TotalSimTime); - cmd.AddValue("nodes", "Number of nodes (i.e. vehicles)", m_nNodes); - cmd.AddValue("sinks", "Number of routing sinks", m_nSinks); - cmd.AddValue("txp", "Transmit power (dB), e.g. txp=7.5", m_txp); - cmd.AddValue("traceMobility", "Enable mobility tracing", m_traceMobility); - cmd.AddValue("protocol", "1=OLSR;2=AODV;3=DSDV;4=DSR", m_protocol); - cmd.AddValue("lossModel", "1=Friis;2=ItuR1411Los;3=TwoRayGround;4=LogDistance", m_lossModel); - cmd.AddValue("fading", "0=None;1=Nakagami;(buildings=1 overrides)", m_fading); - cmd.AddValue("phyMode", "Wifi Phy mode", m_phyMode); - cmd.AddValue("80211Mode", "1=802.11p; 2=802.11b; 3=WAVE-PHY", m_80211mode); - cmd.AddValue("traceFile", "Ns2 movement trace file", m_traceFile); - cmd.AddValue("logFile", "Log file", m_logFile); - cmd.AddValue("mobility", "1=trace;2=RWP", m_mobility); - cmd.AddValue("rate", "Rate", m_rate); - cmd.AddValue("phyModeB", "Phy mode 802.11b", m_phyModeB); - cmd.AddValue("speed", "Node speed (m/s)", m_nodeSpeed); - cmd.AddValue("pause", "Node pause (s)", m_nodePause); - cmd.AddValue("verbose", "Enable verbose output", m_verbose); - cmd.AddValue("bsm", "(WAVE) BSM size (bytes)", m_wavePacketSize); - cmd.AddValue("interval", "(WAVE) BSM interval (s)", m_waveInterval); - cmd.AddValue("scenario", "1=synthetic, 2=playback-trace", m_scenario); - // User is allowed to have up to 10 different PDRs (Packet - // Delivery Ratios) calculate, and so can specify up to - // 10 different tx distances. - cmd.AddValue("txdist1", "Expected BSM tx range, m", txDist1); - cmd.AddValue("txdist2", "Expected BSM tx range, m", txDist2); - cmd.AddValue("txdist3", "Expected BSM tx range, m", txDist3); - cmd.AddValue("txdist4", "Expected BSM tx range, m", txDist4); - cmd.AddValue("txdist5", "Expected BSM tx range, m", txDist5); - cmd.AddValue("txdist6", "Expected BSM tx range, m", txDist6); - cmd.AddValue("txdist7", "Expected BSM tx range, m", txDist7); - cmd.AddValue("txdist8", "Expected BSM tx range, m", txDist8); - cmd.AddValue("txdist9", "Expected BSM tx range, m", txDist9); - cmd.AddValue("txdist10", "Expected BSM tx range, m", txDist10); - cmd.AddValue("gpsaccuracy", "GPS time accuracy, in ns", m_gpsAccuracyNs); - cmd.AddValue("txmaxdelay", "Tx max delay, in ms", m_txMaxDelayMs); - cmd.AddValue("routingTables", "Whether to dump routing tables at t=5 seconds", m_routingTables); - cmd.AddValue("asciiTrace", "Whether to dump ASCII Trace data", m_asciiTrace); - cmd.AddValue("pcap", "Whether to create PCAP files for all nodes", m_pcap); - cmd.AddValue("loadconfig", "Config-store filename to load", m_loadConfigFilename); - cmd.AddValue("saveconfig", "Config-store filename to save", m_saveConfigFilename); - cmd.AddValue("exp", "Experiment", m_exp); - cmd.AddValue("BsmCaptureStart", - "Start time to begin capturing pkts for cumulative Bsm", - m_cumulativeBsmCaptureStart); - cmd.Parse(argc, argv); - - m_txSafetyRange1 = txDist1; - m_txSafetyRange2 = txDist2; - m_txSafetyRange3 = txDist3; - m_txSafetyRange4 = txDist4; - m_txSafetyRange5 = txDist5; - m_txSafetyRange6 = txDist6; - m_txSafetyRange7 = txDist7; - m_txSafetyRange8 = txDist8; - m_txSafetyRange9 = txDist9; - m_txSafetyRange10 = txDist10; - // load configuration info from config-store - ConfigStoreHelper configStoreHelper; - configStoreHelper.LoadConfig(m_loadConfigFilename); - // transfer config-store values to config parameters - SetConfigFromGlobals(); - - // parse again so you can override input file default values via command line - cmd.Parse(argc, argv); - - m_txSafetyRange1 = txDist1; - m_txSafetyRange2 = txDist2; - m_txSafetyRange3 = txDist3; - m_txSafetyRange4 = txDist4; - m_txSafetyRange5 = txDist5; - m_txSafetyRange6 = txDist6; - m_txSafetyRange7 = txDist7; - m_txSafetyRange8 = txDist8; - m_txSafetyRange9 = txDist9; - m_txSafetyRange10 = txDist10; -} - -void -VanetRoutingExperiment::SetupLogFile() -{ - // open log file for output - m_os.open(m_logFile); -} - -void -VanetRoutingExperiment::SetupLogging() -{ - // Enable logging from the ns2 helper - LogComponentEnable("Ns2MobilityHelper", LOG_LEVEL_DEBUG); - - Packet::EnablePrinting(); -} - -void -VanetRoutingExperiment::ConfigureDefaults() -{ - Config::SetDefault("ns3::OnOffApplication::PacketSize", StringValue("64")); - Config::SetDefault("ns3::OnOffApplication::DataRate", StringValue(m_rate)); - - // Set Non-unicastMode rate to unicast mode - if (m_80211mode == 2) - { - Config::SetDefault("ns3::WifiRemoteStationManager::NonUnicastMode", - StringValue(m_phyModeB)); - } - else - { - Config::SetDefault("ns3::WifiRemoteStationManager::NonUnicastMode", StringValue(m_phyMode)); - } -} - -void -VanetRoutingExperiment::SetupAdhocMobilityNodes() -{ - if (m_mobility == 1) - { - // Create Ns2MobilityHelper with the specified trace log file as parameter - Ns2MobilityHelper ns2 = Ns2MobilityHelper(m_traceFile); - ns2.Install(); // configure movements for each node, while reading trace file - // initially assume all nodes are not moving - WaveBsmHelper::GetNodesMoving().resize(m_nNodes, 0); - } - else if (m_mobility == 2) - { - MobilityHelper mobilityAdhoc; - - ObjectFactory pos; - pos.SetTypeId("ns3::RandomBoxPositionAllocator"); - pos.Set("X", StringValue("ns3::UniformRandomVariable[Min=0.0|Max=1500.0]")); - pos.Set("Y", StringValue("ns3::UniformRandomVariable[Min=0.0|Max=300.0]")); - // we need antenna height uniform [1.0 .. 2.0] for loss model - pos.Set("Z", StringValue("ns3::UniformRandomVariable[Min=1.0|Max=2.0]")); - - Ptr taPositionAlloc = pos.Create()->GetObject(); - m_streamIndex += taPositionAlloc->AssignStreams(m_streamIndex); - - std::stringstream ssSpeed; - ssSpeed << "ns3::UniformRandomVariable[Min=0.0|Max=" << m_nodeSpeed << "]"; - std::stringstream ssPause; - ssPause << "ns3::ConstantRandomVariable[Constant=" << m_nodePause << "]"; - mobilityAdhoc.SetMobilityModel("ns3::RandomWaypointMobilityModel", - "Speed", - StringValue(ssSpeed.str()), - "Pause", - StringValue(ssPause.str()), - "PositionAllocator", - PointerValue(taPositionAlloc)); - mobilityAdhoc.SetPositionAllocator(taPositionAlloc); - mobilityAdhoc.Install(m_adhocTxNodes); - m_streamIndex += mobilityAdhoc.AssignStreams(m_adhocTxNodes, m_streamIndex); - - // initially assume all nodes are moving - WaveBsmHelper::GetNodesMoving().resize(m_nNodes, 1); - } - - // Configure callback for logging - Config::Connect("/NodeList/*/$ns3::MobilityModel/CourseChange", - MakeBoundCallback(&VanetRoutingExperiment::CourseChange, &m_os)); -} - -void -VanetRoutingExperiment::SetupAdhocDevices() -{ - if (m_lossModel == 1) - { - m_lossModelName = "ns3::FriisPropagationLossModel"; - } - else if (m_lossModel == 2) - { - m_lossModelName = "ns3::ItuR1411LosPropagationLossModel"; - } - else if (m_lossModel == 3) - { - m_lossModelName = "ns3::TwoRayGroundPropagationLossModel"; - } - else if (m_lossModel == 4) - { - m_lossModelName = "ns3::LogDistancePropagationLossModel"; - } - else - { - // Unsupported propagation loss model. - // Treating as ERROR - NS_LOG_ERROR("Invalid propagation loss model specified. Values must be [1-4], where " - "1=Friis;2=ItuR1411Los;3=TwoRayGround;4=LogDistance"); - } - - // frequency - double freq = 0.0; - if ((m_80211mode == 1) || (m_80211mode == 3)) - { - // 802.11p 5.9 GHz - freq = 5.9e9; - } - else - { - // 802.11b 2.4 GHz - freq = 2.4e9; - } - - // Setup propagation models - YansWifiChannelHelper wifiChannel; - wifiChannel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel"); - if (m_lossModel == 3) - { - // two-ray requires antenna height (else defaults to Friis) - wifiChannel.AddPropagationLoss(m_lossModelName, - "Frequency", - DoubleValue(freq), - "HeightAboveZ", - DoubleValue(1.5)); - } - else - { - wifiChannel.AddPropagationLoss(m_lossModelName, "Frequency", DoubleValue(freq)); - } - - // Propagation loss models are additive. - if (m_fading != 0) - { - // if no obstacle model, then use Nakagami fading if requested - wifiChannel.AddPropagationLoss("ns3::NakagamiPropagationLossModel"); - } - - // the channel - Ptr channel = wifiChannel.Create(); - - // The below set of helpers will help us to put together the wifi NICs we want - YansWifiPhyHelper wifiPhy; - wifiPhy.SetChannel(channel); - // ns-3 supports generate a pcap trace - wifiPhy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11); - - YansWavePhyHelper wavePhy = YansWavePhyHelper::Default(); - wavePhy.SetChannel(channel); - wavePhy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11); - - // Setup WAVE PHY and MAC - NqosWaveMacHelper wifi80211pMac = NqosWaveMacHelper::Default(); - WaveHelper waveHelper = WaveHelper::Default(); - Wifi80211pHelper wifi80211p = Wifi80211pHelper::Default(); - if (m_verbose) - { - Wifi80211pHelper::EnableLogComponents(); // Turn on all Wifi 802.11p logging - // likewise, turn on WAVE PHY logging - WaveHelper::EnableLogComponents(); - } - - WifiHelper wifi; - - // Setup 802.11b stuff - wifi.SetStandard(WIFI_STANDARD_80211b); - - wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue(m_phyModeB), - "ControlMode", - StringValue(m_phyModeB)); - - // Setup 802.11p stuff - wifi80211p.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue(m_phyMode), - "ControlMode", - StringValue(m_phyMode)); - - // Setup WAVE-PHY stuff - waveHelper.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue(m_phyMode), - "ControlMode", - StringValue(m_phyMode)); - - // Set Tx Power - wifiPhy.Set("TxPowerStart", DoubleValue(m_txp)); - wifiPhy.Set("TxPowerEnd", DoubleValue(m_txp)); - wavePhy.Set("TxPowerStart", DoubleValue(m_txp)); - wavePhy.Set("TxPowerEnd", DoubleValue(m_txp)); - - // Add an upper mac and disable rate control - WifiMacHelper wifiMac; - wifiMac.SetType("ns3::AdhocWifiMac"); - QosWaveMacHelper waveMac = QosWaveMacHelper::Default(); - - // Setup net devices - - if (m_80211mode == 3) - { - m_adhocTxDevices = waveHelper.Install(wavePhy, waveMac, m_adhocTxNodes); - } - else if (m_80211mode == 1) - { - m_adhocTxDevices = wifi80211p.Install(wifiPhy, wifi80211pMac, m_adhocTxNodes); - } - else - { - m_adhocTxDevices = wifi.Install(wifiPhy, wifiMac, m_adhocTxNodes); - } - - if (m_asciiTrace) - { - AsciiTraceHelper ascii; - Ptr osw = ascii.CreateFileStream(m_trName + ".tr"); - wifiPhy.EnableAsciiAll(osw); - wavePhy.EnableAsciiAll(osw); - } - if (m_pcap) - { - wifiPhy.EnablePcapAll("vanet-routing-compare-pcap"); - wavePhy.EnablePcapAll("vanet-routing-compare-pcap"); - } -} - -void -VanetRoutingExperiment::SetupWaveMessages() -{ - // WAVE PHY mode - // 0=continuous channel; 1=channel-switching - int chAccessMode = 0; - if (m_80211mode == 3) - { - chAccessMode = 1; - } - - m_waveBsmHelper.Install(m_adhocTxInterfaces, - Seconds(m_TotalSimTime), - m_wavePacketSize, - Seconds(m_waveInterval), - // GPS accuracy (i.e, clock drift), in number of ns - m_gpsAccuracyNs, - m_txSafetyRanges, - chAccessMode, - // tx max delay before transmit, in ms - MilliSeconds(m_txMaxDelayMs)); - - // fix random number streams - m_streamIndex += m_waveBsmHelper.AssignStreams(m_adhocTxNodes, m_streamIndex); -} - -void -VanetRoutingExperiment::SetupRoutingMessages() -{ - m_routingHelper->Install(m_adhocTxNodes, - m_adhocTxDevices, - m_adhocTxInterfaces, - m_TotalSimTime, - m_protocol, - m_nSinks, - m_routingTables); -} - -void -VanetRoutingExperiment::SetupScenario() -{ - // member variable parameter use - // defaults or command line overrides, - // except where scenario={1,2,3,...} - // have been specified, in which case - // specify parameters are overwritten - // here to setup for specific scenarios - - // certain parameters may be further overridden - // i.e. specify a scenario, override tx power. - - if (m_scenario == 1) - { - // 40 nodes in RWP 300 m x 1500 m synthetic highway, 10s - m_traceFile = ""; - m_logFile = ""; - m_mobility = 2; - if (m_nNodes == 156) - { - m_nNodes = 40; - } - if (m_TotalSimTime == 300.01) - { - m_TotalSimTime = 10.0; - } - } - else if (m_scenario == 2) - { - // Realistic vehicular trace in 4.6 km x 3.0 km suburban Zurich - // "low density, 99 total vehicles" - m_traceFile = "src/wave/examples/low99-ct-unterstrass-1day.filt.7.adj.mob"; - m_logFile = "low99-ct-unterstrass-1day.filt.7.adj.log"; - m_mobility = 1; - m_nNodes = 99; - m_TotalSimTime = 300.01; - m_nodeSpeed = 0; - m_nodePause = 0; - m_CSVfileName = "low_vanet-routing-compare.csv"; - m_CSVfileName = "low_vanet-routing-compare2.csv"; - } -} - -void -VanetRoutingExperiment::WriteCsvHeader() -{ - // blank out the last output file and write the column headers - std::ofstream out(m_CSVfileName); - out << "SimulationSecond," - << "ReceiveRate," - << "PacketsReceived," - << "NumberOfSinks," - << "RoutingProtocol," - << "TransmissionPower," - << "WavePktsSent," - << "WavePtksReceived," - << "WavePktsPpr," - << "ExpectedWavePktsReceived," - << "ExpectedWavePktsInCoverageReceived," - << "BSM_PDR1," - << "BSM_PDR2," - << "BSM_PDR3," - << "BSM_PDR4," - << "BSM_PDR5," - << "BSM_PDR6," - << "BSM_PDR7," - << "BSM_PDR8," - << "BSM_PDR9," - << "BSM_PDR10," - << "MacPhyOverhead" << std::endl; - out.close(); - - std::ofstream out2(m_CSVfileName2); - out2 << "BSM_PDR1," - << "BSM_PDR2," - << "BSM_PDR3," - << "BSM_PDR4," - << "BSM_PDR5," - << "BSM_PDR6," - << "BSM_PDR7," - << "BSM_PDR8," - << "BSM_PDR9," - << "BSM_PDR10," - << "AverageRoutingGoodputKbps," - << "MacPhyOverhead" << std::endl; - out2.close(); -} - -int -main(int argc, char* argv[]) -{ - VanetRoutingExperiment experiment; - experiment.Simulate(argc, argv); - - return 0; -} diff --git a/src/wave/examples/wave-simple-80211p.cc b/src/wave/examples/wave-simple-80211p.cc deleted file mode 100644 index db036b783..000000000 --- a/src/wave/examples/wave-simple-80211p.cc +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2005,2006,2007 INRIA - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Author: Junling Bu - * - */ -/** - * This example shows basic construction of an 802.11p node. Two nodes - * are constructed with 802.11p devices, and by default, one node sends a single - * packet to another node (the number of packets and interval between - * them can be configured by command-line arguments). The example shows - * typical usage of the helper classes for this mode of WiFi (where "OCB" refers - * to "Outside the Context of a BSS")." - */ - -#include "ns3/command-line.h" -#include "ns3/config.h" -#include "ns3/double.h" -#include "ns3/internet-stack-helper.h" -#include "ns3/ipv4-address-helper.h" -#include "ns3/ipv4-interface-container.h" -#include "ns3/log.h" -#include "ns3/mobility-helper.h" -#include "ns3/mobility-model.h" -#include "ns3/ocb-wifi-mac.h" -#include "ns3/position-allocator.h" -#include "ns3/socket.h" -#include "ns3/string.h" -#include "ns3/vector.h" -#include "ns3/wave-mac-helper.h" -#include "ns3/wifi-80211p-helper.h" -#include "ns3/yans-wifi-helper.h" - -#include - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE("WifiSimpleOcb"); - -/* - * In WAVE module, there is no net device class named like "Wifi80211pNetDevice", - * instead, we need to use Wifi80211pHelper to create an object of - * WifiNetDevice class. - * - * usage: - * NodeContainer nodes; - * NetDeviceContainer devices; - * nodes.Create (2); - * YansWifiPhyHelper wifiPhy; - * YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); - * wifiPhy.SetChannel (wifiChannel.Create ()); - * NqosWaveMacHelper wifi80211pMac = NqosWave80211pMacHelper::Default(); - * Wifi80211pHelper wifi80211p = Wifi80211pHelper::Default (); - * devices = wifi80211p.Install (wifiPhy, wifi80211pMac, nodes); - * - * The reason of not providing a 802.11p class is that most of modeling - * 802.11p standard has been done in wifi module, so we only need a high - * MAC class that enables OCB mode. - */ - -/** - * Receive a packet - * \param socket Rx socket - */ -void -ReceivePacket(Ptr socket) -{ - while (socket->Recv()) - { - NS_LOG_UNCOND("Received one packet!"); - } -} - -/** - * Geerate traffic - * \param socket Tx socket - * \param pktSize packet size - * \param pktCount number of packets - * \param pktInterval interval between packet generation - */ -static void -GenerateTraffic(Ptr socket, uint32_t pktSize, uint32_t pktCount, Time pktInterval) -{ - if (pktCount > 0) - { - socket->Send(Create(pktSize)); - Simulator::Schedule(pktInterval, - &GenerateTraffic, - socket, - pktSize, - pktCount - 1, - pktInterval); - } - else - { - socket->Close(); - } -} - -int -main(int argc, char* argv[]) -{ - std::string phyMode("OfdmRate6MbpsBW10MHz"); - uint32_t packetSize = 1000; // bytes - uint32_t numPackets = 1; - double interval = 1.0; // seconds - bool verbose = false; - - CommandLine cmd(__FILE__); - - cmd.AddValue("phyMode", "Wifi Phy mode", phyMode); - cmd.AddValue("packetSize", "size of application packet sent", packetSize); - cmd.AddValue("numPackets", "number of packets generated", numPackets); - cmd.AddValue("interval", "interval (seconds) between packets", interval); - cmd.AddValue("verbose", "turn on all WifiNetDevice log components", verbose); - cmd.Parse(argc, argv); - // Convert to time object - Time interPacketInterval = Seconds(interval); - - NodeContainer c; - c.Create(2); - - // The below set of helpers will help us to put together the wifi NICs we want - YansWifiPhyHelper wifiPhy; - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); - Ptr channel = wifiChannel.Create(); - wifiPhy.SetChannel(channel); - // ns-3 supports generate a pcap trace - wifiPhy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11); - NqosWaveMacHelper wifi80211pMac = NqosWaveMacHelper::Default(); - Wifi80211pHelper wifi80211p = Wifi80211pHelper::Default(); - if (verbose) - { - Wifi80211pHelper::EnableLogComponents(); // Turn on all Wifi 802.11p logging - } - - wifi80211p.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue(phyMode), - "ControlMode", - StringValue(phyMode)); - NetDeviceContainer devices = wifi80211p.Install(wifiPhy, wifi80211pMac, c); - - // Tracing - wifiPhy.EnablePcap("wave-simple-80211p", devices); - - MobilityHelper mobility; - Ptr positionAlloc = CreateObject(); - positionAlloc->Add(Vector(0.0, 0.0, 0.0)); - positionAlloc->Add(Vector(5.0, 0.0, 0.0)); - mobility.SetPositionAllocator(positionAlloc); - mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); - mobility.Install(c); - - InternetStackHelper internet; - internet.Install(c); - - Ipv4AddressHelper ipv4; - NS_LOG_INFO("Assign IP Addresses."); - ipv4.SetBase("10.1.1.0", "255.255.255.0"); - Ipv4InterfaceContainer i = ipv4.Assign(devices); - - TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory"); - Ptr recvSink = Socket::CreateSocket(c.Get(0), tid); - InetSocketAddress local = InetSocketAddress(Ipv4Address::GetAny(), 80); - recvSink->Bind(local); - recvSink->SetRecvCallback(MakeCallback(&ReceivePacket)); - - Ptr source = Socket::CreateSocket(c.Get(1), tid); - InetSocketAddress remote = InetSocketAddress(Ipv4Address("255.255.255.255"), 80); - source->SetAllowBroadcast(true); - source->Connect(remote); - - Simulator::ScheduleWithContext(source->GetNode()->GetId(), - Seconds(1.0), - &GenerateTraffic, - source, - packetSize, - numPackets, - interPacketInterval); - - Simulator::Run(); - Simulator::Destroy(); - - return 0; -} diff --git a/src/wave/examples/wave-simple-device.cc b/src/wave/examples/wave-simple-device.cc deleted file mode 100644 index af5a6972b..000000000 --- a/src/wave/examples/wave-simple-device.cc +++ /dev/null @@ -1,302 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#include "ns3/command-line.h" -#include "ns3/mobility-helper.h" -#include "ns3/net-device-container.h" -#include "ns3/node-container.h" -#include "ns3/node.h" -#include "ns3/packet.h" -#include "ns3/seq-ts-header.h" -#include "ns3/simulator.h" -#include "ns3/wave-helper.h" -#include "ns3/wave-mac-helper.h" -#include "ns3/wave-net-device.h" -#include "ns3/yans-wifi-helper.h" - -using namespace ns3; - -/** - * This simulation is to show the routing service of WaveNetDevice described in IEEE 09.4. - * - * note: although txPowerLevel is supported now, the "TxPowerLevels" - * attribute of YansWifiPhy is 1 which means phy devices only support 1 - * levels. Thus, if users want to control txPowerLevel, they should set - * these attributes of YansWifiPhy by themselves.. - */ -class WaveNetDeviceExample -{ - public: - /// Send WSMP example function - void SendWsmpExample(); - - /// Send IP example function - void SendIpExample(); - - /// Send WSA example - void SendWsaExample(); - - private: - /** - * Send one WSMP packet function - * \param channel the channel to use - * \param seq the sequence - */ - void SendOneWsmpPacket(uint32_t channel, uint32_t seq); - /** - * Send IP packet function - * \param seq the sequence - * \param ipv6 true if IPV6 - */ - void SendIpPacket(uint32_t seq, bool ipv6); - /** - * Receive function - * \param dev the device - * \param pkt the packet - * \param mode the mode - * \param sender the sender address - * \returns true if successful - */ - bool Receive(Ptr dev, Ptr pkt, uint16_t mode, const Address& sender); - /** - * Receive VSA function - * \param pkt the packet - * \param address the address - * \returns true if successful - */ - bool ReceiveVsa(Ptr pkt, const Address& address, uint32_t, uint32_t); - /// Create WAVE nodes function - void CreateWaveNodes(); - - NodeContainer nodes; ///< the nodes - NetDeviceContainer devices; ///< the devices -}; - -void -WaveNetDeviceExample::CreateWaveNodes() -{ - nodes = NodeContainer(); - nodes.Create(2); - - MobilityHelper mobility; - Ptr positionAlloc = CreateObject(); - positionAlloc->Add(Vector(0.0, 0.0, 0.0)); - positionAlloc->Add(Vector(5.0, 0.0, 0.0)); - mobility.SetPositionAllocator(positionAlloc); - mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); - mobility.Install(nodes); - - YansWifiChannelHelper waveChannel = YansWifiChannelHelper::Default(); - YansWavePhyHelper wavePhy = YansWavePhyHelper::Default(); - wavePhy.SetChannel(waveChannel.Create()); - wavePhy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11); - QosWaveMacHelper waveMac = QosWaveMacHelper::Default(); - WaveHelper waveHelper = WaveHelper::Default(); - devices = waveHelper.Install(wavePhy, waveMac, nodes); - - for (uint32_t i = 0; i != devices.GetN(); ++i) - { - Ptr device = DynamicCast(devices.Get(i)); - device->SetReceiveCallback(MakeCallback(&WaveNetDeviceExample::Receive, this)); - device->SetWaveVsaCallback(MakeCallback(&WaveNetDeviceExample::ReceiveVsa, this)); - } - - // Tracing - wavePhy.EnablePcap("wave-simple-device", devices); -} - -bool -WaveNetDeviceExample::Receive(Ptr dev, - Ptr pkt, - uint16_t mode, - const Address& sender) -{ - SeqTsHeader seqTs; - pkt->PeekHeader(seqTs); - std::cout << "receive a packet: " << std::endl - << " sequence = " << seqTs.GetSeq() << "," << std::endl - << " sendTime = " << seqTs.GetTs().As(Time::S) << "," << std::endl - << " recvTime = " << Now().As(Time::S) << "," << std::endl - << " protocol = 0x" << std::hex << mode << std::dec << std::endl; - return true; -} - -void -WaveNetDeviceExample::SendOneWsmpPacket(uint32_t channel, uint32_t seq) -{ - Ptr sender = DynamicCast(devices.Get(0)); - Ptr receiver = DynamicCast(devices.Get(1)); - const static uint16_t WSMP_PROT_NUMBER = 0x88DC; - Mac48Address bssWildcard = Mac48Address::GetBroadcast(); - - const TxInfo txInfo = TxInfo(channel); - Ptr p = Create(100); - SeqTsHeader seqTs; - seqTs.SetSeq(seq); - p->AddHeader(seqTs); - sender->SendX(p, bssWildcard, WSMP_PROT_NUMBER, txInfo); -} - -void -WaveNetDeviceExample::SendWsmpExample() -{ - CreateWaveNodes(); - Ptr sender = DynamicCast(devices.Get(0)); - Ptr receiver = DynamicCast(devices.Get(1)); - - // Alternating access without immediate channel switch - const SchInfo schInfo = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, sender, schInfo); - // An important point is that the receiver should also be assigned channel - // access for the same channel to receive packets. - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, receiver, schInfo); - - // send WSMP packets - // the first packet will be queued currently and be transmitted in next SCH interval - Simulator::Schedule(Seconds(1.0), &WaveNetDeviceExample::SendOneWsmpPacket, this, SCH1, 1); - // the second packet will be queued currently and then be transmitted , because of in the CCH - // interval. - Simulator::Schedule(Seconds(1.0), &WaveNetDeviceExample::SendOneWsmpPacket, this, CCH, 2); - // the third packet will be dropped because of no channel access for SCH2. - Simulator::Schedule(Seconds(1.0), &WaveNetDeviceExample::SendOneWsmpPacket, this, SCH2, 3); - - // release SCH access - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::StopSch, sender, SCH1); - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::StopSch, receiver, SCH1); - // the fourth packet will be queued and be transmitted because of default CCH access assigned - // automatically. - Simulator::Schedule(Seconds(3.0), &WaveNetDeviceExample::SendOneWsmpPacket, this, CCH, 4); - // the fifth packet will be dropped because of no SCH1 access assigned - Simulator::Schedule(Seconds(3.0), &WaveNetDeviceExample::SendOneWsmpPacket, this, SCH1, 5); - - Simulator::Stop(Seconds(5.0)); - Simulator::Run(); - Simulator::Destroy(); -} - -void -WaveNetDeviceExample::SendIpPacket(uint32_t seq, bool ipv6) -{ - Ptr sender = DynamicCast(devices.Get(0)); - Ptr receiver = DynamicCast(devices.Get(1)); - const Address dest = receiver->GetAddress(); - // send IPv4 packet or IPv6 packet - const static uint16_t IPv4_PROT_NUMBER = 0x0800; - const static uint16_t IPv6_PROT_NUMBER = 0x86DD; - uint16_t protocol = ipv6 ? IPv6_PROT_NUMBER : IPv4_PROT_NUMBER; - Ptr p = Create(100); - SeqTsHeader seqTs; - seqTs.SetSeq(seq); - p->AddHeader(seqTs); - sender->Send(p, dest, protocol); -} - -void -WaveNetDeviceExample::SendIpExample() -{ - CreateWaveNodes(); - Ptr sender = DynamicCast(devices.Get(0)); - Ptr receiver = DynamicCast(devices.Get(1)); - - // Alternating access without immediate channel switch - const SchInfo schInfo = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, sender, schInfo); - // An important point is that the receiver should also be assigned channel - // access for the same channel to receive packets. - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, receiver, schInfo); - - // both IPv4 and IPv6 packets below will not be inserted to internal queue because of no tx - // profile registered - Simulator::Schedule(Seconds(1.0), &WaveNetDeviceExample::SendIpPacket, this, 1, true); - Simulator::Schedule(Seconds(1.050), &WaveNetDeviceExample::SendIpPacket, this, 2, false); - // register txprofile - // IP packets will automatically be sent with txprofile parameter - const TxProfile txProfile = TxProfile(SCH1); - Simulator::Schedule(Seconds(2.0), &WaveNetDevice::RegisterTxProfile, sender, txProfile); - // both IPv4 and IPv6 packet are transmitted successfully - Simulator::Schedule(Seconds(3.0), &WaveNetDeviceExample::SendIpPacket, this, 3, true); - Simulator::Schedule(Seconds(3.050), &WaveNetDeviceExample::SendIpPacket, this, 4, false); - // unregister TxProfile or release channel access - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::DeleteTxProfile, sender, SCH1); - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::StopSch, sender, SCH1); - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::StopSch, receiver, SCH1); - // these packets will be dropped again because of no channel access assigned and no tx profile - // registered - Simulator::Schedule(Seconds(5.0), &WaveNetDeviceExample::SendIpPacket, this, 5, true); - Simulator::Schedule(Seconds(5.050), &WaveNetDeviceExample::SendIpPacket, this, 6, false); - - Simulator::Stop(Seconds(6.0)); - Simulator::Run(); - Simulator::Destroy(); -} - -bool -WaveNetDeviceExample::ReceiveVsa(Ptr pkt, const Address& address, uint32_t, uint32_t) -{ - std::cout << "receive a VSA management frame: recvTime = " << Now().As(Time::S) << "." - << std::endl; - return true; -} - -void -WaveNetDeviceExample::SendWsaExample() -{ - CreateWaveNodes(); - Ptr sender = DynamicCast(devices.Get(0)); - Ptr receiver = DynamicCast(devices.Get(1)); - - // Alternating access without immediate channel switch for sender and receiver - const SchInfo schInfo = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, sender, schInfo); - Simulator::Schedule(Seconds(0.0), &WaveNetDevice::StartSch, receiver, schInfo); - - // the peer address of VSA is broadcast address, and the repeat rate - // of VsaInfo is 100 per 5s, the VSA frame will be sent repeatedly. - Ptr wsaPacket = Create(100); - Mac48Address dest = Mac48Address::GetBroadcast(); - const VsaInfo vsaInfo = - VsaInfo(dest, OrganizationIdentifier(), 0, wsaPacket, SCH1, 100, VSA_TRANSMIT_IN_BOTHI); - Simulator::Schedule(Seconds(1.0), &WaveNetDevice::StartVsa, sender, vsaInfo); - Simulator::Schedule(Seconds(3.0), &WaveNetDevice::StopVsa, sender, SCH1); - - // release alternating access - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::StopSch, sender, SCH1); - Simulator::Schedule(Seconds(4.0), &WaveNetDevice::StopSch, receiver, SCH1); - - // these WSA packets cannot be transmitted because of no channel access assigned - Simulator::Schedule(Seconds(5.0), &WaveNetDevice::StartVsa, sender, vsaInfo); - Simulator::Schedule(Seconds(6.0), &WaveNetDevice::StopVsa, sender, SCH1); - - Simulator::Stop(Seconds(6.0)); - Simulator::Run(); - Simulator::Destroy(); -} - -int -main(int argc, char* argv[]) -{ - CommandLine cmd(__FILE__); - cmd.Parse(argc, argv); - - WaveNetDeviceExample example; - std::cout << "run WAVE WSMP routing service case:" << std::endl; - example.SendWsmpExample(); - std::cout << "run WAVE IP routing service case:" << std::endl; - // example.SendIpExample (); - std::cout << "run WAVE WSA routing service case:" << std::endl; - // example.SendWsaExample (); - return 0; -} diff --git a/src/wave/helper/wave-bsm-helper.cc b/src/wave/helper/wave-bsm-helper.cc deleted file mode 100644 index 70c389d17..000000000 --- a/src/wave/helper/wave-bsm-helper.cc +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2014 North Carolina State University - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Scott E. Carpenter - * - */ - -#include "ns3/wave-bsm-helper.h" - -#include "ns3/log.h" - -NS_LOG_COMPONENT_DEFINE("WaveBsmHelper"); - -namespace ns3 -{ - -std::vector WaveBsmHelper::nodesMoving; - -WaveBsmHelper::WaveBsmHelper() - : m_waveBsmStats() -{ - m_txSafetyRangesSq.resize(10, 0); - m_txSafetyRangesSq[0] = 50.0 * 50.0; - m_txSafetyRangesSq[1] = 100.0 * 100.0; - m_txSafetyRangesSq[2] = 200.0 * 200.0; - m_txSafetyRangesSq[3] = 300.0 * 300.0; - m_txSafetyRangesSq[4] = 400.0 * 400.0; - m_txSafetyRangesSq[5] = 500.0 * 500.0; - m_txSafetyRangesSq[6] = 600.0 * 600.0; - m_txSafetyRangesSq[7] = 800.0 * 800.0; - m_txSafetyRangesSq[8] = 1000.0 * 1000.0; - m_txSafetyRangesSq[9] = 1500.0 * 1500.0; - - m_factory.SetTypeId("ns3::BsmApplication"); -} - -void -WaveBsmHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -WaveBsmHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -WaveBsmHelper::Install(Ipv4InterfaceContainer i) const -{ - ApplicationContainer apps; - for (Ipv4InterfaceContainer::Iterator itr = i.Begin(); itr != i.End(); ++itr) - { - std::pair, uint32_t> interface = (*itr); - Ptr pp = interface.first; - Ptr node = pp->GetObject(); - apps.Add(InstallPriv(node)); - } - - return apps; -} - -Ptr -WaveBsmHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - -void -WaveBsmHelper::Install(Ipv4InterfaceContainer& i, - Time totalTime, // seconds - uint32_t wavePacketSize, // bytes - Time waveInterval, // seconds - double gpsAccuracyNs, // clock drift range in number of ns - std::vector ranges, // m - int chAccessMode, // channel access mode - Time txMaxDelay) // max delay prior to transmit -{ - int size = ranges.size(); - m_txSafetyRangesSq.clear(); - m_txSafetyRangesSq.resize(size, 0); - for (int index = 0; index < size; index++) - { - // stored as square of value, for optimization - m_txSafetyRangesSq[index] = ranges[index] * ranges[index]; - } - - // install a BsmApplication on each node - ApplicationContainer bsmApps = Install(i); - // start BSM app immediately (BsmApplication will - // delay transmission of first BSM by 1.0 seconds) - bsmApps.Start(Seconds(0)); - bsmApps.Stop(totalTime); - - // for each app, setup the app parameters - ApplicationContainer::Iterator aci; - int nodeId = 0; - for (aci = bsmApps.Begin(); aci != bsmApps.End(); ++aci) - { - Ptr bsmApp = DynamicCast(*aci); - bsmApp->Setup(i, - nodeId, - totalTime, - wavePacketSize, - waveInterval, - gpsAccuracyNs, - m_txSafetyRangesSq, - GetWaveBsmStats(), - &nodesMoving, - chAccessMode, - txMaxDelay); - nodeId++; - } -} - -Ptr -WaveBsmHelper::GetWaveBsmStats() -{ - return &m_waveBsmStats; -} - -int64_t -WaveBsmHelper::AssignStreams(NodeContainer c, int64_t stream) -{ - int64_t currentStream = stream; - Ptr node; - for (NodeContainer::Iterator i = c.Begin(); i != c.End(); ++i) - { - node = (*i); - for (uint32_t j = 0; j < node->GetNApplications(); j++) - { - Ptr bsmApp = DynamicCast(node->GetApplication(j)); - if (bsmApp) - { - currentStream += bsmApp->AssignStreams(currentStream); - } - } - } - return (currentStream - stream); -} - -std::vector& -WaveBsmHelper::GetNodesMoving() -{ - return nodesMoving; -} - -} // namespace ns3 diff --git a/src/wave/helper/wave-bsm-helper.h b/src/wave/helper/wave-bsm-helper.h deleted file mode 100644 index d1009a182..000000000 --- a/src/wave/helper/wave-bsm-helper.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2014 North Carolina State University - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Scott E. Carpenter - * - */ - -#ifndef WAVE_BSM_HELPER_H -#define WAVE_BSM_HELPER_H - -#include "ns3/application-container.h" -#include "ns3/bsm-application.h" -#include "ns3/internet-stack-helper.h" -#include "ns3/mobility-model.h" -#include "ns3/nstime.h" -#include "ns3/object-factory.h" -#include "ns3/wave-bsm-stats.h" - -#include - -namespace ns3 -{ -/** - * \ingroup wave - * \brief The WaveBsmHelper class manages - * IEEE 1609 WAVE (Wireless Access in Vehicular Environments) - * Basic Safety Messages (BSMs) and uses the WaveBsmStats class - * to manage statistics about BSMs transmitted and received - * The BSM is a ~200-byte packet that is - * generally broadcast from every vehicle at a nominal rate of 10 Hz. - */ -class WaveBsmHelper -{ - public: - /** - * \brief Constructor - */ - WaveBsmHelper(); - - /** - * Helper function used to set the underlying application attributes. - * - * \param name the name of the application attribute to set - * \param value the value of the application attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); - - /** - * Install an ns3::BsmApplication on each node of the input container - * configured with all the attributes set with SetAttribute. - * - * \param i Ipv4InterfaceContainer of the set of interfaces on which an BsmApplication - * will be installed on the nodes. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(Ipv4InterfaceContainer i) const; - - /** - * Install an ns3::BsmApplication on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an BsmApplication will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(Ptr node) const; - - /** - * \brief Installs BSM generation on devices for nodes - * and their interfaces - * \param i IPv4 interface container - * \param totalTime total amount of time that BSM packets should be transmitted - * \param wavePacketSize the size, in bytes, of a WAVE BSM - * \param waveInterval the time, in seconds, between each WAVE BSM transmission, - * typically 10 Hz (0.1 second) - * \param gpsAccuracyNs the timing synchronization accuracy of GPS time, in nanoseconds. - * GPS time-sync is ~40-100 ns. Universally synchronized time among all vehicles - * will result in all vehicles transmitting safety messages simultaneously, leading - * to excessive wireless collisions. - * \param ranges the expected transmission range, in m. - * \param chAccessMode channel access mode (0=continuous; 1=switching) - * \param txMaxDelay max delay prior to transmit - */ - void Install(Ipv4InterfaceContainer& i, - Time totalTime, // seconds - uint32_t wavePacketSize, // bytes - Time waveInterval, // seconds - double gpsAccuracyNs, // clock drift range in number of ns - std::vector ranges, // m - int chAccessMode, // channel access mode (0=continuous; 1=switching) - Time txMaxDelay); // max delay prior to transmit - - /** - * \brief Returns the WaveBsmStats instance - * \return the WaveBsmStats instance - */ - Ptr GetWaveBsmStats(); - - /** - * Assign a fixed random variable stream number to the random variables - * used by this model. Return the number of streams (possibly zero) that - * have been assigned. The Install() method should have previously been - * called by the user. - * - * \param stream first stream index to use - * \param c NodeContainer of the set of nodes for which the BsmApplication - * should be modified to use a fixed stream - * \return the number of stream indices assigned by this helper - */ - int64_t AssignStreams(NodeContainer c, int64_t stream); - - /** - * \brief Returns the list of moving nove indicators - * \return the list of moving node indicators - */ - static std::vector& GetNodesMoving(); - - private: - /** - * Install an ns3::BsmApplication on the node - * - * \param node The node on which an BsmApplication will be installed. - * \returns Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - - ObjectFactory m_factory; //!< Object factory. - WaveBsmStats m_waveBsmStats; ///< wave BSM stats - /// tx safety range squared, for optimization - std::vector m_txSafetyRangesSq; - static std::vector nodesMoving; ///< nodes moving -}; - -} // namespace ns3 - -#endif /* WAVE_BSM_HELPER_H*/ diff --git a/src/wave/helper/wave-bsm-stats.cc b/src/wave/helper/wave-bsm-stats.cc deleted file mode 100644 index ad98680e9..000000000 --- a/src/wave/helper/wave-bsm-stats.cc +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2014 North Carolina State University - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Scott E. Carpenter - * - */ - -#include "ns3/wave-bsm-stats.h" - -#include "ns3/integer.h" -#include "ns3/log.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("WaveBsmStats"); - -WaveBsmStats::WaveBsmStats() - : m_wavePktSendCount(0), - m_waveByteSendCount(0), - m_wavePktReceiveCount(0), - m_log(false) -{ - m_wavePktExpectedReceiveCounts.resize(10, 0); - m_wavePktInCoverageReceiveCounts.resize(10, 0); - m_waveTotalPktExpectedReceiveCounts.resize(10, 0); - m_waveTotalPktInCoverageReceiveCounts.resize(10, 0); -} - -/* static */ -TypeId -WaveBsmStats::GetTypeId() -{ - static TypeId tid = TypeId("ns3::WaveBsmStats") - .SetParent() - .SetGroupName("Stats") - .AddConstructor(); - return tid; -} - -void -WaveBsmStats::IncTxPktCount() -{ - m_wavePktSendCount++; -} - -int -WaveBsmStats::GetTxPktCount() const -{ - return m_wavePktSendCount; -} - -void -WaveBsmStats::IncExpectedRxPktCount(int index) -{ - m_wavePktExpectedReceiveCounts[index - 1]++; - m_waveTotalPktExpectedReceiveCounts[index - 1]++; -} - -void -WaveBsmStats::IncRxPktCount() -{ - m_wavePktReceiveCount++; -} - -void -WaveBsmStats::IncRxPktInRangeCount(int index) -{ - m_wavePktInCoverageReceiveCounts[index - 1]++; - m_waveTotalPktInCoverageReceiveCounts[index - 1]++; -} - -int -WaveBsmStats::GetRxPktCount() const -{ - return m_wavePktReceiveCount; -} - -int -WaveBsmStats::GetExpectedRxPktCount(int index) -{ - return m_wavePktExpectedReceiveCounts[index - 1]; -} - -int -WaveBsmStats::GetRxPktInRangeCount(int index) -{ - return m_wavePktInCoverageReceiveCounts[index - 1]; -} - -void -WaveBsmStats::SetTxPktCount(int count) -{ - m_wavePktSendCount = count; -} - -void -WaveBsmStats::SetRxPktCount(int count) -{ - m_wavePktReceiveCount = count; -} - -void -WaveBsmStats::IncTxByteCount(int bytes) -{ - m_waveByteSendCount += bytes; -} - -int -WaveBsmStats::GetTxByteCount() const -{ - return m_waveByteSendCount; -} - -double -WaveBsmStats::GetBsmPdr(int index) -{ - double pdr = 0.0; - - if (m_wavePktExpectedReceiveCounts[index - 1] > 0) - { - pdr = (double)m_wavePktInCoverageReceiveCounts[index - 1] / - (double)m_wavePktExpectedReceiveCounts[index - 1]; - // due to node movement, it is - // possible to receive a packet that is not slightly "within range" that was - // transmitted at the time when the nodes were slightly "out of range" - // thus, prevent overflow of PDR > 100% - if (pdr > 1.0) - { - pdr = 1.0; - } - } - - return pdr; -} - -double -WaveBsmStats::GetCumulativeBsmPdr(int index) -{ - double pdr = 0.0; - - if (m_waveTotalPktExpectedReceiveCounts[index - 1] > 0) - { - pdr = (double)m_waveTotalPktInCoverageReceiveCounts[index - 1] / - (double)m_waveTotalPktExpectedReceiveCounts[index - 1]; - // due to node movement, it is - // possible to receive a packet that is not slightly "within range" that was - // transmitted at the time when the nodes were slightly "out of range" - // thus, prevent overflow of PDR > 100% - if (pdr > 1.0) - { - pdr = 1.0; - } - } - - return pdr; -} - -void -WaveBsmStats::SetLogging(bool log) -{ - m_log = log; -} - -bool -WaveBsmStats::GetLogging() const -{ - return m_log; -} - -void -WaveBsmStats::SetExpectedRxPktCount(int index, int count) -{ - m_wavePktExpectedReceiveCounts[index - 1] = count; -} - -void -WaveBsmStats::SetRxPktInRangeCount(int index, int count) -{ - m_wavePktInCoverageReceiveCounts[index - 1] = count; -} - -void -WaveBsmStats::ResetTotalRxPktCounts(int index) -{ - m_waveTotalPktInCoverageReceiveCounts[index - 1] = 0; - m_waveTotalPktExpectedReceiveCounts[index - 1] = 0; -} - -} // namespace ns3 diff --git a/src/wave/helper/wave-bsm-stats.h b/src/wave/helper/wave-bsm-stats.h deleted file mode 100644 index a27134db1..000000000 --- a/src/wave/helper/wave-bsm-stats.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2014 North Carolina State University - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Scott E. Carpenter - * - */ - -#ifndef WAVE_BSM_STATS_H -#define WAVE_BSM_STATS_H - -#include "ns3/object.h" - -#include - -namespace ns3 -{ -/** - * \ingroup wave - * \brief The WaveBsmStats class implements a stats collector for - * IEEE 1609 WAVE (Wireless Access in Vehicular Environments) - * Basic Safety Messages (BSMs). The BSM is a ~200-byte packet that is - * generally broadcast from every vehicle at a nominal rate of 10 Hz. - * - * \internal - * Note: This class collects data elements and accessors - * along with methods that calculate metrics from the data - * elements. The data and metrics calculation algorithms - * are collected together here purely to keep them together. - * Future work may need to add additional metric calculations, - * and for now, we are trying to keep all related data and - * algorithms together, although these could easily be - * refactored in the future and moved to separate classes. - * However, it seems that for now, moving the data elements - * or the algorithms separately into different classes could - * lead to confusion over usage. - */ -class WaveBsmStats : public Object -{ - public: - /** - * \brief Constructor - */ - WaveBsmStats(); - - /** - * Register this type. - * \return The TypeId. - */ - static TypeId GetTypeId(); - - /** - * \brief Increments the count of transmitted packets - */ - void IncTxPktCount(); - - /** - * \brief Returns the count of transmitted packets - * \return count of packets transmitted - */ - int GetTxPktCount() const; - - /* - * Note: - * The WAVE Basic Safety Message (BSM) is broadcast and - * unacknowledged. In order to calculate packet delivery - * ratio (PDR), we must count i) the packets that are - * actually received and ii) the transmitted packets that - * are expected to be received. Both are relative to a - * specified (circular) coverage area. - * - * For example: Say we have three nodes, A, B, and C, each - * separated by 40m, as follows: - * - * A --<40m>-- B --<40m>-- C - * - * Let's assume that the transmission range is 50m, and only - * A is transmitting (i.e. broadcasting). B can receive A's - * broadcasts, while C cannot. Let's assume no dropped packets. - * If we set the coverage area to 100m, then the PDR is 50%, - * because B receives every transmission from A, while C receives - * none of them. However, if we change the effective - * coverage area to 75m then the PDR improves to 100%, because - * B receives 100% of A's transmissions, and C is outside of the - * coverage area, and so does not factor in to the PDR. - */ - - /** - * \brief Increments the count of (broadcast) packets expected - * to be received within the coverage area1. Broadcast packets - * (i.e. WAVE Basic Safety Messages) are not ACK'd. For packet - * delivery ratio (PDR), we need to count transmitted packets that - * are expected to be received within the coverage area, even - * though they may not be physically received (due to collisions - * or receiver power thresholds). - * \param index index for statistics - */ - void IncExpectedRxPktCount(int index); - - /** - * \brief Increments the count of actual packets received - * (regardless of coverage area). - */ - void IncRxPktCount(); - - /** - * \brief Increments the count of actual packets received within - * the coverage area(index). Broadcast packets - * (i.e. WAVE Basic Safety Messages) are not ACK'd. For packet - * delivery ratio (PDR), we need to count only those received packets - * that are actually received within the (circular) coverage area. - * \param index index for statistics - */ - void IncRxPktInRangeCount(int index); - - /** - * \brief Returns the count of packets received - * \return the count of packets received - */ - int GetRxPktCount() const; - - /** - * \brief Returns the count of expected packets received within range(index) - * \param index index for statistics - * \return the count of expected packets received within range(index) - */ - int GetExpectedRxPktCount(int index); - - /** - * \brief Increments the count of actual packets received within range(index) - * \param index index for statistics - * \return the count of actual packets received within range(index) - */ - int GetRxPktInRangeCount(int index); - - /** - * \brief Sets the count of packets expected to received - * \param index index for statistics - * \param count the count of packets - */ - void SetExpectedRxPktCount(int index, int count); - - /** - * \brief Sets the count of packets within range that are received - * \param index index for statistics - * \param count the count of packets - */ - void SetRxPktInRangeCount(int index, int count); - - /** - * \brief Resets the count of total packets - * expected and/or within range(index) that are received - * \param index index for statistics - */ - void ResetTotalRxPktCounts(int index); - - /** - * \brief Sets the count of packets transmitted - * \param count the count of packets transmitted - */ - void SetTxPktCount(int count); - - /** - * \brief Sets the count of packets received - * \param count the count of packets received - */ - void SetRxPktCount(int count); - - /** - * \brief Increments the count of (application data) bytes transmitted - * not including MAC/PHY overhead - * \param bytes the bytes of application-data transmitted - */ - void IncTxByteCount(int bytes); - - /** - * \brief Returns the count of (application data) bytes transmitted - * not include MAC/PHY overhead - * \return number of bytes of application-data transmitted - */ - int GetTxByteCount() const; - - /** - * \brief Returns the BSM Packet Delivery Ratio (PDR) - * which is the percent of expected packets within range(index) that - * are actually received - * \param index index for statistics - * \return the packet delivery ratio (PDR) of BSMs. - */ - double GetBsmPdr(int index); - - /** - * \brief Returns the cumulative BSM Packet Delivery Ratio (PDR) - * which is the percent of cumulative expected packets within range(index) - * that are actually received - * \param index index for statistics - * \return the packet delivery ratio (PDR) of BSMs. - */ - double GetCumulativeBsmPdr(int index); - - /** - * \brief Enables/disables logging - * \param log logging state - */ - void SetLogging(bool log); - - /** - * \brief Gets logging state - * \return logging state - */ - bool GetLogging() const; - - private: - int m_wavePktSendCount; ///< packet sent count - int m_waveByteSendCount; ///< byte sent count - int m_wavePktReceiveCount; ///< packet receive count - std::vector m_wavePktInCoverageReceiveCounts; ///< packet in coverage receive counts - std::vector m_wavePktExpectedReceiveCounts; ///< packet expected receive counts - std::vector - m_waveTotalPktInCoverageReceiveCounts; ///< total packet in coverage receive counts - std::vector m_waveTotalPktExpectedReceiveCounts; ///< total packet expected receive counts - bool m_log; ///< logging state -}; - -} // namespace ns3 - -#endif /* WAVE_BSM_STATS_H*/ diff --git a/src/wave/helper/wave-helper.cc b/src/wave/helper/wave-helper.cc deleted file mode 100644 index cc4b5e05e..000000000 --- a/src/wave/helper/wave-helper.cc +++ /dev/null @@ -1,476 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ - -#include "wave-helper.h" - -#include "wave-mac-helper.h" - -#include "ns3/abort.h" -#include "ns3/config.h" -#include "ns3/log.h" -#include "ns3/minstrel-wifi-manager.h" -#include "ns3/names.h" -#include "ns3/pointer.h" -#include "ns3/qos-txop.h" -#include "ns3/radiotap-header.h" -#include "ns3/string.h" -#include "ns3/wave-net-device.h" - -NS_LOG_COMPONENT_DEFINE("WaveHelper"); - -namespace ns3 -{ - -/** - * ASCII Phy transmit sink with context - * \param stream the output stream - * \param context the context - * \param p the packet - * \param mode the mode - * \param preamble the preamble - * \param txLevel transmit level - */ -static void -AsciiPhyTransmitSinkWithContext(Ptr stream, - std::string context, - Ptr p, - WifiMode mode [[maybe_unused]], - WifiPreamble preamble [[maybe_unused]], - uint8_t txLevel [[maybe_unused]]) -{ - NS_LOG_FUNCTION(stream << context << p << mode << preamble << txLevel); - *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << context << " " << *p - << std::endl; -} - -/** - * ASCII Phy transmit sink without context - * \param stream the output stream - * \param p the packet - * \param mode the mode - * \param preamble the preamble - * \param txLevel transmit level - */ -static void -AsciiPhyTransmitSinkWithoutContext(Ptr stream, - Ptr p, - WifiMode mode, - WifiPreamble preamble, - uint8_t txLevel) -{ - NS_LOG_FUNCTION(stream << p << mode << preamble << txLevel); - *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << *p << std::endl; -} - -/** - * ASCII Phy receive sink with context - * \param stream the output stream - * \param context the context - * \param p the packet - * \param snr the SNR - * \param mode the mode - * \param preamble the preamble - */ -static void -AsciiPhyReceiveSinkWithContext(Ptr stream, - std::string context, - Ptr p, - double snr, - WifiMode mode, - WifiPreamble preamble) -{ - NS_LOG_FUNCTION(stream << context << p << snr << mode << preamble); - *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << context << " " << *p - << std::endl; -} - -/** - * ASCII Phy receive sink without context - * \param stream the output stream - * \param p the packet - * \param snr the SNR - * \param mode the mode - * \param preamble the preamble - */ -static void -AsciiPhyReceiveSinkWithoutContext(Ptr stream, - Ptr p, - double snr, - WifiMode mode, - WifiPreamble preamble) -{ - NS_LOG_FUNCTION(stream << p << snr << mode << preamble); - *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << *p << std::endl; -} - -/****************************** YansWavePhyHelper ***********************************/ -YansWavePhyHelper -YansWavePhyHelper::Default() -{ - YansWavePhyHelper helper; - helper.SetErrorRateModel("ns3::NistErrorRateModel"); - return helper; -} - -void -YansWavePhyHelper::EnablePcapInternal(std::string prefix, - Ptr nd, - bool /* promiscuous */, - bool explicitFilename) -{ - // - // All of the Pcap enable functions vector through here including the ones - // that are wandering through all of devices on perhaps all of the nodes in - // the system. We can only deal with devices of type WaveNetDevice. - // - Ptr device = nd->GetObject(); - if (!device) - { - NS_LOG_INFO("YansWavePhyHelper::EnablePcapInternal(): Device " - << &device << " not of type ns3::WaveNetDevice"); - return; - } - - std::vector> phys = device->GetPhys(); - NS_ABORT_MSG_IF(phys.empty(), "EnablePcapInternal(): Phy layer in WaveNetDevice must be set"); - - PcapHelper pcapHelper; - - std::string filename; - if (explicitFilename) - { - filename = prefix; - } - else - { - filename = pcapHelper.GetFilenameFromDevice(prefix, device); - } - - Ptr file = - pcapHelper.CreateFile(filename, std::ios::out, GetPcapDataLinkType()); - - std::vector>::iterator i; - for (i = phys.begin(); i != phys.end(); ++i) - { - Ptr phy = (*i); - phy->TraceConnectWithoutContext( - "MonitorSnifferTx", - MakeBoundCallback(&YansWavePhyHelper::PcapSniffTxEvent, file)); - phy->TraceConnectWithoutContext( - "MonitorSnifferRx", - MakeBoundCallback(&YansWavePhyHelper::PcapSniffRxEvent, file)); - } -} - -void -YansWavePhyHelper::EnableAsciiInternal(Ptr stream, - std::string prefix, - Ptr nd, - bool explicitFilename) -{ - // - // All of the ascii enable functions vector through here including the ones - // that are wandering through all of devices on perhaps all of the nodes in - // the system. We can only deal with devices of type WaveNetDevice. - // - Ptr device = nd->GetObject(); - if (!device) - { - NS_LOG_INFO("EnableAsciiInternal(): Device " << device - << " not of type ns3::WaveNetDevice"); - return; - } - - // - // Our trace sinks are going to use packet printing, so we have to make sure - // that is turned on. - // - Packet::EnablePrinting(); - - uint32_t nodeid = nd->GetNode()->GetId(); - uint32_t deviceid = nd->GetIfIndex(); - std::ostringstream oss; - - // - // If we are not provided an OutputStreamWrapper, we are expected to create - // one using the usual trace filename conventions and write our traces - // without a context since there will be one file per context and therefore - // the context would be redundant. - // - if (!stream) - { - // - // Set up an output stream object to deal with private ofstream copy - // constructor and lifetime issues. Let the helper decide the actual - // name of the file given the prefix. - // - AsciiTraceHelper asciiTraceHelper; - - std::string filename; - if (explicitFilename) - { - filename = prefix; - } - else - { - filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device); - } - - Ptr theStream = asciiTraceHelper.CreateFileStream(filename); - // - // We could go poking through the phy and the state looking for the - // correct trace source, but we can let Config deal with that with - // some search cost. Since this is presumably happening at topology - // creation time, it doesn't seem much of a price to pay. - // - oss.str(""); - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid - << "/$ns3::WaveNetDevice/PhyEntities/*/$ns3::WifiPhy/State/RxOk"; - Config::ConnectWithoutContext( - oss.str(), - MakeBoundCallback(&AsciiPhyReceiveSinkWithoutContext, theStream)); - - oss.str(""); - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid - << "/$ns3::WaveNetDevice/PhyEntities/*/$ns3::WifiPhy/State/Tx"; - Config::ConnectWithoutContext( - oss.str(), - MakeBoundCallback(&AsciiPhyTransmitSinkWithoutContext, theStream)); - - return; - } - - // - // If we are provided an OutputStreamWrapper, we are expected to use it, and - // to provide a context. We are free to come up with our own context if we - // want, and use the AsciiTraceHelper Hook*WithContext functions, but for - // compatibility and simplicity, we just use Config::Connect and let it deal - // with coming up with a context. - // - oss.str(""); - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid - << "/$ns3::WaveNetDevice/PhyEntities/*/$ns3::WifiPhy/RxOk"; - Config::Connect(oss.str(), MakeBoundCallback(&AsciiPhyReceiveSinkWithContext, stream)); - - oss.str(""); - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid - << "/$ns3::WaveNetDevice/PhyEntities/*/$ns3::WifiPhy/State/Tx"; - Config::Connect(oss.str(), MakeBoundCallback(&AsciiPhyTransmitSinkWithContext, stream)); -} - -/********************************** WaveHelper ******************************************/ -WaveHelper::WaveHelper() -{ -} - -WaveHelper::~WaveHelper() -{ -} - -WaveHelper -WaveHelper::Default() -{ - WaveHelper helper; - // default 7 MAC entities and single PHY device. - helper.CreateMacForChannel(ChannelManager::GetWaveChannels()); - helper.CreatePhys(1); - helper.SetChannelScheduler("ns3::DefaultChannelScheduler"); - helper.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue("OfdmRate6MbpsBW10MHz"), - "ControlMode", - StringValue("OfdmRate6MbpsBW10MHz"), - "NonUnicastMode", - StringValue("OfdmRate6MbpsBW10MHz")); - return helper; -} - -void -WaveHelper::CreateMacForChannel(std::vector channelNumbers) -{ - if (channelNumbers.empty()) - { - NS_FATAL_ERROR("the WAVE MAC entities is at least one"); - } - for (std::vector::iterator i = channelNumbers.begin(); i != channelNumbers.end(); ++i) - { - if (!ChannelManager::IsWaveChannel(*i)) - { - NS_FATAL_ERROR("the channel number " << (*i) << " is not a valid WAVE channel number"); - } - } - m_macsForChannelNumber = channelNumbers; -} - -void -WaveHelper::CreatePhys(uint32_t phys) -{ - if (phys == 0) - { - NS_FATAL_ERROR("the WAVE PHY entities is at least one"); - } - if (phys > ChannelManager::GetNumberOfWaveChannels()) - { - NS_FATAL_ERROR("the number of assigned WAVE PHY entities is more than the number of valid " - "WAVE channels"); - } - m_physNumber = phys; -} - -NetDeviceContainer -WaveHelper::Install(const WifiPhyHelper& phyHelper, - const WifiMacHelper& macHelper, - NodeContainer c) const -{ - try - { - const QosWaveMacHelper& qosMac [[maybe_unused]] = - dynamic_cast(macHelper); - } - catch (const std::bad_cast&) - { - NS_FATAL_ERROR("WifiMacHelper should be the class or subclass of QosWaveMacHelper"); - } - - NetDeviceContainer devices; - for (NodeContainer::Iterator i = c.Begin(); i != c.End(); ++i) - { - Ptr node = *i; - Ptr device = CreateObject(); - - device->SetChannelManager(CreateObject()); - device->SetChannelCoordinator(CreateObject()); - device->SetVsaManager(CreateObject()); - device->SetChannelScheduler(m_channelScheduler.Create()); - - for (uint32_t j = 0; j != m_physNumber; ++j) - { - std::vector> phys = phyHelper.Create(node, device); - NS_ABORT_IF(phys.size() != 1); - phys[0]->ConfigureStandard(WIFI_STANDARD_80211p); - phys[0]->SetOperatingChannel( - WifiPhy::ChannelTuple{ChannelManager::GetCch(), 0, WIFI_PHY_BAND_5GHZ, 0}); - device->AddPhy(phys[0]); - } - - for (std::vector::const_iterator k = m_macsForChannelNumber.begin(); - k != m_macsForChannelNumber.end(); - ++k) - { - Ptr wifiMac = macHelper.Create(device, WIFI_STANDARD_80211p); - Ptr ocbMac = DynamicCast(wifiMac); - ocbMac->SetWifiRemoteStationManager( - m_stationManager.Create()); - ocbMac->EnableForWave(device); - device->AddMac(*k, ocbMac); - } - - device->SetAddress(Mac48Address::Allocate()); - - node->AddDevice(device); - devices.Add(device); - } - return devices; -} - -NetDeviceContainer -WaveHelper::Install(const WifiPhyHelper& phy, const WifiMacHelper& mac, Ptr node) const -{ - return Install(phy, mac, NodeContainer(node)); -} - -NetDeviceContainer -WaveHelper::Install(const WifiPhyHelper& phy, const WifiMacHelper& mac, std::string nodeName) const -{ - Ptr node = Names::Find(nodeName); - return Install(phy, mac, NodeContainer(node)); -} - -void -WaveHelper::EnableLogComponents() -{ - WifiHelper::EnableLogComponents(); - - LogComponentEnable("WaveNetDevice", LOG_LEVEL_ALL); - LogComponentEnable("ChannelCoordinator", LOG_LEVEL_ALL); - LogComponentEnable("ChannelManager", LOG_LEVEL_ALL); - LogComponentEnable("ChannelScheduler", LOG_LEVEL_ALL); - LogComponentEnable("DefaultChannelScheduler", LOG_LEVEL_ALL); - LogComponentEnable("VsaManager", LOG_LEVEL_ALL); - LogComponentEnable("OcbWifiMac", LOG_LEVEL_ALL); - LogComponentEnable("VendorSpecificAction", LOG_LEVEL_ALL); - LogComponentEnable("WaveFrameExchangeManager", LOG_LEVEL_ALL); - LogComponentEnable("HigherLayerTxVectorTag", LOG_LEVEL_ALL); -} - -int64_t -WaveHelper::AssignStreams(NetDeviceContainer c, int64_t stream) -{ - int64_t currentStream = stream; - Ptr netDevice; - for (NetDeviceContainer::Iterator i = c.Begin(); i != c.End(); ++i) - { - netDevice = (*i); - Ptr wave = DynamicCast(netDevice); - if (wave) - { - // Handle any random numbers in the PHY objects. - std::vector> phys = wave->GetPhys(); - for (std::vector>::iterator j = phys.begin(); j != phys.end(); ++j) - { - currentStream += (*j)->AssignStreams(currentStream); - } - - // Handle any random numbers in the MAC objects. - std::map> macs = wave->GetMacs(); - for (std::map>::iterator k = macs.begin(); k != macs.end(); - ++k) - { - // Handle any random numbers in the station managers. - Ptr manager = k->second->GetWifiRemoteStationManager(); - Ptr minstrel = DynamicCast(manager); - if (minstrel) - { - currentStream += minstrel->AssignStreams(currentStream); - } - - PointerValue ptr; - k->second->GetAttribute("Txop", ptr); - Ptr txop = ptr.Get(); - currentStream += txop->AssignStreams(currentStream); - - k->second->GetAttribute("VO_Txop", ptr); - Ptr vo_txop = ptr.Get(); - currentStream += vo_txop->AssignStreams(currentStream); - - k->second->GetAttribute("VI_Txop", ptr); - Ptr vi_txop = ptr.Get(); - currentStream += vi_txop->AssignStreams(currentStream); - - k->second->GetAttribute("BE_Txop", ptr); - Ptr be_txop = ptr.Get(); - currentStream += be_txop->AssignStreams(currentStream); - - k->second->GetAttribute("BK_Txop", ptr); - Ptr bk_txop = ptr.Get(); - currentStream += bk_txop->AssignStreams(currentStream); - } - } - } - return (currentStream - stream); -} -} // namespace ns3 diff --git a/src/wave/helper/wave-helper.h b/src/wave/helper/wave-helper.h deleted file mode 100644 index dead48a51..000000000 --- a/src/wave/helper/wave-helper.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ - -#ifndef WAVE_HELPER_H -#define WAVE_HELPER_H - -#include "ns3/attribute.h" -#include "ns3/net-device-container.h" -#include "ns3/node-container.h" -#include "ns3/object-factory.h" -#include "ns3/trace-helper.h" -#include "ns3/yans-wifi-helper.h" - -#include - -namespace ns3 -{ - -class WaveNetDevice; -class Node; - -/** - * \ingroup wave - * To trace WaveNetDevice, we have to overwrite the trace functions of class YansWifiPhyHelper. - * The source code is very similar with YansWifiPhy, only with some adaptation. - */ -class YansWavePhyHelper : public YansWifiPhyHelper -{ - public: - /** - * Create a phy helper in a default working state. - * \return A phy helper - */ - static YansWavePhyHelper Default(); - - private: - /** - * @brief Enable pcap output the indicated net device. - * - * NetDevice-specific implementation mechanism for hooking the trace and - * writing to the trace file. - * - * @param prefix Filename prefix to use for pcap files. - * @param nd Net device for which you want to enable tracing. - * @param promiscuous If true capture all possible packets available at the device. - * @param explicitFilename Treat the prefix as an explicit filename if true - */ - void EnablePcapInternal(std::string prefix, - Ptr nd, - bool promiscuous, - bool explicitFilename) override; - - /** - * \brief Enable ascii trace output on the indicated net device. - * \internal - * - * NetDevice-specific implementation mechanism for hooking the trace and - * writing to the trace file. - * - * \param stream The output stream object to use when logging ascii traces. - * \param prefix Filename prefix to use for ascii trace files. - * \param nd Net device for which you want to enable tracing. - * \param explicitFilename Treat the prefix as an explicit filename if true - */ - void EnableAsciiInternal(Ptr stream, - std::string prefix, - Ptr nd, - bool explicitFilename) override; -}; - -/** - * \ingroup wave - * \brief helps to create WaveNetDevice objects - * - * This class can help to create a large set of similar - * WaveNetDevice objects and to configure a large set of - * their attributes during creation. - * - * Generally WaveHelper with default configuration will - * create devices with 7 MAC entities,1 PHY entity and a - * multiple-channel scheduler for to deal with these entities. - * - * If users can make sure on which channel this WAVE device - * will work, they can set specific channel numbers to save - * resources of unused channels as below: - * WaveHelper helper = WaveHelper::Default (); - * uint32_t channels[] = {CCH, SCH1}; - * std::vector channelsVector (channels, channels + 2); - * helper.helper.CreateMacForChannel (channelsVector); - * - * If users can create other channel scheduler such as "AnotherScheduler" - * which can assign channel access in the context of more PHY entities, - * they can use this helper to create WAVE devices as below: - * WaveHelper helper = WaveHelper::Default (); - * helper.helper.CreateMacForChannel (ChannelManager::GetWaveChannels ()); - * helper.CreatePhys (2); // or other number which should be less than 7 - * helper.SetChannelScheduler ("ns3::AnotherScheduler"); - * helper.SetRemoteStationManager ("ns3::ConstantRateWifiManager"); // or other rate control - * algorithms - */ -class WaveHelper -{ - public: - WaveHelper(); - virtual ~WaveHelper(); - - /** - * \returns a new WaveHelper in a default state - * - * The default state is defined as being seven OcbWifiMac MAC entities - * with an ConstantRate rate control algorithm, one WifiPhy entity and - * a default multiple-channel scheduler DefaultChannelScheduler for - * assigning channel access with these created entities. - */ - static WaveHelper Default(); - - /** - * \param channelNumbers the MAC entities will be created to support these channels for multiple - * channel operation. - */ - void CreateMacForChannel(std::vector channelNumbers); - /** - * \param phys the number of PHY entity which will be created for multiple channel operation. - */ - void CreatePhys(uint32_t phys); - - /** - * \tparam Ts \deduced Argument types - * \param type the type of ns3::WifiRemoteStationManager to create. - * \param [in] args Name and AttributeValue pairs to set. - * - * All the attributes specified in this method should exist - * in the requested station manager. - */ - template - void SetRemoteStationManager(std::string type, Ts&&... args); - /** - * \tparam Ts \deduced Argument types - * \param type the type of ns3::ChannelScheduler to create. - * \param [in] args Name and AttributeValue pairs to set. - * - * All the attributes specified in this method should exist - * in the requested channel scheduler. - */ - template - void SetChannelScheduler(std::string type, Ts&&... args); - - /** - * \param phy the PHY helper to create PHY objects - * \param mac the MAC helper to create MAC objects - * \param c the set of nodes on which a wifi device must be created - * \returns a device container which contains all the devices created by this method. - */ - virtual NetDeviceContainer Install(const WifiPhyHelper& phy, - const WifiMacHelper& mac, - NodeContainer c) const; - /** - * \param phy the PHY helper to create PHY objects - * \param mac the MAC helper to create MAC objects - * \param node the node on which a wifi device must be created - * \returns a device container which contains all the devices created by this method. - */ - virtual NetDeviceContainer Install(const WifiPhyHelper& phy, - const WifiMacHelper& mac, - Ptr node) const; - /** - * \param phy the PHY helper to create PHY objects - * \param mac the MAC helper to create MAC objects - * \param nodeName the name of node on which a wifi device must be created - * \returns a device container which contains all the devices created by this method. - */ - virtual NetDeviceContainer Install(const WifiPhyHelper& phy, - const WifiMacHelper& mac, - std::string nodeName) const; - - /** - * Helper to enable all WaveNetDevice log components with one statement - */ - static void EnableLogComponents(); - - /** - * Assign a fixed random variable stream number to the random variables - * used by the Phy and Mac aspects of the WAVE models. Each device in - * container c has fixed stream numbers assigned to its random variables. - * The Wifi channel (e.g. propagation loss model) is excluded. - * Return the number of streams (possibly zero) that - * have been assigned. The Install() method should have previously been - * called by the user. - * - * \param c NetDeviceContainer of the set of net devices for which the - * WaveNetDevice should be modified to use fixed streams - * \param stream first stream index to use - * \return the number of stream indices assigned by this helper - */ - int64_t AssignStreams(NetDeviceContainer c, int64_t stream); - - protected: - ObjectFactory m_stationManager; ///< station manager - ObjectFactory m_channelScheduler; ///< channel scheduler - std::vector m_macsForChannelNumber; ///< MACs for channel number - uint32_t m_physNumber; ///< Phy number -}; - -/*************************************************************** - * Implementation of the templates declared above. - ***************************************************************/ - -template -void -WaveHelper::SetRemoteStationManager(std::string type, Ts&&... args) -{ - m_stationManager = ObjectFactory(type, std::forward(args)...); -} - -template -void -WaveHelper::SetChannelScheduler(std::string type, Ts&&... args) -{ - m_channelScheduler = ObjectFactory(type, std::forward(args)...); -} - -} // namespace ns3 -#endif /* WAVE_HELPER_H */ diff --git a/src/wave/helper/wave-mac-helper.cc b/src/wave/helper/wave-mac-helper.cc deleted file mode 100644 index a9d2495f6..000000000 --- a/src/wave/helper/wave-mac-helper.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2009 MIRKO BANCHI - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Author: Mirko Banchi - * Author: Junling Bu - */ -#include "wave-mac-helper.h" - -#include "ns3/boolean.h" - -namespace ns3 -{ - -NqosWaveMacHelper::NqosWaveMacHelper() -{ -} - -NqosWaveMacHelper::~NqosWaveMacHelper() -{ -} - -NqosWaveMacHelper -NqosWaveMacHelper::Default() -{ - NqosWaveMacHelper helper; - // We're making non QoS-enabled Wi-Fi MACs here, so we set the - // necessary attribute. I've carefully positioned this here so that - // someone who knows what they're doing can override with explicit - // attributes. - helper.SetType("ns3::OcbWifiMac", "QosSupported", BooleanValue(false)); - return helper; -} - -/********** QosWifi80211pMacHelper *********/ -QosWaveMacHelper::QosWaveMacHelper() -{ -} - -QosWaveMacHelper::~QosWaveMacHelper() -{ -} - -QosWaveMacHelper -QosWaveMacHelper::Default() -{ - QosWaveMacHelper helper; - - // We're making QoS-enabled Wi-Fi MACs here, so we set the necessary - // attribute. I've carefully positioned this here so that someone - // who knows what they're doing can override with explicit - // attributes. - helper.SetType("ns3::OcbWifiMac", "QosSupported", BooleanValue(true)); - - return helper; -} -} // namespace ns3 diff --git a/src/wave/helper/wave-mac-helper.h b/src/wave/helper/wave-mac-helper.h deleted file mode 100644 index de7bd942c..000000000 --- a/src/wave/helper/wave-mac-helper.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2009 MIRKO BANCHI - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Author: Mirko Banchi - * Author: Junling Bu - */ -#ifndef WAVE_MAC_HELPER_H -#define WAVE_MAC_HELPER_H -#include "ns3/wifi-mac-helper.h" - -namespace ns3 -{ - -/** - * \ingroup wave - * \brief Nqos Wave Mac Helper class - */ -class NqosWaveMacHelper : public WifiMacHelper -{ - public: - /** - * Create a NqosWaveMacHelper to make life easier for people who want to - * work with non-QOS Wave MAC layers. - */ - NqosWaveMacHelper(); - - /** - * Destroy a NqosWaveMacHelper. - */ - ~NqosWaveMacHelper() override; - /** - * Create a mac helper in a default working state. - * i.e., this is an ocb mac by default. - * \returns NqosWaveMacHelper - */ - static NqosWaveMacHelper Default(); - /** - * \tparam Ts \deduced Argument types - * \param type the type of ns3::WifiMac to create. - * \param [in] args Name and AttributeValue pairs to set. - * - * All the attributes specified in this method should exist - * in the requested mac. - * - * note: Here we require users set type with OcbWifiMac or its - * subclass, otherwise it will become error - */ - template - void SetType(std::string type, Ts&&... args); -}; - -/** - * \ingroup wave - * \brief Qos Wave Mac Helper class - */ -class QosWaveMacHelper : public WifiMacHelper -{ - public: - /** - * Create a QosWaveMacHelper that is used to make life easier when working - * with Wifi 802.11p devices using a QOS MAC layer. - */ - QosWaveMacHelper(); - - /** - * Destroy a QosWaveMacHelper - */ - ~QosWaveMacHelper() override; - - /** - * Create a mac helper in a default working state. - * \return A mac helper - */ - static QosWaveMacHelper Default(); - - /** - * \tparam Ts \deduced Argument types - * \param type the type of ns3::WifiMac to create. - * \param [in] args Name and AttributeValue pairs to set. - * - * All the attributes specified in this method should exist - * in the requested mac. - * - * note: Here we require users set type with OcbWifiMac or its - * subclass, otherwise it will become error - */ - template - void SetType(std::string type, Ts&&... args); -}; - -/*************************************************************** - * Implementation of the templates declared above. - ***************************************************************/ - -template -void -NqosWaveMacHelper::SetType(std::string type, Ts&&... args) -{ - if (type != "ns3::OcbWifiMac") - { - NS_FATAL_ERROR("QosWaveMacHelper shall set OcbWifiMac"); - } - WifiMacHelper::SetType("ns3::OcbWifiMac", std::forward(args)...); -} - -template -void -QosWaveMacHelper::SetType(std::string type, Ts&&... args) -{ - if (type != "ns3::OcbWifiMac") - { - NS_FATAL_ERROR("QosWaveMacHelper shall set OcbWifiMac"); - } - WifiMacHelper::SetType("ns3::OcbWifiMac", std::forward(args)...); -} - -} // namespace ns3 - -#endif /* WAVE_MAC_HELPER_H */ diff --git a/src/wave/helper/wifi-80211p-helper.cc b/src/wave/helper/wifi-80211p-helper.cc deleted file mode 100644 index caab330ac..000000000 --- a/src/wave/helper/wifi-80211p-helper.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2009 MIRKO BANCHI - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Author: Mirko Banchi - * Author: Junling Bu - */ -#include "wifi-80211p-helper.h" - -#include "wave-mac-helper.h" - -#include "ns3/log.h" -#include "ns3/string.h" - -#include - -namespace ns3 -{ - -Wifi80211pHelper::Wifi80211pHelper() -{ -} - -Wifi80211pHelper::~Wifi80211pHelper() -{ -} - -Wifi80211pHelper -Wifi80211pHelper::Default() -{ - Wifi80211pHelper helper; - helper.SetStandard(WIFI_STANDARD_80211p); - helper.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue("OfdmRate6MbpsBW10MHz"), - "ControlMode", - StringValue("OfdmRate6MbpsBW10MHz"), - "NonUnicastMode", - StringValue("OfdmRate6MbpsBW10MHz")); - return helper; -} - -void -Wifi80211pHelper::SetStandard(WifiStandard standard) -{ - if (standard == WIFI_STANDARD_80211p) - { - WifiHelper::SetStandard(standard); - } - else - { - NS_FATAL_ERROR("wrong standard selected!"); - } -} - -void -Wifi80211pHelper::EnableLogComponents() -{ - WifiHelper::EnableLogComponents(); - - LogComponentEnable("OcbWifiMac", LOG_LEVEL_ALL); - LogComponentEnable("VendorSpecificAction", LOG_LEVEL_ALL); -} - -NetDeviceContainer -Wifi80211pHelper::Install(const WifiPhyHelper& phyHelper, - const WifiMacHelper& macHelper, - NodeContainer c) const -{ - const QosWaveMacHelper* qosMac [[maybe_unused]] = - dynamic_cast(&macHelper); - if (qosMac == nullptr) - { - const NqosWaveMacHelper* nqosMac [[maybe_unused]] = - dynamic_cast(&macHelper); - if (nqosMac == nullptr) - { - NS_FATAL_ERROR("the macHelper should be either QosWaveMacHelper or NqosWaveMacHelper" - ", or should be the subclass of QosWaveMacHelper or NqosWaveMacHelper"); - } - } - - return WifiHelper::Install(phyHelper, macHelper, c); -} - -} // namespace ns3 diff --git a/src/wave/helper/wifi-80211p-helper.h b/src/wave/helper/wifi-80211p-helper.h deleted file mode 100644 index 3d60ba3fe..000000000 --- a/src/wave/helper/wifi-80211p-helper.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2009 MIRKO BANCHI - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Author: Mirko Banchi - * Author: Junling Bu - */ -#ifndef WIFI_802_11P_HELPER_H -#define WIFI_802_11P_HELPER_H -#include "ns3/wifi-helper.h" - -namespace ns3 -{ - -/** - * \ingroup wave - * \brief helps to create wifi 802.11p objects of - * WifiNetDevice class - * - * This class can help to create a large set of similar - * wifi 802.11p objects and to configure a large set of - * their attributes during creation. - */ -class Wifi80211pHelper : public WifiHelper -{ - public: - Wifi80211pHelper(); - ~Wifi80211pHelper() override; - - /** - * \returns a new Wifi80211pHelper in a default state - * - * The default state is defined as being an OcbWifiMac MAC - * layer with constant rate OfdmRate6MbpsBW10MHz - * and both objects using their default attribute values. - */ - static Wifi80211pHelper Default(); - - /** - * \param standard the phy standard to configure during installation - * - * Users can only configure 802.11p with 10MHz or 5 MHz channel bandwidth. - * The default 802.11p standard uses 10MHz. - */ - void SetStandard(WifiStandard standard) override; - - /** - * \param phy the PHY helper to create PHY objects - * \param macHelper the MAC helper to create MAC objects - * \param c the set of nodes on which a wifi device must be created - * \returns a device container which contains all the devices created by this method. - */ - NetDeviceContainer Install(const WifiPhyHelper& phy, - const WifiMacHelper& macHelper, - NodeContainer c) const override; - - /** - * Helper to enable all WifiNetDevice log components with one statement - */ - static void EnableLogComponents(); -}; - -} // namespace ns3 - -#endif /* WIFI_802_11P_HELPER_H */ diff --git a/src/wave/model/bsm-application.cc b/src/wave/model/bsm-application.cc deleted file mode 100644 index c2c29aba4..000000000 --- a/src/wave/model/bsm-application.cc +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (c) 2014 North Carolina State University - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Scott E. Carpenter - * - */ - -#include "ns3/bsm-application.h" - -#include "ns3/log.h" -#include "ns3/mobility-helper.h" -#include "ns3/mobility-model.h" -#include "ns3/wave-helper.h" -#include "ns3/wave-mac-helper.h" -#include "ns3/wave-net-device.h" - -NS_LOG_COMPONENT_DEFINE("BsmApplication"); - -namespace ns3 -{ - -// (Arbitrary) port for establishing socket to transmit WAVE BSMs -int BsmApplication::wavePort = 9080; - -NS_OBJECT_ENSURE_REGISTERED(BsmApplication); - -TypeId -BsmApplication::GetTypeId() -{ - static TypeId tid = TypeId("ns3::BsmApplication") - .SetParent() - .SetGroupName("Wave") - .AddConstructor(); - return tid; -} - -BsmApplication::BsmApplication() - : m_waveBsmStats(nullptr), - m_txSafetyRangesSq(), - m_TotalSimTime(Seconds(10)), - m_wavePacketSize(200), - m_numWavePackets(1), - m_waveInterval(MilliSeconds(100)), - m_gpsAccuracyNs(10000), - m_adhocTxInterfaces(nullptr), - m_nodesMoving(nullptr), - m_unirv(nullptr), - m_nodeId(0), - m_chAccessMode(0), - m_txMaxDelay(MilliSeconds(10)), - m_prevTxDelay(MilliSeconds(0)) -{ - NS_LOG_FUNCTION(this); -} - -BsmApplication::~BsmApplication() -{ - NS_LOG_FUNCTION(this); -} - -void -BsmApplication::DoDispose() -{ - NS_LOG_FUNCTION(this); - - // chain up - Application::DoDispose(); -} - -// Application Methods -void -BsmApplication::StartApplication() // Called at time specified by Start -{ - NS_LOG_FUNCTION(this); - - // setup generation of WAVE BSM messages - Time waveInterPacketInterval = m_waveInterval; - - // BSMs are not transmitted for the first second - Time startTime = Seconds(1.0); - // total length of time transmitting WAVE packets - Time totalTxTime = m_TotalSimTime - startTime; - // total WAVE packets needing to be sent - m_numWavePackets = (uint32_t)(totalTxTime.GetDouble() / m_waveInterval.GetDouble()); - - TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory"); - - // every node broadcasts WAVE BSM to potentially all other nodes - Ptr recvSink = Socket::CreateSocket(GetNode(m_nodeId), tid); - recvSink->SetRecvCallback(MakeCallback(&BsmApplication::ReceiveWavePacket, this)); - InetSocketAddress local = InetSocketAddress(Ipv4Address::GetAny(), wavePort); - recvSink->BindToNetDevice(GetNetDevice(m_nodeId)); - recvSink->Bind(local); - recvSink->SetAllowBroadcast(true); - - // dest is broadcast address - InetSocketAddress remote = InetSocketAddress(Ipv4Address("255.255.255.255"), wavePort); - recvSink->Connect(remote); - - // Transmission start time for each BSM: - // We assume that the start transmission time - // for the first packet will be on a ns-3 time - // "Second" boundary - e.g., 1.0 s. - // However, the actual transmit time must reflect - // additional effects of 1) clock drift and - // 2) transmit delay requirements. - // 1) Clock drift - clocks are not perfectly - // synchronized across all nodes. In a VANET - // we assume all nodes sync to GPS time, which - // itself is assumed accurate to, say, 40-100 ns. - // Thus, the start transmission time must be adjusted - // by some value, t_drift. - // 2) Transmit delay requirements - The US - // minimum performance requirements for V2V - // BSM transmission expect a random delay of - // +/- 5 ms, to avoid simultaneous transmissions - // by all vehicles congesting the channel. Thus, - // we need to adjust the start transmission time by - // some value, t_tx_delay. - // Therefore, the actual transmit time should be: - // t_start = t_time + t_drift + t_tx_delay - // t_drift is always added to t_time. - // t_tx_delay is supposed to be +/- 5ms, but if we - // allow negative numbers the time could drift to a value - // BEFORE the interval start time (i.e., at 100 ms - // boundaries, we do not want to drift into the - // previous interval, such as at 95 ms. Instead, - // we always want to be at the 100 ms interval boundary, - // plus [0..10] ms tx delay. - // Thus, the average t_tx_delay will be - // within the desired range of [0..10] ms of - // (t_time + t_drift) - - // WAVE devices sync to GPS time - // and all devices would like to begin broadcasting - // their safety messages immediately at the start of - // the CCH interval. However, if all do so, then - // significant collisions occur. Thus, we assume there - // is some GPS sync accuracy on GPS devices, - // typically 40-100 ns. - // Get a uniformly random number for GPS sync accuracy, in ns. - Time tDrift = NanoSeconds(m_unirv->GetInteger(0, m_gpsAccuracyNs)); - - // When transmitting at a default rate of 10 Hz, - // the subsystem shall transmit every 100 ms +/- - // a random value between 0 and 5 ms. [MPR-BSMTX-TXTIM-002] - // Source: CAMP Vehicle Safety Communications 4 Consortium - // On-board Minimum Performance Requirements - // for V2V Safety Systems Version 1.0, December 17, 2014 - // max transmit delay (default 10ms) - // get value for transmit delay, as number of ns - uint32_t d_ns = static_cast(m_txMaxDelay.GetInteger()); - // convert random tx delay to ns-3 time - // see note above regarding centering tx delay - // offset by 5ms + a random value. - Time txDelay = NanoSeconds(m_unirv->GetInteger(0, d_ns)); - m_prevTxDelay = txDelay; - - Time txTime = startTime + tDrift + txDelay; - // schedule transmission of first packet - Simulator::ScheduleWithContext(recvSink->GetNode()->GetId(), - txTime, - &BsmApplication::GenerateWaveTraffic, - this, - recvSink, - m_wavePacketSize, - m_numWavePackets, - waveInterPacketInterval, - m_nodeId); -} - -void -BsmApplication::StopApplication() // Called at time specified by Stop -{ - NS_LOG_FUNCTION(this); -} - -void -BsmApplication::Setup(Ipv4InterfaceContainer& i, - int nodeId, - Time totalTime, - uint32_t wavePacketSize, // bytes - Time waveInterval, - double gpsAccuracyNs, - std::vector rangesSq, // m ^2 - Ptr waveBsmStats, - std::vector* nodesMoving, - int chAccessMode, - Time txMaxDelay) -{ - NS_LOG_FUNCTION(this); - - m_unirv = CreateObject(); - - m_TotalSimTime = totalTime; - m_wavePacketSize = wavePacketSize; - m_waveInterval = waveInterval; - m_gpsAccuracyNs = gpsAccuracyNs; - int size = rangesSq.size(); - m_waveBsmStats = waveBsmStats; - m_nodesMoving = nodesMoving; - m_chAccessMode = chAccessMode; - m_txSafetyRangesSq.clear(); - m_txSafetyRangesSq.resize(size, 0); - - for (int index = 0; index < size; index++) - { - // stored as square of value, for optimization - m_txSafetyRangesSq[index] = rangesSq[index]; - } - - m_adhocTxInterfaces = &i; - m_nodeId = nodeId; - m_txMaxDelay = txMaxDelay; -} - -void -BsmApplication::GenerateWaveTraffic(Ptr socket, - uint32_t pktSize, - uint32_t pktCount, - Time pktInterval, - uint32_t sendingNodeId) -{ - NS_LOG_FUNCTION(this); - - // more packets to send? - if (pktCount > 0) - { - // for now, we cannot tell if each node has - // started mobility. so, as an optimization - // only send if this node is moving - // if not, then skip - int txNodeId = sendingNodeId; - Ptr txNode = GetNode(txNodeId); - Ptr txPosition = txNode->GetObject(); - NS_ASSERT(txPosition); - - int senderMoving = m_nodesMoving->at(txNodeId); - if (senderMoving != 0) - { - // send it! - socket->Send(Create(pktSize)); - // count it - m_waveBsmStats->IncTxPktCount(); - m_waveBsmStats->IncTxByteCount(pktSize); - int wavePktsSent = m_waveBsmStats->GetTxPktCount(); - if ((m_waveBsmStats->GetLogging() != 0) && ((wavePktsSent % 1000) == 0)) - { - NS_LOG_UNCOND("Sending WAVE pkt # " << wavePktsSent); - } - - // find other nodes within range that would be - // expected to receive this broadbast - int nRxNodes = m_adhocTxInterfaces->GetN(); - for (int i = 0; i < nRxNodes; i++) - { - Ptr rxNode = GetNode(i); - int rxNodeId = rxNode->GetId(); - - if (rxNodeId != txNodeId) - { - Ptr rxPosition = rxNode->GetObject(); - NS_ASSERT(rxPosition); - // confirm that the receiving node - // has also started moving in the scenario - // if it has not started moving, then - // it is not a candidate to receive a packet - int receiverMoving = m_nodesMoving->at(rxNodeId); - if (receiverMoving == 1) - { - double distSq = MobilityHelper::GetDistanceSquaredBetween(txNode, rxNode); - if (distSq > 0.0) - { - // dest node within range? - int rangeCount = m_txSafetyRangesSq.size(); - for (int index = 1; index <= rangeCount; index++) - { - if (distSq <= m_txSafetyRangesSq[index - 1]) - { - // we should expect dest node to receive broadcast pkt - m_waveBsmStats->IncExpectedRxPktCount(index); - } - } - } - } - } - } - } - - // every BSM must be scheduled with a tx time delay - // of +/- (5) ms. See comments in StartApplication(). - // we handle this as a tx delay of [0..10] ms - // from the start of the pktInterval boundary - uint32_t d_ns = static_cast(m_txMaxDelay.GetInteger()); - Time txDelay = NanoSeconds(m_unirv->GetInteger(0, d_ns)); - - // do not want the tx delay to be cumulative, so - // deduct the previous delay value. thus we adjust - // to schedule the next event at the next pktInterval, - // plus some new [0..10] ms tx delay - Time txTime = pktInterval - m_prevTxDelay + txDelay; - m_prevTxDelay = txDelay; - - Simulator::ScheduleWithContext(socket->GetNode()->GetId(), - txTime, - &BsmApplication::GenerateWaveTraffic, - this, - socket, - pktSize, - pktCount - 1, - pktInterval, - socket->GetNode()->GetId()); - } - else - { - socket->Close(); - } -} - -void -BsmApplication::ReceiveWavePacket(Ptr socket) -{ - NS_LOG_FUNCTION(this); - - Ptr packet; - Address senderAddr; - while ((packet = socket->RecvFrom(senderAddr))) - { - Ptr rxNode = socket->GetNode(); - - if (InetSocketAddress::IsMatchingType(senderAddr)) - { - InetSocketAddress addr = InetSocketAddress::ConvertFrom(senderAddr); - int nodes = m_adhocTxInterfaces->GetN(); - for (int i = 0; i < nodes; i++) - { - if (addr.GetIpv4() == m_adhocTxInterfaces->GetAddress(i)) - { - Ptr txNode = GetNode(i); - HandleReceivedBsmPacket(txNode, rxNode); - } - } - } - } -} - -void -BsmApplication::HandleReceivedBsmPacket(Ptr txNode, Ptr rxNode) -{ - NS_LOG_FUNCTION(this); - - m_waveBsmStats->IncRxPktCount(); - - Ptr rxPosition = rxNode->GetObject(); - NS_ASSERT(rxPosition); - // confirm that the receiving node - // has also started moving in the scenario - // if it has not started moving, then - // it is not a candidate to receive a packet - int rxNodeId = rxNode->GetId(); - int receiverMoving = m_nodesMoving->at(rxNodeId); - if (receiverMoving == 1) - { - double rxDistSq = MobilityHelper::GetDistanceSquaredBetween(rxNode, txNode); - if (rxDistSq > 0.0) - { - int rangeCount = m_txSafetyRangesSq.size(); - for (int index = 1; index <= rangeCount; index++) - { - if (rxDistSq <= m_txSafetyRangesSq[index - 1]) - { - m_waveBsmStats->IncRxPktInRangeCount(index); - } - } - } - } -} - -int64_t -BsmApplication::AssignStreams(int64_t streamIndex) -{ - NS_LOG_FUNCTION(this); - - NS_ASSERT(m_unirv); // should be set by Setup() prevoiusly - m_unirv->SetStream(streamIndex); - - return 1; -} - -Ptr -BsmApplication::GetNode(int id) -{ - NS_LOG_FUNCTION(this); - - std::pair, uint32_t> interface = m_adhocTxInterfaces->Get(id); - Ptr pp = interface.first; - Ptr node = pp->GetObject(); - - return node; -} - -Ptr -BsmApplication::GetNetDevice(int id) -{ - NS_LOG_FUNCTION(this); - - std::pair, uint32_t> interface = m_adhocTxInterfaces->Get(id); - Ptr pp = interface.first; - Ptr device = pp->GetObject(); - - return device; -} - -} // namespace ns3 diff --git a/src/wave/model/bsm-application.h b/src/wave/model/bsm-application.h deleted file mode 100644 index a407dbd0a..000000000 --- a/src/wave/model/bsm-application.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2014 North Carolina State University - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Scott E. Carpenter - * - */ - -#ifndef BSM_APPLICATION_H -#define BSM_APPLICATION_H - -#include "ns3/application.h" -#include "ns3/internet-stack-helper.h" -#include "ns3/random-variable-stream.h" -#include "ns3/wave-bsm-stats.h" - -namespace ns3 -{ -/** - * \ingroup wave - * \brief The BsmApplication class sends and receives the - * IEEE 1609 WAVE (Wireless Access in Vehicular Environments) - * Basic Safety Messages (BSMs) and uses the WaveBsmStats class - * to manage statistics about BSMs transmitted and received - * The BSM is a ~200-byte packet that is - * generally broadcast from every vehicle at a nominal rate of 10 Hz. - */ -class BsmApplication : public Application -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - - /** - * \brief Constructor - */ - BsmApplication(); - ~BsmApplication() override; - - /** - * \brief Setup BSM generation parameters for a node - * \param i IPv4 interface container - * \param nodeId identifier of the node (index into container) - * \param totalTime total amount of time that BSM packets should be transmitted - * \param wavePacketSize the size, in bytes, of a WAVE BSM - * \param waveInterval the time, in seconds, between each WAVE BSM transmission, - * typically 10 Hz (0.1 second) - * \param gpsAccuracyNs the timing synchronization accuracy of GPS time, in nanoseconds. - * GPS time-sync is ~40-100 ns. Universally synchronized time among all vehicles - * will result in all vehicles transmitting safety messages simultaneously, leading - * to excessive wireless collisions. - * \param rangesSq the expected transmission range, in m ^ 2. - * \param waveBsmStats class for WAVE BSM statistics - * \param nodesMoving of whether or not node(s) are moving - * \param mode - * \param txDelay - */ - void Setup(Ipv4InterfaceContainer& i, - int nodeId, - Time totalTime, - uint32_t wavePacketSize, // bytes - Time waveInterval, - double gpsAccuracyNs, - std::vector rangesSq, // m ^ 2 - Ptr waveBsmStats, - std::vector* nodesMoving, - int mode, - Time txDelay); - - /** - * Assign a fixed random variable stream number to the random variables - * used by this model. Return the number of streams (possibly zero) that - * have been assigned. The Install() method should have previously been - * called by the user. - * - * \param streamIndex first stream index to use - * \return the number of stream indices assigned by this helper - */ - int64_t AssignStreams(int64_t streamIndex); - - /** - * (Arbitrary) port number that is used to create a socket for transmitting WAVE BSMs. - */ - static int wavePort; - - protected: - void DoDispose() override; - - private: - // inherited from Application base class. - void StartApplication() override; ///< Called at time specified by Start - void StopApplication() override; ///< Called at time specified by Stop - - /** - * \brief Creates and transmits a WAVE BSM packet - * \param socket socket to use for transmission - * \param pktSize the size, in bytes, of the WAVE BSM packet - * \param pktCount the number of remaining WAVE BSM packets to be transmitted - * \param pktInterval the interval, in seconds, until the next packet - * should be transmitted - * \param sendingNodeId - */ - void GenerateWaveTraffic(Ptr socket, - uint32_t pktSize, - uint32_t pktCount, - Time pktInterval, - uint32_t sendingNodeId); - - /** - * \brief Receive a WAVE BSM packet - * \param socket the receiving socket - */ - void ReceiveWavePacket(Ptr socket); - - /** - * \brief Handle the receipt of a WAVE BSM packet from sender to receiver - * \param txNode the sending node - * \param rxNode the receiving node - */ - void HandleReceivedBsmPacket(Ptr txNode, Ptr rxNode); - - /** - * \brief Get the node for the desired id - * \param id the id of the desired node - * \return ptr to the desired node - */ - Ptr GetNode(int id); - - /** - * \brief Get the net device for the desired id - * \param id the id of the desired net device - * \return ptr to the desired net device - */ - Ptr GetNetDevice(int id); - - Ptr m_waveBsmStats; ///< BSM stats - /// tx safety range squared, for optimization - std::vector m_txSafetyRangesSq; - Time m_TotalSimTime; ///< total sim time - uint32_t m_wavePacketSize; ///< bytes - uint32_t m_numWavePackets; ///< number of wave packets - Time m_waveInterval; ///< wave interval - double m_gpsAccuracyNs; ///< GPS accuracy - Ipv4InterfaceContainer* m_adhocTxInterfaces; ///< transmit interfaces - std::vector* m_nodesMoving; ///< nodes moving - Ptr m_unirv; ///< random variable - int m_nodeId; ///< node ID - /// WAVE channel access mode. 0=continuous PHY; 1=channel-switching - int m_chAccessMode; - /** - * When transmitting at a default rate of 10 Hz, - * the subsystem shall transmit every 100 ms +/- - * a random value between 0 and 5 ms. [MPR-BSMTX-TXTIM-002] - * Source: CAMP Vehicle Safety Communications 4 Consortium - * On-board Minimum Performance Requirements - * for V2V Safety Systems Version 1.0, December 17, 2014 - * max transmit delay (default 10ms) */ - Time m_txMaxDelay; - Time m_prevTxDelay; ///< previous transmit delay -}; - -} // namespace ns3 - -#endif /* BSM_APPLICATION_H*/ diff --git a/src/wave/model/channel-coordinator.cc b/src/wave/model/channel-coordinator.cc deleted file mode 100644 index 898e4f2b7..000000000 --- a/src/wave/model/channel-coordinator.cc +++ /dev/null @@ -1,403 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#include "channel-coordinator.h" - -#include "ns3/log.h" -#include "ns3/simulator.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("ChannelCoordinator"); - -/**************************************************************** - * This destructor is needed. - ****************************************************************/ - -ChannelCoordinationListener::~ChannelCoordinationListener() -{ -} - -/****************************************************************/ - -NS_OBJECT_ENSURE_REGISTERED(ChannelCoordinator); - -TypeId -ChannelCoordinator::GetTypeId() -{ - static TypeId tid = TypeId("ns3::ChannelCoordinator") - .SetParent() - .SetGroupName("Wave") - .AddConstructor() - .AddAttribute("CchInterval", - "CCH Interval, default value is 50ms.", - TimeValue(GetDefaultCchInterval()), - MakeTimeAccessor(&ChannelCoordinator::m_cchi), - MakeTimeChecker()) - .AddAttribute("SchInterval", - "SCH Interval, default value is 50ms.", - TimeValue(GetDefaultSchInterval()), - MakeTimeAccessor(&ChannelCoordinator::m_schi), - MakeTimeChecker()) - .AddAttribute("GuardInterval", - "Guard Interval, default value is 4ms.", - TimeValue(GetDefaultGuardInterval()), - MakeTimeAccessor(&ChannelCoordinator::m_gi), - MakeTimeChecker()); - return tid; -} - -ChannelCoordinator::ChannelCoordinator() - : m_guardCount(0) -{ - NS_LOG_FUNCTION(this); -} - -ChannelCoordinator::~ChannelCoordinator() -{ - NS_LOG_FUNCTION(this); -} - -void -ChannelCoordinator::DoInitialize() -{ - NS_LOG_FUNCTION(this); - StartChannelCoordination(); -} - -void -ChannelCoordinator::DoDispose() -{ - NS_LOG_FUNCTION(this); - StopChannelCoordination(); - UnregisterAllListeners(); -} - -Time -ChannelCoordinator::GetDefaultCchInterval() -{ - NS_LOG_FUNCTION_NOARGS(); - // refer to Annex H of IEEE 1609.4-2010 - const static uint8_t DEFAULT_CCH_INTERVAL = 50; - return MilliSeconds(DEFAULT_CCH_INTERVAL); -} - -Time -ChannelCoordinator::GetDefaultSchInterval() -{ - NS_LOG_FUNCTION_NOARGS(); - // refer to Annex H of IEEE 1609.4-2010 - const static uint8_t DEFAULT_SCH_INTERVAL = 50; - return MilliSeconds(DEFAULT_SCH_INTERVAL); -} - -Time -ChannelCoordinator::GetDefaultSyncInterval() -{ - NS_LOG_FUNCTION_NOARGS(); - return GetDefaultCchInterval() + GetDefaultSchInterval(); -} - -Time -ChannelCoordinator::GetDefaultGuardInterval() -{ - NS_LOG_FUNCTION_NOARGS(); - // refer to Annex H of IEEE 1609.4-2010 - const static uint8_t SyncTolerance = 2; - const static uint8_t MaxChSwitchTime = 2; - const static uint8_t DEFAULT_GUARD_INTERVAL = SyncTolerance + MaxChSwitchTime; - return MilliSeconds(DEFAULT_GUARD_INTERVAL); -} - -void -ChannelCoordinator::SetCchInterval(Time cchInterval) -{ - NS_LOG_FUNCTION(this << cchInterval); - m_cchi = cchInterval; -} - -Time -ChannelCoordinator::GetCchInterval() const -{ - NS_LOG_FUNCTION(this); - return m_cchi; -} - -void -ChannelCoordinator::SetSchInterval(Time schInterval) -{ - NS_LOG_FUNCTION(this << schInterval); - m_schi = schInterval; -} - -Time -ChannelCoordinator::GetSchInterval() const -{ - NS_LOG_FUNCTION(this); - return m_schi; -} - -Time -ChannelCoordinator::GetSyncInterval() const -{ - NS_LOG_FUNCTION(this); - return GetCchInterval() + GetSchInterval(); -} - -void -ChannelCoordinator::SetGuardInterval(Time guard) -{ - NS_LOG_FUNCTION(this); - m_gi = guard; -} - -Time -ChannelCoordinator::GetGuardInterval() const -{ - NS_LOG_FUNCTION(this); - return m_gi; -} - -Time -ChannelCoordinator::GetSchSlot() const -{ - NS_LOG_FUNCTION(this); - return m_schi - m_gi; -} - -Time -ChannelCoordinator::GetCchSlot() const -{ - NS_LOG_FUNCTION(this); - return m_cchi - m_gi; -} - -bool -ChannelCoordinator::IsCchInterval(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - Time future = GetIntervalTime(duration); - return (future < m_cchi); -} - -bool -ChannelCoordinator::IsSchInterval(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - return !IsCchInterval(duration); -} - -bool -ChannelCoordinator::IsGuardInterval(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - Time future = GetIntervalTime(duration); - // the interval is either in CchInterval or SchInterval - Time interval = future < m_cchi ? future : future - m_cchi; - return interval < m_gi; -} - -bool -ChannelCoordinator::IsValidConfig() const -{ - NS_LOG_FUNCTION(this); - if (GetCchInterval().GetMilliSeconds() == 0 || GetSchInterval().GetMilliSeconds() == 0 || - GetGuardInterval().GetMilliSeconds() == 0) - { - NS_LOG_WARN("the channel interval should not be zero"); - return false; - } - // 1000 is 1000ms which is one UTC second - if ((1000 % GetSyncInterval().GetMilliSeconds()) != 0) - { - NS_LOG_WARN("every UTC second shall be an integer number of SyncInterval"); - return false; - } - if (GetCchInterval() <= GetGuardInterval()) - { - NS_LOG_WARN("CCH Interval should be large than GuardInterval"); - return false; - } - if (GetSchInterval() <= GetGuardInterval()) - { - NS_LOG_WARN("SCH Interval should be large than GuardInterval"); - return false; - } - // at last, GguardInterval should be larger than real channel switch time of PHY layer. - // However there is no method such as GetChannelSwitchTime in the WifiPhy to support test here. - return true; -} - -Time -ChannelCoordinator::NeedTimeToCchInterval(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - if (IsCchInterval(duration)) - { - return MilliSeconds(0); - } - return GetSyncInterval() - GetIntervalTime(duration); -} - -Time -ChannelCoordinator::NeedTimeToSchInterval(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - if (IsSchInterval(duration)) - { - return MilliSeconds(0); - } - return GetCchInterval() - GetIntervalTime(duration); -} - -Time -ChannelCoordinator::NeedTimeToGuardInterval(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - if (IsGuardInterval(duration)) - { - return MilliSeconds(0); - } - if (IsCchInterval(duration)) - { - // the time to Guard Interval of SCH Interval - return (GetCchInterval() - GetIntervalTime(duration)); - } - // the time to Guard Interval of next CCH Interval - return (GetSyncInterval() - GetIntervalTime(duration)); -} - -Time -ChannelCoordinator::GetIntervalTime(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - Time future = Now() + duration; - Time sync = GetSyncInterval(); - uint32_t n = future.GetMilliSeconds() / sync.GetMilliSeconds(); - return future - MilliSeconds(n * sync.GetMilliSeconds()); -} - -Time -ChannelCoordinator::GetRemainTime(Time duration) const -{ - NS_LOG_FUNCTION(this << duration); - return GetSyncInterval() - GetIntervalTime(duration); -} - -void -ChannelCoordinator::RegisterListener(Ptr listener) -{ - NS_LOG_FUNCTION(this << listener); - NS_ASSERT(listener); - m_listeners.push_back(listener); -} - -void -ChannelCoordinator::UnregisterListener(Ptr listener) -{ - NS_LOG_FUNCTION(this << listener); - NS_ASSERT(listener); - for (ListenersI i = m_listeners.begin(); i != m_listeners.end(); ++i) - { - if ((*i) == listener) - { - m_listeners.erase(i); - return; - } - } -} - -void -ChannelCoordinator::UnregisterAllListeners() -{ - NS_LOG_FUNCTION(this); - m_listeners.clear(); -} - -void -ChannelCoordinator::StartChannelCoordination() -{ - NS_LOG_FUNCTION(this); - Time now = Now(); - if ((now.GetMilliSeconds() % 1000) != 0) - { - // see chapter 5.5.2 - NS_FATAL_ERROR("the coordination event order should start with the beginning of 1 second"); - } - if (!IsValidConfig()) - { - NS_FATAL_ERROR( - "the channel intervals configured for channel coordination events are invalid"); - } - m_guardCount = 0; - NotifyGuardSlot(); -} - -void -ChannelCoordinator::StopChannelCoordination() -{ - if (!m_coordination.IsExpired()) - { - m_coordination.Cancel(); - } - m_guardCount = 0; -} - -void -ChannelCoordinator::NotifySchSlot() -{ - NS_LOG_FUNCTION(this); - m_coordination = Simulator::Schedule(GetSchSlot(), &ChannelCoordinator::NotifyGuardSlot, this); - for (ListenersI i = m_listeners.begin(); i != m_listeners.end(); ++i) - { - (*i)->NotifySchSlotStart(GetSchSlot()); - } -} - -void -ChannelCoordinator::NotifyCchSlot() -{ - NS_LOG_FUNCTION(this); - m_coordination = Simulator::Schedule(GetCchSlot(), &ChannelCoordinator::NotifyGuardSlot, this); - for (ListenersI i = m_listeners.begin(); i != m_listeners.end(); ++i) - { - (*i)->NotifyCchSlotStart(GetCchSlot()); - } -} - -void -ChannelCoordinator::NotifyGuardSlot() -{ - NS_LOG_FUNCTION(this); - Time guardSlot = GetGuardInterval(); - bool inCchi = ((m_guardCount % 2) == 0); - if (inCchi) - { - m_coordination = Simulator::Schedule(guardSlot, &ChannelCoordinator::NotifyCchSlot, this); - } - else - { - m_coordination = Simulator::Schedule(guardSlot, &ChannelCoordinator::NotifySchSlot, this); - } - for (ListenersI i = m_listeners.begin(); i != m_listeners.end(); ++i) - { - (*i)->NotifyGuardSlotStart(guardSlot, inCchi); - } - m_guardCount++; -} - -} // namespace ns3 diff --git a/src/wave/model/channel-coordinator.h b/src/wave/model/channel-coordinator.h deleted file mode 100644 index 298a0a765..000000000 --- a/src/wave/model/channel-coordinator.h +++ /dev/null @@ -1,256 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#ifndef CHANNEL_COORDINATOR_H -#define CHANNEL_COORDINATOR_H -#include "ns3/event-id.h" -#include "ns3/nstime.h" -#include "ns3/object.h" - -namespace ns3 -{ - -/** - * \ingroup wave - * \brief receive notifications about channel coordination events. - */ -class ChannelCoordinationListener : public SimpleRefCount -{ - public: - virtual ~ChannelCoordinationListener(); - /** - * \param duration the CCH access time (CCHI - GI) continues, - */ - virtual void NotifyCchSlotStart(Time duration) = 0; - /** - * \param duration the SCH access time (SCHI - GI) continues, - */ - virtual void NotifySchSlotStart(Time duration) = 0; - /** - * \param duration the time Guard access time (GI) continues - * \param cchi indicate whether the guard slot is in the GI of CCHI or SCHI. - */ - virtual void NotifyGuardSlotStart(Time duration, bool cchi) = 0; -}; - -/** - * \ingroup wave - * \brief ChannelCoordinator deals with channel coordination in data plane (see 1609.4 chapter 5.2) - * - * <------------ -----SYNCI-----------------> <-------------------SYNCI------------------> - * CCHI SCHI CCHI SCHI - * |..************|..************|..************|..************| - * GI GI GI GI - * - * The relation among CCHI(CCH Interval), SCHI(SCH Interval), GI(Guard Interval), SYNCI(Sync - * Interval): - * 1. they are all time durations, gegerally default CCHI is 50ms, - * default SCHI is 50ms, default GI is 4ms, default SYNCI is 100ms. - * 2. Every UTC second shall be an integer number of sync interval, and the - * beginning of a sync interval shall align with beginning of UTC second; - * 3. SYNCI is the sum of CCHI and SCHI. - * GI is the sum of SyncTolerance and MaxSwitchTime defined for - * multi-channel synchronization (see 1609.4 chapter 6.2). And since all - * devices the in simulation could be supposed to synchronize by "perfect GPS", - * here the synchronization mechanism defined in the standard will be not implemented. - * 4. Although the real channel switch time of wifi PHY layer is very fast, and the - * "ChannelSwitchDelay" of YansWifiPhy is 250 microseconds, here in 4ms guard interval WAVE devices - * cannot transmit packets while may receive packets. - */ -class ChannelCoordinator : public Object -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - ChannelCoordinator(); - ~ChannelCoordinator() override; - - /** - * \return the default control channel interval for multi-channel operation (50 milliseconds). - */ - static Time GetDefaultCchInterval(); - /** - * \return the default service channel interval for multi-channel operation (50 milliseconds). - */ - static Time GetDefaultSchInterval(); - /** - * \return the default sync interval for multi-channel operation (100 milliseconds). - */ - static Time GetDefaultSyncInterval(); - /** - * \return the default guard channel interval for multi-channel operation (4 milliseconds). - */ - static Time GetDefaultGuardInterval(); - - /** - * \param cchi the CCH interval for multi-channel operation. - */ - void SetCchInterval(Time cchi); - /** - * \return the CCH interval for multi-channel operation. - */ - Time GetCchInterval() const; - /** - * \param schi the SCH interval for multi-channel operation. - */ - void SetSchInterval(Time schi); - /** - * \return the SCH interval for multi-channel operation. - */ - Time GetSchInterval() const; - /** - * \return the Sync interval for multi-channel operation. - */ - Time GetSyncInterval() const; - /** - * \param guardi the guard interval for multi-channel operation. - */ - void SetGuardInterval(Time guardi); - /** - * \return the guard interval for multi-channel operation. - */ - Time GetGuardInterval() const; - /** - * \return whether current channel interval configuration is valid. - * - * If users set the channel intervals different from default values here, - * it should be better to test whether the configuration is valid. - */ - bool IsValidConfig() const; - - /** - * \param duration the future time after duration - * \returns whether future time is in CCH Interval - */ - bool IsCchInterval(Time duration = Seconds(0.0)) const; - /** - * \param duration the future time after duration - * \returns whether future time is in SCH Interval - */ - bool IsSchInterval(Time duration = Seconds(0.0)) const; - /** - * \param duration the future time after duration - * \returns whether future time is in Guard Interval - */ - bool IsGuardInterval(Time duration = Seconds(0.0)) const; - /** - * \param duration the future time after duration - * \returns the time to the next CCH interval. - * If current time is already in CCH interval, return 0; - */ - Time NeedTimeToCchInterval(Time duration = Seconds(0.0)) const; - /** - * \param duration the future time after duration - * \returns the duration time to the next SCH interval. - * If current time is already in SCH interval, return 0; - */ - Time NeedTimeToSchInterval(Time duration = Seconds(0.0)) const; - /** - * \param duration the future time after duration - * \returns the duration time to next Guard Interval; - * return 0 if current time is already in Guard Interval, ; - */ - Time NeedTimeToGuardInterval(Time duration = Seconds(0.0)) const; - /** - * \param duration the future time after duration - * \return the time in a Sync Interval of future time - * for example: - * SyncInterval = 100ms; - * Now = 5s20ms; - * duration = 50ms; - * then GetIntervalTime (duration) = 70ms. - */ - Time GetIntervalTime(Time duration = Seconds(0.0)) const; - /** - * \param duration the future time after duration - * \return the remain time in a Sync Interval of future time - * for example: - * SyncInterval = 100ms; - * Now = 5s20ms; - * duration = 50ms; - * then GetRemainTime (duration) = 30ms. - */ - Time GetRemainTime(Time duration = Seconds(0.0)) const; - /** - * \param listener the new listener for channel coordination events. - * - * Add the input listener to the list of objects to be notified of - * channel coordination events. - */ - void RegisterListener(Ptr listener); - /** - * \param listener the current attached listener - * - * Remove the specified listener. - */ - void UnregisterListener(Ptr listener); - /** - * Remove all listeners. - */ - void UnregisterAllListeners(); - - private: - void DoDispose() override; - void DoInitialize() override; - - /** - * start to make channel coordination events - */ - void StartChannelCoordination(); - /** - * stop channel coordination events - */ - void StopChannelCoordination(); - /** - * notify listeners of a SCH slot start - */ - void NotifySchSlot(); - /** - * notify listeners of a CCH slot start - */ - void NotifyCchSlot(); - /** - * notify listeners of a guard slot start - */ - void NotifyGuardSlot(); - /** - * \return SCH channel access time which is SchInterval - GuardInterval, default 46ms - */ - Time GetSchSlot() const; - /** - * \return CCH channel access time which is SchInterval - GuardInterval, default 46ms - */ - Time GetCchSlot() const; - - Time m_cchi; ///< CchInterval - Time m_schi; ///< SchInterval - Time m_gi; ///< GuardInterval - - /// Listeners typedef - typedef std::vector> Listeners; - /// Listeners iterator typedef - typedef std::vector>::iterator ListenersI; - Listeners m_listeners; ///< listeners - - uint32_t m_guardCount; ///< guard count - EventId m_coordination; ///< coordination event -}; - -} // namespace ns3 -#endif /* CHANNEL_COORDINATOR_H */ diff --git a/src/wave/model/channel-manager.cc b/src/wave/model/channel-manager.cc deleted file mode 100644 index 3834c5480..000000000 --- a/src/wave/model/channel-manager.cc +++ /dev/null @@ -1,184 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#include "channel-manager.h" - -#include "ns3/assert.h" -#include "ns3/log.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("ChannelManager"); - -NS_OBJECT_ENSURE_REGISTERED(ChannelManager); - -TypeId -ChannelManager::GetTypeId() -{ - static TypeId tid = TypeId("ns3::ChannelManager") - .SetParent() - .SetGroupName("Wave") - .AddConstructor(); - return tid; -} - -ChannelManager::ChannelManager() -{ - NS_LOG_FUNCTION(this); - m_channels.insert(std::make_pair(CCH, new WaveChannel(CCH))); - m_channels.insert(std::make_pair(SCH1, new WaveChannel(SCH1))); - m_channels.insert(std::make_pair(SCH2, new WaveChannel(SCH2))); - m_channels.insert(std::make_pair(SCH3, new WaveChannel(SCH3))); - m_channels.insert(std::make_pair(SCH4, new WaveChannel(SCH4))); - m_channels.insert(std::make_pair(SCH5, new WaveChannel(SCH5))); - m_channels.insert(std::make_pair(SCH6, new WaveChannel(SCH6))); -} - -ChannelManager::~ChannelManager() -{ - NS_LOG_FUNCTION(this); -} - -uint32_t -ChannelManager::GetCch() -{ - NS_LOG_FUNCTION_NOARGS(); - return CCH; -} - -std::vector -ChannelManager::GetSchs() -{ - NS_LOG_FUNCTION_NOARGS(); - std::vector schs; - schs.push_back(SCH1); - schs.push_back(SCH2); - schs.push_back(SCH3); - schs.push_back(SCH4); - schs.push_back(SCH5); - schs.push_back(SCH6); - return schs; -} - -std::vector -ChannelManager::GetWaveChannels() -{ - NS_LOG_FUNCTION_NOARGS(); - std::vector channels; - channels.push_back(CCH); - channels.push_back(SCH1); - channels.push_back(SCH2); - channels.push_back(SCH3); - channels.push_back(SCH4); - channels.push_back(SCH5); - channels.push_back(SCH6); - return channels; -} - -uint32_t -ChannelManager::GetNumberOfWaveChannels() -{ - NS_LOG_FUNCTION_NOARGS(); - static uint32_t NumberOfWaveChannels = GetWaveChannels().size(); - return NumberOfWaveChannels; -} - -bool -ChannelManager::IsCch(uint32_t channelNumber) -{ - NS_LOG_FUNCTION_NOARGS(); - return channelNumber == CCH; -} - -bool -ChannelManager::IsSch(uint32_t channelNumber) -{ - NS_LOG_FUNCTION_NOARGS(); - if (channelNumber < SCH1 || channelNumber > SCH6) - { - return false; - } - if (channelNumber % 2 == 1) - { - return false; - } - return (channelNumber != CCH); -} - -bool -ChannelManager::IsWaveChannel(uint32_t channelNumber) -{ - NS_LOG_FUNCTION_NOARGS(); - if (channelNumber < SCH1 || channelNumber > SCH6) - { - return false; - } - if (channelNumber % 2 == 1) - { - return false; - } - return true; -} - -uint32_t -ChannelManager::GetOperatingClass(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - return m_channels[channelNumber]->operatingClass; -} - -bool -ChannelManager::GetManagementAdaptable(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - return m_channels[channelNumber]->adaptable; -} - -WifiMode -ChannelManager::GetManagementDataRate(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - return m_channels[channelNumber]->dataRate; -} - -WifiPreamble -ChannelManager::GetManagementPreamble(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - return m_channels[channelNumber]->preamble; -} - -uint32_t -ChannelManager::GetManagementPowerLevel(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - return m_channels[channelNumber]->txPowerLevel; -} - -void -ChannelManager::DoDispose() -{ - NS_LOG_FUNCTION(this); - std::map::iterator i; - for (i = m_channels.begin(); i != m_channels.end(); ++i) - { - delete (i->second); - } - m_channels.clear(); -} - -} // namespace ns3 diff --git a/src/wave/model/channel-manager.h b/src/wave/model/channel-manager.h deleted file mode 100644 index 326a7b0e2..000000000 --- a/src/wave/model/channel-manager.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#ifndef CHANNEL_MANAGER_H -#define CHANNEL_MANAGER_H -#include "ns3/object.h" -#include "ns3/wifi-mode.h" -#include "ns3/wifi-phy-common.h" - -#include -#include - -namespace ns3 -{ - -/** - * \ingroup wave - * - * WAVE channels - * channel number | 172 | 174 | 176 | 178 | 180 | 182 | 184 | - * channel bandwidth 10MHz 10MHz 10MHz 10MHz 10MHz 10MHz 10MHz - * channel name SCH1 SCH2 SCH3 CCH SCH4 SCH5 SCH6 - * another name CH172 CH174 CH176 CH178 CH180 CH182 CH184 - * - * not support - * channel 175 : combine channel 174 and 176 - * channel 181 : combine channel 180 and 182 - */ -#define CH172 172 -#define CH174 174 -#define CH176 176 -#define CH178 178 -#define CH180 180 -#define CH182 182 -#define CH184 184 - -#define SCH1 172 -#define SCH2 174 -#define SCH3 176 -#define CCH 178 -#define SCH4 180 -#define SCH5 182 -#define SCH6 184 - -/** - * \ingroup wave - * \brief manage 7 WaveChannels and the tx information such as data rate and txPowerLevel. - * for transmitting VSA management frames. - */ -class ChannelManager : public Object -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - ChannelManager(); - ~ChannelManager() override; - - /** - * \return the channel number of WAVE CCH. - */ - static uint32_t GetCch(); - /** - * \return the channel number set of WAVE SCHs. - */ - static std::vector GetSchs(); - /** - * \return the channel number set of WAVE channels. - * - * The sequence is CCH, SCH1, SCH2, SCH3, SCH4, SCH5 and SCH6. - */ - static std::vector GetWaveChannels(); - /** - * \return the number of WAVE channels. - */ - static uint32_t GetNumberOfWaveChannels(); - /** - * \param channelNumber the specific channel - * \return whether channel is valid CCH channel - */ - static bool IsCch(uint32_t channelNumber); - /** - * \param channelNumber the specific channel - * \return whether channel is valid SCH channel - */ - static bool IsSch(uint32_t channelNumber); - /** - * \param channelNumber the specific channel - * \return whether channel is valid WAVE channel - */ - static bool IsWaveChannel(uint32_t channelNumber); - - /** - * \param channelNumber the specific channel - * \return the operating class on this channel - * - * the operating class is unused in the simulation - */ - uint32_t GetOperatingClass(uint32_t channelNumber); - /** - * \param channelNumber the specific channel - * \return the adaptable mode for management frames - */ - bool GetManagementAdaptable(uint32_t channelNumber); - /** - * \param channelNumber the specific channel - * \return the data rate for management frames - */ - WifiMode GetManagementDataRate(uint32_t channelNumber); - /** - * \param channelNumber the specific channel - * \return the preamble for management frames - */ - WifiPreamble GetManagementPreamble(uint32_t channelNumber); - /** - * \param channelNumber the specific channel - * \return the tx power level for management frames - */ - uint32_t GetManagementPowerLevel(uint32_t channelNumber); - - protected: - void DoDispose() override; - - private: - /// 1609.4-2010 Annex H - static const uint32_t DEFAULT_OPERATING_CLASS = 17; - - /// WaveChannel structure - struct WaveChannel - { - uint32_t channelNumber; ///< channel number - uint32_t operatingClass; ///< operating class - bool adaptable; ///< adaptable? - WifiMode dataRate; ///< data rate - WifiPreamble preamble; ///< preamble - uint32_t txPowerLevel; ///< transmit power level - - /** - * initializor - * \param channel the channel number - */ - WaveChannel(uint32_t channel) - : channelNumber(channel), - operatingClass(DEFAULT_OPERATING_CLASS), - adaptable(true), - dataRate(WifiMode("OfdmRate6MbpsBW10MHz")), - preamble(WIFI_PREAMBLE_LONG), - txPowerLevel(4) - { - } - }; - - std::map m_channels; ///< list of channels -}; - -} // namespace ns3 -#endif /* CHANNEL_MANAGER_H */ diff --git a/src/wave/model/channel-scheduler.cc b/src/wave/model/channel-scheduler.cc deleted file mode 100644 index f463a9e6d..000000000 --- a/src/wave/model/channel-scheduler.cc +++ /dev/null @@ -1,174 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ - -#include "channel-scheduler.h" - -#include "ns3/log.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("ChannelScheduler"); - -NS_OBJECT_ENSURE_REGISTERED(ChannelScheduler); - -/** - * \brief Get the type ID. - * \return the object TypeId - */ -TypeId -ChannelScheduler::GetTypeId() -{ - static TypeId tid = TypeId("ns3::ChannelScheduler").SetParent().SetGroupName("Wave"); - return tid; -} - -ChannelScheduler::ChannelScheduler() -{ - NS_LOG_FUNCTION(this); -} - -ChannelScheduler::~ChannelScheduler() -{ - NS_LOG_FUNCTION(this); -} - -void -ChannelScheduler::DoInitialize() -{ - // assign default CCH access when the device is initialized - AssignDefaultCchAccess(); -} - -void -ChannelScheduler::SetWaveNetDevice(Ptr device) -{ - NS_LOG_FUNCTION(this << device); - m_device = device; -} - -bool -ChannelScheduler::IsChannelAccessAssigned(uint32_t channelNumber) const -{ - NS_LOG_FUNCTION(this << channelNumber); - return (GetAssignedAccessType(channelNumber) != NoAccess); -} - -bool -ChannelScheduler::IsCchAccessAssigned() const -{ - NS_LOG_FUNCTION(this); - return (GetAssignedAccessType(CCH) != NoAccess); -} - -bool -ChannelScheduler::IsSchAccessAssigned() const -{ - NS_LOG_FUNCTION(this); - return (GetAssignedAccessType(SCH1) != NoAccess) || (GetAssignedAccessType(SCH2) != NoAccess) || - (GetAssignedAccessType(SCH3) != NoAccess) || (GetAssignedAccessType(SCH4) != NoAccess) || - (GetAssignedAccessType(SCH5) != NoAccess) || (GetAssignedAccessType(SCH6) != NoAccess); -} - -bool -ChannelScheduler::IsContinuousAccessAssigned(uint32_t channelNumber) const -{ - NS_LOG_FUNCTION(this << channelNumber); - return (GetAssignedAccessType(channelNumber) == ContinuousAccess); -} - -bool -ChannelScheduler::IsAlternatingAccessAssigned(uint32_t channelNumber) const -{ - NS_LOG_FUNCTION(this << channelNumber); - return (GetAssignedAccessType(channelNumber) == AlternatingAccess); -} - -bool -ChannelScheduler::IsExtendedAccessAssigned(uint32_t channelNumber) const -{ - NS_LOG_FUNCTION(this << channelNumber); - return (GetAssignedAccessType(channelNumber) == ExtendedAccess); -} - -bool -ChannelScheduler::IsDefaultCchAccessAssigned() const -{ - NS_LOG_FUNCTION(this); - return (GetAssignedAccessType(CCH) == DefaultCchAccess); -} - -bool -ChannelScheduler::StartSch(const SchInfo& schInfo) -{ - NS_LOG_FUNCTION(this << &schInfo); - uint32_t cn = schInfo.channelNumber; - - if (ChannelManager::IsCch(schInfo.channelNumber)) - { - NS_LOG_DEBUG("the channel access requirement for CCH is not allowed."); - return false; - } - uint32_t extends = schInfo.extendedAccess; - bool immediate = schInfo.immediateAccess; - Ptr mac = m_device->GetMac(cn); - for (EdcaParametersI i = schInfo.edcaParameters.begin(); i != schInfo.edcaParameters.end(); ++i) - { - EdcaParameter edca = i->second; - mac->ConfigureEdca(edca.cwmin, edca.cwmax, edca.aifsn, i->first); - } - - if (extends == EXTENDED_CONTINUOUS) - { - return AssignContinuousAccess(cn, immediate); - } - else if (extends == EXTENDED_ALTERNATING) - { - return AssignAlternatingAccess(cn, immediate); - } - else - { - return AssignExtendedAccess(cn, extends, immediate); - } -} - -bool -ChannelScheduler::StopSch(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - if (ChannelManager::IsCch(channelNumber)) - { - NS_LOG_DEBUG("the channel access for CCH is not allowed to be released."); - return false; - } - if (!IsChannelAccessAssigned(channelNumber)) - { - NS_LOG_DEBUG("the channel access for channel " << channelNumber - << " has already been released."); - return true; - } - return ReleaseAccess(channelNumber); -} - -void -ChannelScheduler::DoDispose() -{ - NS_LOG_FUNCTION(this); - m_device = nullptr; -} - -} // namespace ns3 diff --git a/src/wave/model/channel-scheduler.h b/src/wave/model/channel-scheduler.h deleted file mode 100644 index 6ef0a8487..000000000 --- a/src/wave/model/channel-scheduler.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#ifndef CHANNEL_SCHEDULER_H -#define CHANNEL_SCHEDULER_H - -#include "wave-net-device.h" - -#include "ns3/qos-utils.h" - -#include - -namespace ns3 -{ -class WaveNetDevice; - -/** - * \ingroup wave - * EdcaParameter structure - */ -struct EdcaParameter -{ - uint32_t cwmin; ///< minimum - uint32_t cwmax; ///< maximum - uint32_t aifsn; ///< AIFSN -}; - -/** - * \ingroup wave - * EDCA parameters typedef - */ -typedef std::map EdcaParameters; - -/** - * \ingroup wave - * EDCA parameters iterator typedef - */ -typedef std::map::const_iterator EdcaParametersI; - -#define EXTENDED_ALTERNATING 0x00 -#define EXTENDED_CONTINUOUS 0xff - -/** - * \ingroup wave - * - * \param channelNumber channel number that the SCH service - * can be made available for communications. - * \param operationalRateSet OperationalRateSet if present, as specified in IEEE Std 802.11. - * valid range: 1-127. - * \param immediateAccess Indicates that the MLME should provide immediate - * access to the SCH and not wait until the next SCH interval. - * \param extendedAccess Indicates that the MLME should provide continuous - * access (during both SCH interval and CCH interval) to the SCH for ExtendedAccess - * control channel intervals. A value of 255 indicates indefinite access. - * \param edcaParameters If present, as specified in IEEE Std 802.11. - */ -struct SchInfo -{ - uint32_t channelNumber; ///< channel number - // OperationalRateSet operationalRateSet; // not supported - bool immediateAccess; ///< immediate access - uint8_t extendedAccess; ///< extended access - EdcaParameters edcaParameters; ///< EDCA parameters - - /// Initializer - SchInfo() - : channelNumber(SCH1), - immediateAccess(false), - extendedAccess(EXTENDED_ALTERNATING) - { - } - - /** - * Initializer - * \param channel the channel number - * \param immediate true if immediate access - * \param channelAccess - */ - SchInfo(uint32_t channel, bool immediate, uint32_t channelAccess) - : channelNumber(channel), - immediateAccess(immediate), - extendedAccess(channelAccess) - { - } - - /** - * Initializer - * \param channel the channel number - * \param immediate true if immediate access - * \param channelAccess - * \param edca the EDCA parameters - */ - SchInfo(uint32_t channel, bool immediate, uint32_t channelAccess, EdcaParameters edca) - : channelNumber(channel), - immediateAccess(immediate), - extendedAccess(channelAccess), - edcaParameters(edca) - { - } -}; - -/// ChannelAccess enumeration -enum ChannelAccess -{ - ContinuousAccess, // continuous access for SCHs - AlternatingAccess, // alternating CCH and SCH access - ExtendedAccess, // extended access in SCHs - DefaultCchAccess, // default continuous CCH access - NoAccess, // no channel access assigned -}; - -/** - * \ingroup wave - * \brief This class will assign channel access for requests from higher layers. - * The channel access options include (1) continuous access for SCHs, (2) alternating - * CCH and SCH access, (3) extended access for SCHs and (4) default continuous CCH - * access. The options except (4) have an immediate parameter to enable immediate - * access assignment without the need for waiting. - * Its sub-class can use different mechanism to assign the channel access. - */ -class ChannelScheduler : public Object -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - ChannelScheduler(); - ~ChannelScheduler() override; - - /** - * \param device enable channel scheduler associated with WaveNetDevice - */ - virtual void SetWaveNetDevice(Ptr device); - /** - * \return whether CCH channel access is assigned. - */ - bool IsCchAccessAssigned() const; - /** - * \return whether SCH channel access is assigned. - */ - bool IsSchAccessAssigned() const; - /** - * \param channelNumber the specified channel number - * \return whether channel access is assigned for the channel. - */ - bool IsChannelAccessAssigned(uint32_t channelNumber) const; - /** - * \param channelNumber the specified channel number - * \return whether the continuous access is assigned for the specific channel. - */ - bool IsContinuousAccessAssigned(uint32_t channelNumber) const; - /** - * \param channelNumber the specified channel number - * \return whether the continuous access is assigned for the specific channel. - */ - bool IsAlternatingAccessAssigned(uint32_t channelNumber) const; - /** - * \param channelNumber the specified channel number - * \return whether the continuous access is assigned for the specific channel. - */ - bool IsExtendedAccessAssigned(uint32_t channelNumber) const; - /** - * \return whether the continuous access is assigned for CCHl. - */ - bool IsDefaultCchAccessAssigned() const; - /** - * \param channelNumber the specified channel number - * \return the type of current assigned channel access for the specific channel. - */ - virtual ChannelAccess GetAssignedAccessType(uint32_t channelNumber) const = 0; - - /** - * \param schInfo the request information for assigning SCH access. - * \return whether the channel access is assigned successfully. - * - * This method is called to assign channel access for sending packets. - */ - bool StartSch(const SchInfo& schInfo); - /** - * \param channelNumber indicating which channel should release - * the assigned channel access resource. - * \return true if successful. - */ - bool StopSch(uint32_t channelNumber); - - protected: - void DoInitialize() override; - void DoDispose() override; - - /** - * \param channelNumber the specific channel - * \param immediate indicate whether channel switch to channel - * \return whether the channel access is assigned successfully - * - * This method will assign alternating access for SCHs and CCH. - */ - virtual bool AssignAlternatingAccess(uint32_t channelNumber, bool immediate) = 0; - /** - * \param channelNumber the specific channel - * \param immediate indicate whether channel switch to channel - * \return whether the channel access is assigned successfully - * - * This method will assign continuous access CCH. - */ - virtual bool AssignContinuousAccess(uint32_t channelNumber, bool immediate) = 0; - /** - * \param channelNumber the specific channel - * \param extends extension duration - * \param immediate indicate whether channel switch to channel - * \return whether the channel access is assigned successfully - * - * This method will assign extended access for SCHs. - */ - virtual bool AssignExtendedAccess(uint32_t channelNumber, uint32_t extends, bool immediate) = 0; - /** - * This method will assign default CCH access for CCH. - * \return whether the channel access is assigned successfully - */ - virtual bool AssignDefaultCchAccess() = 0; - /** - * \param channelNumber indicating for which channel should release - * the assigned channel access resource. - * \return whether the channel access is released successfully - */ - virtual bool ReleaseAccess(uint32_t channelNumber) = 0; - - Ptr m_device; ///< the device -}; - -} // namespace ns3 -#endif /* CHANNEL_SCHEDULER_H */ diff --git a/src/wave/model/default-channel-scheduler.cc b/src/wave/model/default-channel-scheduler.cc deleted file mode 100644 index 3379c7e43..000000000 --- a/src/wave/model/default-channel-scheduler.cc +++ /dev/null @@ -1,449 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#include "default-channel-scheduler.h" - -#include "ns3/log.h" -#include "ns3/simulator.h" -#include "ns3/wifi-phy.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("DefaultChannelScheduler"); - -NS_OBJECT_ENSURE_REGISTERED(DefaultChannelScheduler); - -/** - * \ingroup wave - * \brief CoordinationListener class - */ -class CoordinationListener : public ChannelCoordinationListener -{ - public: - /** - * Constructor - * - * \param scheduler channel scheduler - */ - CoordinationListener(DefaultChannelScheduler* scheduler) - : m_scheduler(scheduler) - { - } - - void NotifyCchSlotStart(Time duration) override - { - m_scheduler->NotifyCchSlotStart(duration); - } - - void NotifySchSlotStart(Time duration) override - { - m_scheduler->NotifySchSlotStart(duration); - } - - void NotifyGuardSlotStart(Time duration, bool cchi) override - { - m_scheduler->NotifyGuardSlotStart(duration, cchi); - } - - private: - DefaultChannelScheduler* m_scheduler; ///< the scheduler -}; - -TypeId -DefaultChannelScheduler::GetTypeId() -{ - static TypeId tid = TypeId("ns3::DefaultChannelScheduler") - .SetParent() - .SetGroupName("Wave") - .AddConstructor(); - return tid; -} - -DefaultChannelScheduler::DefaultChannelScheduler() - : m_channelNumber(0), - m_extend(EXTENDED_CONTINUOUS), - m_channelAccess(NoAccess), - m_waitChannelNumber(0), - m_waitExtend(0), - m_coordinationListener(nullptr) -{ - NS_LOG_FUNCTION(this); -} - -DefaultChannelScheduler::~DefaultChannelScheduler() -{ - NS_LOG_FUNCTION(this); -} - -void -DefaultChannelScheduler::DoInitialize() -{ - NS_LOG_FUNCTION(this); - ChannelScheduler::DoInitialize(); -} - -void -DefaultChannelScheduler::DoDispose() -{ - NS_LOG_FUNCTION(this); - m_coordinator = nullptr; - if (m_coordinationListener) - { - m_coordinationListener = nullptr; - } - if (!m_waitEvent.IsExpired()) - { - m_waitEvent.Cancel(); - } - if (!m_extendEvent.IsExpired()) - { - m_waitEvent.Cancel(); - } - m_phy = nullptr; - ChannelScheduler::DoDispose(); -} - -void -DefaultChannelScheduler::SetWaveNetDevice(Ptr device) -{ - NS_LOG_FUNCTION(this << device); - ChannelScheduler::SetWaveNetDevice(device); - std::vector> phys = device->GetPhys(); - if (phys.size() > 1) - { - NS_LOG_WARN("The class is only in the context of single-PHY device, while there are more " - "than one PHY devices"); - } - // since default channel scheduler is in the context of single-PHY, we only use one phy object. - m_phy = device->GetPhy(0); - m_coordinator = device->GetChannelCoordinator(); - m_coordinationListener = Create(this); - m_coordinator->RegisterListener(m_coordinationListener); -} - -ChannelAccess -DefaultChannelScheduler::GetAssignedAccessType(uint32_t channelNumber) const -{ - NS_LOG_FUNCTION(this << channelNumber); - if (m_channelAccess == AlternatingAccess && channelNumber == CCH) - { - return AlternatingAccess; - } - return (m_channelNumber == channelNumber) ? m_channelAccess : NoAccess; -} - -bool -DefaultChannelScheduler::AssignAlternatingAccess(uint32_t channelNumber, bool immediate) -{ - NS_LOG_FUNCTION(this << channelNumber << immediate); - NS_ASSERT(m_channelAccess != NoAccess && m_channelNumber != 0); - uint32_t sch = channelNumber; - - if (m_channelAccess == ContinuousAccess || m_channelAccess == ExtendedAccess) - { - return false; - } - - if (m_channelAccess == AlternatingAccess) - { - return m_channelNumber == sch; - } - - // if we need immediately switch to AlternatingAccess, - // we switch to specific SCH. - if ((immediate && m_coordinator->IsSchInterval())) - { - NS_ASSERT(m_channelNumber == CCH); - SwitchToNextChannel(CCH, sch); - } - - m_channelNumber = sch; - m_channelAccess = AlternatingAccess; - return true; -} - -bool -DefaultChannelScheduler::AssignContinuousAccess(uint32_t channelNumber, bool immediate) -{ - NS_LOG_FUNCTION(this << channelNumber << immediate); - NS_ASSERT(m_channelAccess != NoAccess && m_channelNumber != 0); - uint32_t sch = channelNumber; - if (m_channelAccess == AlternatingAccess || m_channelAccess == ExtendedAccess) - { - return false; - } - - if (m_channelAccess == ContinuousAccess) - { - return m_channelNumber == sch; - } - - // if there is already an wait event for previous non-immediate request - if (!m_waitEvent.IsExpired()) - { - if (m_waitChannelNumber != sch) - { - // then the coming new request will be rejected because of FCFS - return false; - } - else - { - if (!immediate) - { - return true; - } - // then cancel this wait event and assign access for request immediately - m_waitEvent.Cancel(); - } - } - - if (immediate || m_coordinator->IsSchInterval()) - { - SwitchToNextChannel(m_channelNumber, sch); - m_channelNumber = sch; - m_channelAccess = ContinuousAccess; - } - else - { - Time wait = m_coordinator->NeedTimeToSchInterval(); - m_waitEvent = Simulator::Schedule(wait, - &DefaultChannelScheduler::AssignContinuousAccess, - this, - sch, - false); - m_waitChannelNumber = sch; - } - - return true; -} - -bool -DefaultChannelScheduler::AssignExtendedAccess(uint32_t channelNumber, - uint32_t extends, - bool immediate) -{ - NS_LOG_FUNCTION(this << channelNumber << extends << immediate); - NS_ASSERT(m_channelAccess != NoAccess && m_channelNumber != 0); - uint32_t sch = channelNumber; - if (m_channelAccess == AlternatingAccess || m_channelAccess == ContinuousAccess) - { - return false; - } - - if (m_channelAccess == ExtendedAccess) - { - if (m_channelNumber != sch) - { - return false; - } - else - { - // if current remain extends cannot fulfill the requirement for extends - Time remainTime = Simulator::GetDelayLeft(m_extendEvent); - uint32_t remainExtends = (remainTime / m_coordinator->GetSyncInterval()).GetHigh(); - return remainExtends > extends; - } - } - - // if there is already an wait event for previous non-immediate request - if (!m_waitEvent.IsExpired()) - { - NS_ASSERT(m_extendEvent.IsExpired()); - if (m_waitChannelNumber != sch) - { - // then the coming new request will be rejected because of FCFS - return false; - } - else - { - if (m_waitExtend < extends) - { - return false; - } - - if (immediate) - { - // then cancel previous wait event and - // go to below code to assign access for request immediately - m_waitEvent.Cancel(); - } - else - { - return true; - } - } - } - - if (immediate || m_coordinator->IsSchInterval()) - { - SwitchToNextChannel(m_channelNumber, sch); - m_channelNumber = sch; - m_channelAccess = ExtendedAccess; - m_extend = extends; - - Time sync = m_coordinator->GetSyncInterval(); - // the wait time to proper interval will not be calculated as extended time. - Time extendedDuration = - m_coordinator->NeedTimeToCchInterval() + MilliSeconds(extends * sync.GetMilliSeconds()); - // after end_duration time, DefaultChannelScheduler will release channel access - // automatically - m_extendEvent = Simulator::Schedule(extendedDuration, - &DefaultChannelScheduler::ReleaseAccess, - this, - sch); - } - else - { - Time wait = m_coordinator->NeedTimeToSchInterval(); - m_waitEvent = Simulator::Schedule(wait, - &DefaultChannelScheduler::AssignExtendedAccess, - this, - sch, - extends, - false); - m_waitChannelNumber = sch; - m_waitExtend = extends; - } - return true; -} - -bool -DefaultChannelScheduler::AssignDefaultCchAccess() -{ - NS_LOG_FUNCTION(this); - if (m_channelAccess == DefaultCchAccess) - { - return true; - } - if (m_channelNumber != 0) - { - // This class does not support preemptive scheduling - NS_LOG_DEBUG("channel access is already assigned for other SCHs, thus cannot assign " - "default CCH access."); - return false; - } - // CCH MAC is to attach single-PHY device and wake up for transmission. - Ptr cchMacEntity = m_device->GetMac(CCH); - if (Now().GetMilliSeconds() != 0) - { - m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{CCH, 0, WIFI_PHY_BAND_5GHZ, 0}); - Time switchTime = m_phy->GetChannelSwitchDelay(); - cchMacEntity->MakeVirtualBusy(switchTime); - } - cchMacEntity->SetWifiPhy(m_phy); - cchMacEntity->Resume(); - - m_channelAccess = DefaultCchAccess; - m_channelNumber = CCH; - m_extend = EXTENDED_CONTINUOUS; - return true; -} - -void -DefaultChannelScheduler::SwitchToNextChannel(uint32_t curChannelNumber, uint32_t nextChannelNumber) -{ - NS_LOG_FUNCTION(this << curChannelNumber << curChannelNumber); - if (m_phy->GetChannelNumber() == nextChannelNumber) - { - return; - } - Ptr curMacEntity = m_device->GetMac(curChannelNumber); - Ptr nextMacEntity = m_device->GetMac(nextChannelNumber); - // Perfect channel switch operation among multiple MAC entities in the context of single PHY - // device. first make current MAC entity in sleep mode. - curMacEntity->Suspend(); - // second unattached current MAC entity from single PHY device - curMacEntity->ResetWifiPhys(); - // third switch PHY device from current channel to next channel; - m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{nextChannelNumber, 0, WIFI_PHY_BAND_5GHZ, 0}); - // four attach next MAC entity to single PHY device - nextMacEntity->SetWifiPhy(m_phy); - // Here channel switch time is required to notify next MAC entity - // that channel access cannot be enabled in channel switch time. - Time switchTime = m_phy->GetChannelSwitchDelay(); - nextMacEntity->MakeVirtualBusy(switchTime); - // finally resume next MAC entity from sleep mode - nextMacEntity->Resume(); -} - -bool -DefaultChannelScheduler::ReleaseAccess(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - NS_ASSERT(m_channelNumber != 0); - if (m_channelNumber != channelNumber) - { - return false; - } - // cancel current SCH MAC activity and assigned default CCH access. - SwitchToNextChannel(m_channelNumber, CCH); - m_channelAccess = DefaultCchAccess; - m_channelNumber = CCH; - m_extend = EXTENDED_CONTINUOUS; - if (!m_waitEvent.IsExpired()) - { - m_waitEvent.Cancel(); - } - if (!m_extendEvent.IsExpired()) - { - m_extendEvent.Cancel(); - } - m_waitChannelNumber = 0; - m_waitExtend = 0; - return true; -} - -void -DefaultChannelScheduler::NotifyCchSlotStart(Time duration) -{ - NS_LOG_FUNCTION(this << duration); -} - -void -DefaultChannelScheduler::NotifySchSlotStart(Time duration) -{ - NS_LOG_FUNCTION(this << duration); -} - -void -DefaultChannelScheduler::NotifyGuardSlotStart(Time duration, bool cchi) -{ - NS_LOG_FUNCTION(this << duration << cchi); - // only alternating access requires channel coordination events - if (m_channelAccess != AlternatingAccess) - { - return; - } - - if (cchi) - { - SwitchToNextChannel(m_channelNumber, CCH); - Ptr mac = m_device->GetMac(CCH); - // see chapter 6.2.5 Sync tolerance - // a medium busy shall be declared during the guard interval. - mac->MakeVirtualBusy(duration); - } - else - { - Ptr mac = m_device->GetMac(m_channelNumber); - SwitchToNextChannel(CCH, m_channelNumber); - // see chapter 6.2.5 Sync tolerance - // a medium busy shall be declared during the guard interval. - mac->MakeVirtualBusy(duration); - } -} -} // namespace ns3 diff --git a/src/wave/model/default-channel-scheduler.h b/src/wave/model/default-channel-scheduler.h deleted file mode 100644 index dbb6f6761..000000000 --- a/src/wave/model/default-channel-scheduler.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#ifndef DEFAULT_CHANNEL_SCHEDULER_H -#define DEFAULT_CHANNEL_SCHEDULER_H - -#include "wave-net-device.h" - -namespace ns3 -{ -class WaveNetDevice; - -/** - * \ingroup wave - * \brief This class uses a simple mechanism to assign channel access with following features: - * (1) only in the context of single-PHY device; - * (2) FCFS (First come First service) strategy, which seems against the description of - * the standard (preemptive strategy). - */ -class DefaultChannelScheduler : public ChannelScheduler -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - DefaultChannelScheduler(); - ~DefaultChannelScheduler() override; - - /** - * \param device enable channel scheduler associated with WaveNetDevice - */ - void SetWaveNetDevice(Ptr device) override; - /** - * \param channelNumber the specified channel number - * \return the type of current assigned channel access for the specific channel. - */ - ChannelAccess GetAssignedAccessType(uint32_t channelNumber) const override; - - /** - * Notify CCH slot start - * \param duration the CCH slot duration - */ - void NotifyCchSlotStart(Time duration); - /** - * Notify SCH slot start - * \param duration the SCH slot duration - */ - void NotifySchSlotStart(Time duration); - /** - * Notify guard slot start - * \param duration the CCH slot duration - * \param cchi if true, switch to next channel - */ - void NotifyGuardSlotStart(Time duration, bool cchi); - - private: - void DoInitialize() override; - void DoDispose() override; - /** - * \param channelNumber the specific channel - * \param immediate indicate whether channel switch to channel - * \return whether the channel access is assigned successfully - * - * This method will assign alternating access for SCHs and CCH. - */ - bool AssignAlternatingAccess(uint32_t channelNumber, bool immediate) override; - /** - * \param channelNumber the specific channel - * \param immediate indicate whether channel switch to channel - * \return whether the channel access is assigned successfully - * - * This method will assign continuous SCH access CCH. - */ - bool AssignContinuousAccess(uint32_t channelNumber, bool immediate) override; - /** - * \param channelNumber the specific channel - * \param extends extension duration - * \param immediate indicate whether channel switch to channel - * \return whether the channel access is assigned successfully - * - * This method will assign extended SCH access for SCHs. - */ - bool AssignExtendedAccess(uint32_t channelNumber, uint32_t extends, bool immediate) override; - /** - * This method will assign default CCH access for CCH. - * \return whether the channel access is assigned successfully - */ - bool AssignDefaultCchAccess() override; - /** - * \param channelNumber indicating for which channel should release - * the assigned channel access resource. - * \return whether the channel access is released successfully - */ - bool ReleaseAccess(uint32_t channelNumber) override; - /** - * \param curChannelNumber switch from MAC activity for current channel - * \param nextChannelNumber switch to MAC activity for next channel - */ - void SwitchToNextChannel(uint32_t curChannelNumber, uint32_t nextChannelNumber); - - Ptr m_manager; ///< channel manager - Ptr m_coordinator; ///< channel coordinator - Ptr m_phy; ///< Phy - - /** - * when m_channelAccess is ContinuousAccess, m_channelNumber - * is continuous channel number; - * when m_channelAccess is AlternatingAccess, m_channelNumber - * is SCH channel number, another alternating channel is CCH; - * when m_channelAccess is ExtendedAccess, m_channelNumber - * is extended access, extends is the number of extends access. - * when m_channelAccess is DefaultCchAccess, m_channelNumber is CCH. - */ - uint32_t m_channelNumber; ///< channel number - uint32_t m_extend; ///< extend - EventId m_extendEvent; ///< extend event - ChannelAccess m_channelAccess; ///< channel access - - EventId m_waitEvent; ///< wait event - uint32_t m_waitChannelNumber; ///< wait channel number - uint32_t m_waitExtend; ///< wait extend - - Ptr m_coordinationListener; ///< coordination listener -}; - -} // namespace ns3 -#endif /* DEFAULT_CHANNEL_SCHEDULER_H */ diff --git a/src/wave/model/higher-tx-tag.cc b/src/wave/model/higher-tx-tag.cc deleted file mode 100644 index 0f591f71a..000000000 --- a/src/wave/model/higher-tx-tag.cc +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Junling Bu - */ -#include "higher-tx-tag.h" - -#include "ns3/abort.h" -#include "ns3/log.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("HigherLayerTxVectorTag"); - -NS_OBJECT_ENSURE_REGISTERED(HigherLayerTxVectorTag); - -TypeId -HigherLayerTxVectorTag::GetTypeId() -{ - static TypeId tid = TypeId("ns3::HigherLayerTxVectorTag") - .SetParent() - .SetGroupName("Wave") - .AddConstructor(); - return tid; -} - -TypeId -HigherLayerTxVectorTag::GetInstanceTypeId() const -{ - NS_LOG_FUNCTION(this); - return GetTypeId(); -} - -HigherLayerTxVectorTag::HigherLayerTxVectorTag() - : m_adaptable(false) -{ - NS_LOG_FUNCTION(this); -} - -HigherLayerTxVectorTag::HigherLayerTxVectorTag(WifiTxVector txVector, bool adaptable) - : m_txVector(txVector), - m_mode(txVector.GetMode()), - m_preamble(txVector.GetPreambleType()), - m_channelWidth(txVector.GetChannelWidth()), - m_adaptable(adaptable) -{ - NS_LOG_FUNCTION(this); - NS_ABORT_MSG_IF(txVector.GetPreambleType() == WIFI_PREAMBLE_HE_MU, - "HE MU is not compatible with this tag"); -} - -WifiTxVector -HigherLayerTxVectorTag::GetTxVector() const -{ - NS_LOG_FUNCTION(this); - return m_txVector; -} - -bool -HigherLayerTxVectorTag::IsAdaptable() const -{ - NS_LOG_FUNCTION(this); - return m_adaptable; -} - -uint32_t -HigherLayerTxVectorTag::GetSerializedSize() const -{ - NS_LOG_FUNCTION(this); - return (sizeof(WifiMode) + 1 + 2 + 1); -} - -void -HigherLayerTxVectorTag::Serialize(TagBuffer i) const -{ - NS_LOG_FUNCTION(this << &i); - i.Write((uint8_t*)&m_mode, sizeof(WifiMode)); - i.WriteU8(static_cast(m_preamble)); - i.WriteU16(m_channelWidth); - i.WriteU8(static_cast(m_adaptable)); -} - -void -HigherLayerTxVectorTag::Deserialize(TagBuffer i) -{ - NS_LOG_FUNCTION(this << &i); - i.Read((uint8_t*)&m_mode, sizeof(WifiMode)); - m_preamble = static_cast(i.ReadU8()); - m_channelWidth = i.ReadU16(); - m_adaptable = i.ReadU8(); - m_txVector.SetMode(m_mode); - m_txVector.SetPreambleType(m_preamble); - m_txVector.SetChannelWidth(m_channelWidth); -} - -void -HigherLayerTxVectorTag::Print(std::ostream& os) const -{ - NS_LOG_FUNCTION(this << &os); - os << " TxVector=" << m_txVector << "; Adapter=" << m_adaptable; -} - -} // namespace ns3 diff --git a/src/wave/model/higher-tx-tag.h b/src/wave/model/higher-tx-tag.h deleted file mode 100644 index 76c794547..000000000 --- a/src/wave/model/higher-tx-tag.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Junling Bu - */ -#ifndef HIGHER_LAYER_TX_VECTOR_TAG_H -#define HIGHER_LAYER_TX_VECTOR_TAG_H - -#include "ns3/tag.h" -#include "ns3/wifi-tx-vector.h" - -namespace ns3 -{ - -class Tag; -class TypeId; - -/** - * \ingroup packet - * \ingroup wave - * - * \brief This tag will be used to support higher layer control DataRate - * and TxPwr_Level for transmission. - * If the high layer enables adaptable mode, DataRate will be the - * minimum allowable value and TxPwr_Level will be the maximum - * allowable value for transmission. - * If the higher layer does not enable adaptable parameter, the - * DataRate and TxPwr_Level will be actual values for transmission. - * However, if this tag is not used and inserted in the packet, the actual - * DataRate and TxPwr_Level for transmission will be determined by MAC layer. - */ -class HigherLayerTxVectorTag : public Tag -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - TypeId GetInstanceTypeId() const override; - - HigherLayerTxVectorTag(); - /** - * Constructor - * - * \param txVector wifi transmit vector - * \param adaptable is adaptable? - */ - HigherLayerTxVectorTag(WifiTxVector txVector, bool adaptable); - /** - * \returns the tx vector for transmission - */ - WifiTxVector GetTxVector() const; - /** - * \returns the adaptable mode for transmission - */ - bool IsAdaptable() const; - - uint32_t GetSerializedSize() const override; - void Serialize(TagBuffer i) const override; - void Deserialize(TagBuffer i) override; - void Print(std::ostream& os) const override; - - private: - WifiTxVector m_txVector; ///< transmit vector - WifiMode m_mode; ///< wifi mode - WifiPreamble m_preamble; ///< wifi preamble - uint16_t m_channelWidth; ///< channel width in MHz - bool m_adaptable; ///< adaptable -}; - -} // namespace ns3 - -#endif /* HIGHER_LAYER_TX_VECTOR_TAG_H*/ diff --git a/src/wave/model/ocb-wifi-mac.cc b/src/wave/model/ocb-wifi-mac.cc deleted file mode 100644 index 068ef63ad..000000000 --- a/src/wave/model/ocb-wifi-mac.cc +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Junling Bu - */ - -#include "ocb-wifi-mac.h" - -#include "higher-tx-tag.h" -#include "vendor-specific-action.h" -#include "wave-frame-exchange-manager.h" - -#include "ns3/channel-access-manager.h" -#include "ns3/event-id.h" -#include "ns3/ht-capabilities.h" -#include "ns3/log.h" -#include "ns3/mac-rx-middle.h" -#include "ns3/pointer.h" -#include "ns3/string.h" -#include "ns3/vht-capabilities.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("OcbWifiMac"); - -NS_OBJECT_ENSURE_REGISTERED(OcbWifiMac); - -/// Wildcard BSSID -const static Mac48Address WILDCARD_BSSID = Mac48Address::GetBroadcast(); - -TypeId -OcbWifiMac::GetTypeId() -{ - static TypeId tid = TypeId("ns3::OcbWifiMac") - .SetParent() - .SetGroupName("Wave") - .AddConstructor(); - return tid; -} - -OcbWifiMac::OcbWifiMac() -{ - NS_LOG_FUNCTION(this); - // Let the lower layers know that we are acting as an OCB node - SetTypeOfStation(OCB); -} - -OcbWifiMac::~OcbWifiMac() -{ - NS_LOG_FUNCTION(this); -} - -void -OcbWifiMac::SendVsc(Ptr vsc, Mac48Address peer, OrganizationIdentifier oi) -{ - NS_LOG_FUNCTION(this << vsc << peer << oi); - WifiMacHeader hdr; - hdr.SetType(WIFI_MAC_MGT_ACTION); - hdr.SetAddr1(peer); - hdr.SetAddr2(GetAddress()); - hdr.SetAddr3(WILDCARD_BSSID); - hdr.SetDsNotFrom(); - hdr.SetDsNotTo(); - VendorSpecificActionHeader vsa; - vsa.SetOrganizationIdentifier(oi); - vsc->AddHeader(vsa); - - if (GetQosSupported()) - { - uint8_t tid = QosUtilsGetTidForPacket(vsc); - tid = tid > 7 ? 0 : tid; - GetQosTxop(tid)->Queue(vsc, hdr); - } - else - { - GetTxop()->Queue(vsc, hdr); - } -} - -void -OcbWifiMac::AddReceiveVscCallback(OrganizationIdentifier oi, VscCallback cb) -{ - NS_LOG_FUNCTION(this << oi << &cb); - m_vscManager.RegisterVscCallback(oi, cb); -} - -void -OcbWifiMac::RemoveReceiveVscCallback(OrganizationIdentifier oi) -{ - NS_LOG_FUNCTION(this << oi); - m_vscManager.DeregisterVscCallback(oi); -} - -void -OcbWifiMac::SetSsid(Ssid ssid) -{ - NS_LOG_WARN("in OCB mode we should not call SetSsid"); -} - -Ssid -OcbWifiMac::GetSsid() const -{ - NS_LOG_WARN("in OCB mode we should not call GetSsid"); - // we really do not want to return ssid, however we have to provide - return WifiMac::GetSsid(); -} - -void -OcbWifiMac::SetBssid(Mac48Address bssid) -{ - NS_LOG_WARN("in OCB mode we should not call SetBsid"); -} - -Mac48Address -OcbWifiMac::GetBssid(uint8_t /* linkId */) const -{ - NS_LOG_WARN("in OCB mode we should not call GetBssid"); - return WILDCARD_BSSID; -} - -void -OcbWifiMac::SetLinkUpCallback(Callback linkUp) -{ - NS_LOG_FUNCTION(this << &linkUp); - WifiMac::SetLinkUpCallback(linkUp); - - // The approach taken here is that, from the point of view of a STA - // in OCB mode, the link is always up, so we immediately invoke the - // callback if one is set - linkUp(); -} - -void -OcbWifiMac::SetLinkDownCallback(Callback linkDown) -{ - NS_LOG_FUNCTION(this << &linkDown); - WifiMac::SetLinkDownCallback(linkDown); - NS_LOG_WARN("in OCB mode the like will never down, so linkDown will never be called"); -} - -bool -OcbWifiMac::CanForwardPacketsTo(Mac48Address to) const -{ - return true; -} - -void -OcbWifiMac::Enqueue(Ptr packet, Mac48Address to) -{ - NS_LOG_FUNCTION(this << packet << to); - if (GetWifiRemoteStationManager()->IsBrandNew(to)) - { - // In ad hoc mode, we assume that every destination supports all - // the rates we support. - if (GetHtSupported() || GetVhtSupported(SINGLE_LINK_OP_ID)) - { - GetWifiRemoteStationManager()->AddAllSupportedMcs(to); - GetWifiRemoteStationManager()->AddStationHtCapabilities( - to, - GetHtCapabilities(SINGLE_LINK_OP_ID)); - } - if (GetVhtSupported(SINGLE_LINK_OP_ID)) - { - GetWifiRemoteStationManager()->AddStationVhtCapabilities( - to, - GetVhtCapabilities(SINGLE_LINK_OP_ID)); - } - GetWifiRemoteStationManager()->AddAllSupportedModes(to); - GetWifiRemoteStationManager()->RecordDisassociated(to); - } - - WifiMacHeader hdr; - - // If we are not a QoS STA then we definitely want to use AC_BE to - // transmit the packet. A TID of zero will map to AC_BE (through \c - // QosUtilsMapTidToAc()), so we use that as our default here. - uint8_t tid = 0; - - if (GetQosSupported()) - { - hdr.SetType(WIFI_MAC_QOSDATA); - hdr.SetQosAckPolicy(WifiMacHeader::NORMAL_ACK); - hdr.SetQosNoEosp(); - hdr.SetQosNoAmsdu(); - // About transmission of multiple frames, - // in Ad-hoc mode TXOP is not supported for now, so TxopLimit=0; - // however in OCB mode, 802.11p do not allow transmit multiple frames - // so TxopLimit must equal 0 - hdr.SetQosTxopLimit(0); - - // Fill in the QoS control field in the MAC header - tid = QosUtilsGetTidForPacket(packet); - // Any value greater than 7 is invalid and likely indicates that - // the packet had no QoS tag, so we revert to zero, which'll - // mean that AC_BE is used. - if (tid > 7) - { - tid = 0; - } - hdr.SetQosTid(tid); - } - else - { - hdr.SetType(WIFI_MAC_DATA); - } - - if (GetHtSupported() || GetVhtSupported(SINGLE_LINK_OP_ID)) - { - hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT/VHT/HE control field is - // not yet implemented (set it to 1 when implemented) - } - hdr.SetAddr1(to); - hdr.SetAddr2(GetAddress()); - hdr.SetAddr3(WILDCARD_BSSID); - hdr.SetDsNotFrom(); - hdr.SetDsNotTo(); - - if (GetQosSupported()) - { - // Sanity check that the TID is valid - NS_ASSERT(tid < 8); - GetQosTxop(tid)->Queue(packet, hdr); - } - else - { - GetTxop()->Queue(packet, hdr); - } -} - -/* - * see 802.11p-2010 chapter 11.19 - * here we only care about data packet and vsa management frame - */ -void -OcbWifiMac::Receive(Ptr mpdu, uint8_t linkId) -{ - NS_LOG_FUNCTION(this << *mpdu << +linkId); - const WifiMacHeader* hdr = &mpdu->GetHeader(); - // Create a copy of the MPDU payload because non-const operations like RemovePacketTag - // and RemoveHeader may need to be performed. - Ptr packet = mpdu->GetPacket()->Copy(); - NS_ASSERT(!hdr->IsCtl()); - NS_ASSERT(hdr->GetAddr3() == WILDCARD_BSSID); - - Mac48Address from = hdr->GetAddr2(); - Mac48Address to = hdr->GetAddr1(); - - if (GetWifiRemoteStationManager()->IsBrandNew(from)) - { - // In ad hoc mode, we assume that every destination supports all - // the rates we support. - if (GetHtSupported() || GetVhtSupported(SINGLE_LINK_OP_ID)) - { - GetWifiRemoteStationManager()->AddAllSupportedMcs(from); - GetWifiRemoteStationManager()->AddStationHtCapabilities( - from, - GetHtCapabilities(SINGLE_LINK_OP_ID)); - } - if (GetVhtSupported(SINGLE_LINK_OP_ID)) - { - GetWifiRemoteStationManager()->AddStationVhtCapabilities( - from, - GetVhtCapabilities(SINGLE_LINK_OP_ID)); - } - GetWifiRemoteStationManager()->AddAllSupportedModes(from); - GetWifiRemoteStationManager()->RecordDisassociated(from); - } - - if (hdr->IsData()) - { - if (hdr->IsQosData() && hdr->IsQosAmsdu()) - { - NS_LOG_DEBUG("Received A-MSDU from" << from); - DeaggregateAmsduAndForward(mpdu); - } - else - { - ForwardUp(packet, from, to); - } - return; - } - - // why put check here, not before "if (hdr->IsData ())" ? - // because WifiNetDevice::ForwardUp needs to m_promiscRx data packet - // and will filter data packet for itself - // so we need to filter management frame - if (to != GetAddress() && !to.IsGroup()) - { - NS_LOG_LOGIC("the management frame is not for us"); - NotifyRxDrop(packet); - return; - } - - if (hdr->IsMgt() && hdr->IsAction()) - { - // yes, we only care about VendorSpecificAction frame in OCB mode - // other management frames will be handled by WifiMac::Receive - VendorSpecificActionHeader vsaHdr; - packet->PeekHeader(vsaHdr); - if (vsaHdr.GetCategory() == CATEGORY_OF_VSA) - { - VendorSpecificActionHeader vsa; - packet->RemoveHeader(vsa); - OrganizationIdentifier oi = vsa.GetOrganizationIdentifier(); - VscCallback cb = m_vscManager.FindVscCallback(oi); - - if (cb.IsNull()) - { - NS_LOG_DEBUG("cannot find VscCallback for OrganizationIdentifier=" << oi); - return; - } - bool succeed = cb(this, oi, packet, from); - - if (!succeed) - { - NS_LOG_DEBUG("vsc callback could not handle the packet successfully"); - } - - return; - } - } - // Invoke the receive handler of our parent class to deal with any - // other frames. Specifically, this will handle Block Ack-related - // Management Action frames. - WifiMac::Receive(Create(packet, *hdr), linkId); -} - -void -OcbWifiMac::ConfigureEdca(uint32_t cwmin, uint32_t cwmax, uint32_t aifsn, AcIndex ac) -{ - NS_LOG_FUNCTION(this << cwmin << cwmax << aifsn << ac); - Ptr dcf; - switch (ac) - { - case AC_VO: - dcf = WifiMac::GetVOQueue(); - dcf->SetWifiMac(this); - dcf->SetMinCw((cwmin + 1) / 4 - 1); - dcf->SetMaxCw((cwmin + 1) / 2 - 1); - dcf->SetAifsn(aifsn); - break; - case AC_VI: - dcf = WifiMac::GetVIQueue(); - dcf->SetWifiMac(this); - dcf->SetMinCw((cwmin + 1) / 2 - 1); - dcf->SetMaxCw(cwmin); - dcf->SetAifsn(aifsn); - break; - case AC_BE: - dcf = WifiMac::GetBEQueue(); - dcf->SetWifiMac(this); - dcf->SetMinCw(cwmin); - dcf->SetMaxCw(cwmax); - dcf->SetAifsn(aifsn); - break; - case AC_BK: - dcf = WifiMac::GetBKQueue(); - dcf->SetWifiMac(this); - dcf->SetMinCw(cwmin); - dcf->SetMaxCw(cwmax); - dcf->SetAifsn(aifsn); - break; - case AC_BE_NQOS: - dcf = WifiMac::GetTxop(); - dcf->SetWifiMac(this); - dcf->SetMinCw(cwmin); - dcf->SetMaxCw(cwmax); - dcf->SetAifsn(aifsn); - break; - case AC_BEACON: - // done by ApWifiMac - break; - case AC_UNDEF: - NS_FATAL_ERROR("I don't know what to do with this"); - break; - } - - GetLink(SINGLE_LINK_OP_ID).channelAccessManager->Add(dcf); -} - -void -OcbWifiMac::SetWifiPhy(Ptr phy) -{ - NS_LOG_FUNCTION(this << phy); - WifiMac::SetWifiPhys({phy}); - NS_ABORT_MSG_IF(!phy->GetOperatingChannel().IsSet(), - "PHY operating channel must have been set"); - auto& link = GetLink(SINGLE_LINK_OP_ID); - if (link.channelAccessManager != nullptr) - { - link.channelAccessManager->SetupPhyListener(phy); - } - if (link.feManager != nullptr) - { - link.feManager->SetWifiPhy(phy); - } -} - -void -OcbWifiMac::ConfigureStandard(WifiStandard standard) -{ - NS_LOG_FUNCTION(this << standard); - NS_ASSERT(standard == WIFI_STANDARD_80211p); - - if (GetNLinks() == 0) - { - WifiMac::SetWifiPhys({nullptr}); // for the purpose of adding a link - } - - auto& link = GetLink(SINGLE_LINK_OP_ID); - - // Setup ChannelAccessManager - link.channelAccessManager = CreateObject(); - - uint32_t cwmin = 15; - uint32_t cwmax = 1023; - - if (!GetQosSupported()) - { - // The special value of AC_BE_NQOS which exists in the Access - // Category enumeration allows us to configure plain old DCF. - ConfigureEdca(cwmin, cwmax, 2, AC_BE_NQOS); - } - else - { - // Now we configure the EDCA functions - // see IEEE802.11p-2010 section 7.3.2.29 - // Wave CCH and SCHs set default 802.11p EDCA - ConfigureEdca(cwmin, cwmax, 2, AC_VO); - ConfigureEdca(cwmin, cwmax, 3, AC_VI); - ConfigureEdca(cwmin, cwmax, 6, AC_BE); - ConfigureEdca(cwmin, cwmax, 9, AC_BK); - } - - // Setup FrameExchangeManager - auto feManager = CreateObject(); - feManager->SetWifiMac(this); - feManager->SetMacTxMiddle(m_txMiddle); - feManager->SetMacRxMiddle(m_rxMiddle); - feManager->SetAddress(GetAddress()); - link.channelAccessManager->SetupFrameExchangeManager(feManager); - if (auto phy = GetWifiPhy(); phy != nullptr) - { - feManager->SetWifiPhy(phy); - link.channelAccessManager->SetupPhyListener(phy); - } - link.feManager = feManager; -} - -void -OcbWifiMac::Suspend() -{ - NS_LOG_FUNCTION(this); - GetLink(SINGLE_LINK_OP_ID).channelAccessManager->NotifySleepNow(); - GetLink(SINGLE_LINK_OP_ID).feManager->NotifySleepNow(); -} - -void -OcbWifiMac::Resume() -{ - NS_LOG_FUNCTION(this); - // wake-up operation is not required in m_low object - GetLink(SINGLE_LINK_OP_ID).channelAccessManager->NotifyWakeupNow(); -} - -void -OcbWifiMac::MakeVirtualBusy(Time duration) -{ - NS_LOG_FUNCTION(this << duration); - GetLink(SINGLE_LINK_OP_ID) - .channelAccessManager->NotifyCcaBusyStartNow(duration, WIFI_CHANLIST_PRIMARY, {}); -} - -void -OcbWifiMac::CancelTx(AcIndex ac) -{ - NS_LOG_FUNCTION(this << ac); - Ptr queue = GetQosTxop(ac); - NS_ASSERT(queue); - // reset and flush queue - queue->GetWifiMacQueue()->Flush(); -} - -void -OcbWifiMac::Reset() -{ - NS_LOG_FUNCTION(this); - // The switching event is used to notify MAC entity reset its operation. - GetLink(SINGLE_LINK_OP_ID).channelAccessManager->NotifySwitchingStartNow(Time(0)); - GetLink(SINGLE_LINK_OP_ID).feManager->NotifySwitchingStartNow(Time(0)); -} - -void -OcbWifiMac::EnableForWave(Ptr device) -{ - NS_LOG_FUNCTION(this << device); - // To extend current OcbWifiMac for WAVE 1609.4, we shall use WaveFrameExchangeManager - StaticCast(GetLink(SINGLE_LINK_OP_ID).feManager) - ->SetWaveNetDevice(device); -} - -std::optional -OcbWifiMac::GetLinkIdByAddress(const Mac48Address& address) const -{ - return 0; -} - -void -OcbWifiMac::DoDispose() -{ - NS_LOG_FUNCTION(this); - WifiMac::DoDispose(); -} - -} // namespace ns3 diff --git a/src/wave/model/ocb-wifi-mac.h b/src/wave/model/ocb-wifi-mac.h deleted file mode 100644 index c3a2e5c73..000000000 --- a/src/wave/model/ocb-wifi-mac.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Junling Bu - */ -#ifndef OCB_WIFI_MAC_H -#define OCB_WIFI_MAC_H - -#include "vendor-specific-action.h" -#include "wave-net-device.h" - -#include "ns3/object-factory.h" -#include "ns3/wifi-mac-queue.h" -#include "ns3/wifi-mac.h" - -namespace ns3 -{ - -class OrganizationIdentifier; -class WaveNetDevice; - -/** - * \brief STAs communicate with each directly outside the context of a BSS - * \ingroup wave - * - * In OCB mac mode,synchronization, association, dis-association - * and authentication of normal wifi are not used for wireless access in - * vehicular environments. - * - * Although Timing Advertisement frame is a specific management frame defined - * in 802.11p. It is mainly used by IEEE Std 1609.4 for channel switch synchronization. - * However in simulation nodes are supposed to have GPS synchronization ability, - * so we will not implement this feature. - */ -class OcbWifiMac : public WifiMac -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - OcbWifiMac(); - ~OcbWifiMac() override; - /** - * \param vsc management packet to send. - * \param peer the address to which the packet should be sent. - * \param oi Organization Identifier field - * see 7.3.1.31 Organization Identifier field and 10.3.29 Vendor-specific action - * - * management information can be transmitted over vendor specific action frame. - * This will be mainly called by IEEE Std 1609.4 to send WSA from IEEE Std 1609.3 - */ - void SendVsc(Ptr vsc, Mac48Address peer, OrganizationIdentifier oi); - /** - * \param oi Organization Identifier - * \param cb callback to invoke whenever a vendor specific action frame has been received and - * must be forwarded to the higher layers. every node shall register first if it wants to - * receive specific vendor specific content. - */ - void AddReceiveVscCallback(OrganizationIdentifier oi, VscCallback cb); - /** - * \param oi Organization Identifier - */ - void RemoveReceiveVscCallback(OrganizationIdentifier oi); - - /** - * \returns the ssid which this MAC layer is going to try to stay in. - * - * This method shall not be used in WAVE environment and - * here it will overloaded to log warn message - */ - virtual Ssid GetSsid() const; - /** - * \param ssid the current ssid of this MAC layer. - * - * This method shall not be used in WAVE environment and - * here it will overloaded to log warn message - */ - virtual void SetSsid(Ssid ssid); - /** - * \param bssid the BSSID of the network that this device belongs to. - * This method shall not be used in WAVE environment and - * here it will overloaded to log warn message - */ - virtual void SetBssid(Mac48Address bssid); - /** - * This method shall not be used in WAVE environment and - * here it will overloaded to log warn message - * \return An invalid BSSID. - */ - virtual Mac48Address GetBssid(uint8_t /* linkId */) const; - /** - * SetLinkUpCallback and SetLinkDownCallback will be overloaded - * In OCB mode, stations can send packets directly whenever they want - * so the link is always up and never down even during channel switch - */ - /** - * \param linkUp the callback to invoke when the link becomes up. - */ - void SetLinkUpCallback(Callback linkUp) override; - /** - * \param linkDown the callback to invoke when the link becomes down. - */ - virtual void SetLinkDownCallback(Callback linkDown); - /** - * \param packet the packet to send. - * \param to the address to which the packet should be sent. - * - * The packet should be enqueued in a tx queue, and should be - * dequeued as soon as the channel access function determines that - * access is granted to this MAC. - */ - void Enqueue(Ptr packet, Mac48Address to) override; - bool CanForwardPacketsTo(Mac48Address to) const override; - /** - * \param cwmin the min contention window - * \param cwmax the max contention window - * \param aifsn the arbitration inter-frame space - * \param ac the access category index - * - * configure EDCA queue parameters - */ - void ConfigureEdca(uint32_t cwmin, uint32_t cwmax, uint32_t aifsn, AcIndex ac); - - // below six public methods are used for MAC extension defined in IEEE 1609.4 - /** - * \param device make current MAC entity associated with WaveNetDevice - * - * To support MAC extension for multiple channel operation, - * WaveMacLow object will be used to replace original MacLow object. - */ - void EnableForWave(Ptr device); - /** - * To support MAC extension for multiple channel operation, - * Suspend the activity in current MAC entity - */ - void Suspend(); - /** - * To support MAC extension for multiple channel operation, - * Resume the activity of suspended MAC entity - */ - void Resume(); - /** - * \param duration the virtual busy time for MAC entity - * - * To support MAC extension for multiple channel operation, - * Notify MAC entity busy for some time to prevent transmission - */ - void MakeVirtualBusy(Time duration); - /** - * \param ac the specified access category - * - * To support MAC extension for multiple channel operation, - * Cancel transmit operation for internal queue associated with a specified Access Category. - */ - void CancelTx(AcIndex ac); - /** - * To support MAC extension for multiple channel operation, - * Reset current MAC entity and flush its internal queues. - */ - void Reset(); - /** - * Set the PHY. - * - * \param phy the PHY object - */ - void SetWifiPhy(Ptr phy); - - // Inherited from base class - void ConfigureStandard(WifiStandard standard) override; - - protected: - void DoDispose() override; - - private: - void Receive(Ptr mpdu, uint8_t linkId) override; - std::optional GetLinkIdByAddress(const Mac48Address& address) const override; - - VendorSpecificContentManager m_vscManager; ///< VSC manager -}; - -} // namespace ns3 -#endif /* OCB_WIFI_MAC_H */ diff --git a/src/wave/model/vendor-specific-action.cc b/src/wave/model/vendor-specific-action.cc deleted file mode 100644 index 720bb07a1..000000000 --- a/src/wave/model/vendor-specific-action.cc +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2013 Dalian University of Technology - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#include "vendor-specific-action.h" - -#include "ns3/assert.h" -#include "ns3/log.h" - -#include -#include -#include - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("VendorSpecificAction"); - -/*********** OrganizationIdentifier *******/ - -ATTRIBUTE_HELPER_CPP(OrganizationIdentifier); - -OrganizationIdentifier::OrganizationIdentifier() - : m_type(Unknown) -{ - NS_LOG_FUNCTION(this); - m_type = Unknown; - std::memset(m_oi, 0, 5); -} - -OrganizationIdentifier::OrganizationIdentifier(const uint8_t* str, uint32_t length) -{ - NS_LOG_FUNCTION(this << str << length); - if (length == 3) - { - m_type = OUI24; - std::memcpy(m_oi, str, length); - } - else if (length == 5) - { - m_type = OUI36; - std::memcpy(m_oi, str, length); - } - else - { - m_type = Unknown; - NS_FATAL_ERROR("cannot support organization identifier with length=" << length); - } -} - -OrganizationIdentifier& -OrganizationIdentifier::operator=(const OrganizationIdentifier& oi) -{ - this->m_type = oi.m_type; - std::memcpy(this->m_oi, oi.m_oi, 5); - return (*this); -} - -OrganizationIdentifier::~OrganizationIdentifier() -{ - NS_LOG_FUNCTION(this); -} - -uint8_t -OrganizationIdentifier::GetManagementId() const -{ - NS_LOG_FUNCTION(this); - NS_ASSERT(m_type == OUI36); - return (m_oi[4] & 0x0f); -} - -bool -OrganizationIdentifier::IsNull() const -{ - NS_LOG_FUNCTION(this); - return m_type == Unknown; -} - -uint32_t -OrganizationIdentifier::GetSerializedSize() const -{ - NS_LOG_FUNCTION(this); - switch (m_type) - { - case OUI24: - return 3; - case OUI36: - return 5; - case Unknown: - default: - NS_FATAL_ERROR_NO_MSG(); - return 0; - } -} - -void -OrganizationIdentifier::SetType(OrganizationIdentifierType type) -{ - NS_LOG_FUNCTION(this); - m_type = type; -} - -OrganizationIdentifier::OrganizationIdentifierType -OrganizationIdentifier::GetType() const -{ - NS_LOG_FUNCTION(this); - return m_type; -} - -void -OrganizationIdentifier::Serialize(Buffer::Iterator start) const -{ - NS_LOG_FUNCTION(this << &start); - start.Write(m_oi, GetSerializedSize()); -} - -/* because OrganizationIdentifier field is not standard - * and the length of OrganizationIdentifier is variable - * so data parse here is troublesome - */ -uint32_t -OrganizationIdentifier::Deserialize(Buffer::Iterator start) -{ - NS_LOG_FUNCTION(this << &start); - // first try to parse OUI24 with 3 bytes - start.Read(m_oi, 3); - for (std::vector::iterator i = OrganizationIdentifiers.begin(); - i != OrganizationIdentifiers.end(); - ++i) - { - if ((i->m_type == OUI24) && (std::memcmp(i->m_oi, m_oi, 3) == 0)) - { - m_type = OUI24; - return 3; - } - } - - // then try to parse OUI36 with 5 bytes - start.Read(m_oi + 3, 2); - for (std::vector::iterator i = OrganizationIdentifiers.begin(); - i != OrganizationIdentifiers.end(); - ++i) - { - if ((i->m_type == OUI36) && (std::memcmp(i->m_oi, m_oi, 4) == 0)) - { - // OUI36 first check 4 bytes, then check half of the 5th byte - if ((i->m_oi[4] & 0xf0) == (m_oi[4] & 0xf0)) - { - m_type = OUI36; - return 5; - } - } - } - - // if we cannot deserialize the organization identifier field, - // we will fail - NS_FATAL_ERROR("cannot deserialize the organization identifier field successfully"); - return 0; -} - -/** - * equality operator - * \param a left side object - * \param b right side object - * \returns true if equal - */ -bool -operator==(const OrganizationIdentifier& a, const OrganizationIdentifier& b) -{ - if (a.m_type != b.m_type) - { - return false; - } - - if (a.m_type == OrganizationIdentifier::OUI24) - { - return memcmp(a.m_oi, b.m_oi, 3) == 0; - } - - if (a.m_type == OrganizationIdentifier::OUI36) - { - return (memcmp(a.m_oi, b.m_oi, 4) == 0) && ((a.m_oi[4] & 0xf0) == (b.m_oi[4] & 0xf0)); - } - - return false; -} - -/** - * inequality operator - * \param a left side object - * \param b right side object - * \returns true if not equal - */ -bool -operator!=(const OrganizationIdentifier& a, const OrganizationIdentifier& b) -{ - return !(a == b); -} - -/** - * less than operator - * \param a left side object - * \param b right side object - * \returns true if a < b - */ -bool -operator<(const OrganizationIdentifier& a, const OrganizationIdentifier& b) -{ - return memcmp(a.m_oi, b.m_oi, std::min(a.m_type, b.m_type)) < 0; -} - -/** - * output operator - * \param os output stream - * \param oi organization identifier - * \returns output stream - */ -std::ostream& -operator<<(std::ostream& os, const OrganizationIdentifier& oi) -{ - for (int i = 0; i < oi.m_type; i++) - { - os << "0x" << std::hex << static_cast(oi.m_oi[i]) << " "; - } - os << std::endl; - return os; -} - -/** - * input operator - * \param is input stream - * \param oi organization identifier - * \returns input stream - */ -std::istream& -operator>>(std::istream& is, const OrganizationIdentifier& oi) -{ - return is; -} - -/*********** VendorSpecificActionHeader *******/ -NS_OBJECT_ENSURE_REGISTERED(VendorSpecificActionHeader); - -VendorSpecificActionHeader::VendorSpecificActionHeader() - : m_oi(), - m_category(CATEGORY_OF_VSA) -{ - NS_LOG_FUNCTION(this); -} - -VendorSpecificActionHeader::~VendorSpecificActionHeader() -{ - NS_LOG_FUNCTION(this); -} - -void -VendorSpecificActionHeader::SetOrganizationIdentifier(OrganizationIdentifier oi) -{ - NS_LOG_FUNCTION(this << oi); - m_oi = oi; -} - -OrganizationIdentifier -VendorSpecificActionHeader::GetOrganizationIdentifier() const -{ - NS_LOG_FUNCTION(this); - return m_oi; -} - -TypeId -VendorSpecificActionHeader::GetTypeId() -{ - static TypeId tid = TypeId("ns3::VendorSpecificActionHeader") - .SetParent
() - .SetGroupName("Wave") - .AddConstructor(); - - return tid; -} - -uint8_t -VendorSpecificActionHeader::GetCategory() const -{ - NS_LOG_FUNCTION(this); - return m_category; -} - -TypeId -VendorSpecificActionHeader::GetInstanceTypeId() const -{ - NS_LOG_FUNCTION(this); - return GetTypeId(); -} - -void -VendorSpecificActionHeader::Print(std::ostream& os) const -{ - NS_LOG_FUNCTION(this << &os); - os << "VendorSpecificActionHeader[ " - << "category = 0x" << std::hex << (int)m_category << "organization identifier = " << m_oi - << std::dec; -} - -uint32_t -VendorSpecificActionHeader::GetSerializedSize() const -{ - NS_LOG_FUNCTION(this); - return sizeof(m_category) + m_oi.GetSerializedSize(); -} - -void -VendorSpecificActionHeader::Serialize(Buffer::Iterator start) const -{ - NS_LOG_FUNCTION(this << &start); - start.WriteU8(m_category); - m_oi.Serialize(start); -} - -uint32_t -VendorSpecificActionHeader::Deserialize(Buffer::Iterator start) -{ - NS_LOG_FUNCTION(this << &start); - m_category = start.ReadU8(); - if (m_category != CATEGORY_OF_VSA) - { - return 0; - } - m_oi.Deserialize(start); - - return GetSerializedSize(); -} - -/********* VendorSpecificContentManager ***********/ -VendorSpecificContentManager::VendorSpecificContentManager() -{ - NS_LOG_FUNCTION(this); -} - -VendorSpecificContentManager::~VendorSpecificContentManager() -{ - NS_LOG_FUNCTION(this); -} - -void -VendorSpecificContentManager::RegisterVscCallback(OrganizationIdentifier oi, VscCallback cb) -{ - NS_LOG_FUNCTION(this << oi << &cb); - if (IsVscCallbackRegistered(oi)) - { - NS_LOG_WARN("there is already a VsaCallback registered for OrganizationIdentifier " << oi); - } - m_callbacks.insert(std::make_pair(oi, cb)); -} - -void -VendorSpecificContentManager::DeregisterVscCallback(OrganizationIdentifier& oi) -{ - NS_LOG_FUNCTION(this << oi); - m_callbacks.erase(oi); -} - -bool -VendorSpecificContentManager::IsVscCallbackRegistered(OrganizationIdentifier& oi) -{ - NS_LOG_FUNCTION(this << oi); - if (m_callbacks.find(oi) == m_callbacks.end()) - { - OrganizationIdentifiers.push_back(oi); - return false; - } - return true; -} - -/// VSC callback function -static VscCallback null_callback = MakeNullCallback, - const OrganizationIdentifier&, - Ptr, - const Address&>(); - -VscCallback -VendorSpecificContentManager::FindVscCallback(OrganizationIdentifier& oi) -{ - NS_LOG_FUNCTION(this << oi); - VscCallbacksI i; - i = m_callbacks.find(oi); - return (i == m_callbacks.end()) ? null_callback : i->second; -} - -} // namespace ns3 diff --git a/src/wave/model/vendor-specific-action.h b/src/wave/model/vendor-specific-action.h deleted file mode 100644 index aab4117f6..000000000 --- a/src/wave/model/vendor-specific-action.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2013 Dalian University of Technology - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#ifndef Vendor_Specific_Action_H -#define Vendor_Specific_Action_H - -#include "ns3/address.h" -#include "ns3/attribute-helper.h" -#include "ns3/attribute.h" -#include "ns3/header.h" -#include "ns3/packet.h" -#include "ns3/pointer.h" - -#include -#include - -namespace ns3 -{ - -class WifiMac; -class VendorSpecificContentManager; - -/** - * \ingroup wave - * - * \brief the organization identifier is a public organizationally - * unique identifier assigned by the IEEE. - * - * Similar to protocol field of data packets that indicates which - * entity of higher layer should handle received packets, Organization - * Identifier field is used in Vendor Specific Action frames to - * indicate which entity or higher layer should handle vendor specific - * content. - * Normally the value is assigned by IEEE and the length of field is - * either 24 bits or 36 bits. - * For more, see IEEE802.11p-2010 section 7.3.1.31 and 7.4.5 - * - * \see attribute_OrganizationIdentifier - */ -class OrganizationIdentifier -{ - public: - OrganizationIdentifier(); - /** - * Constructor - * - * \param str identifier name - * \param length identifier length - */ - OrganizationIdentifier(const uint8_t* str, uint32_t length); - /** - * Assignment operator - * \param oi object to copy from - * \return reference to the new object - */ - OrganizationIdentifier& operator=(const OrganizationIdentifier& oi); - virtual ~OrganizationIdentifier(); - - /// OrganizationIdentifierType enumeration - enum OrganizationIdentifierType - { - OUI24 = 3, // 3 bytes - OUI36 = 5, // 5 bytes - Unknown = 0, - }; - - /** - * \returns last 4 bits when OrganizationIdentifier is OUI36 - */ - uint8_t GetManagementId() const; - /** - * \returns whether current OrganizationIdentifier is initial state - */ - bool IsNull() const; - /** - * \param type set the type of current OrganizationIdentifier - */ - void SetType(OrganizationIdentifierType type); - /** - * \returns whether this OrganizationIdentifier is OUI24 or OUI36. - */ - OrganizationIdentifierType GetType() const; - - // below methods will be called by VendorSpecificActionHeader - /** - * Get serialized size - * \returns the serialized size - */ - uint32_t GetSerializedSize() const; - /** - * Serialize to buffer - * \param start the iterator - */ - void Serialize(Buffer::Iterator start) const; - /** - * Deserialize from buffer - * \param start the iterator - * \returns the deserialize size - */ - uint32_t Deserialize(Buffer::Iterator start); - - private: - friend bool operator==(const OrganizationIdentifier& a, const OrganizationIdentifier& b); - friend bool operator!=(const OrganizationIdentifier& a, const OrganizationIdentifier& b); - friend bool operator<(const OrganizationIdentifier& a, const OrganizationIdentifier& b); - friend std::ostream& operator<<(std::ostream& os, const OrganizationIdentifier& oi); - friend std::istream& operator>>(std::istream& is, const OrganizationIdentifier& oi); - - OrganizationIdentifierType m_type; ///< OI type - uint8_t m_oi[5]; ///< organization identifier -}; - -ATTRIBUTE_HELPER_HEADER(OrganizationIdentifier); - -bool operator==(const OrganizationIdentifier& a, const OrganizationIdentifier& b); -bool operator!=(const OrganizationIdentifier& a, const OrganizationIdentifier& b); -bool operator<(const OrganizationIdentifier& a, const OrganizationIdentifier& b); - -std::ostream& operator<<(std::ostream& os, const OrganizationIdentifier& oi); -std::istream& operator>>(std::istream& is, const OrganizationIdentifier& oi); - -/** - * see IEEE 802.11-2007 chapter 7.3.1.11 - * Table 7-24—Category values - */ -const static uint8_t CATEGORY_OF_VSA = 127; - -/** - * \ingroup wave - * See IEEE 802.11-2007 chapter 7.3.1.11 and 7.4.5 - * also IEEE 802.11p-2010 chapter 7.4.5 - * Although WifiActionHeader has been defined in wifi mgt-header.h/.cc, - * it is not a good way to inherit from it or add vendor specific action support. - * The reason is Action field. Other Action frames contains Action field, and - * the VSA frame contains OUI or variable OrganizationIdentifier instead of one byte Action field. - * Header format: | Category | Organization IdentifierType | Vendor Specific content | - * Octets: 1 j Variable - * - * In ns-3, VSA frame will be divided into VendorSpecificActionHeader vsaHeader - * and Packet vsc that indicates vendor specific content. - * - * This frame is used by IEEE 1609.4 to send WSA packet of IEEE 1609.3, - * and if users want to send management information without customized management - * frames, he can use VSA frames. - */ -class VendorSpecificActionHeader : public Header -{ - public: - VendorSpecificActionHeader(); - ~VendorSpecificActionHeader() override; - - /** - * \param oi the OrganizationIdentifier of current VSA header - */ - void SetOrganizationIdentifier(OrganizationIdentifier oi); - /** - * \returns current OrganizationIdentifier of the VSA header - */ - OrganizationIdentifier GetOrganizationIdentifier() const; - /** - * Get the category field - * - * The category field shall be CATEGORY_OF_VSA - * - * \return The category field - */ - uint8_t GetCategory() const; - - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - TypeId GetInstanceTypeId() const override; - void Print(std::ostream& os) const override; - uint32_t GetSerializedSize() const override; - void Serialize(Buffer::Iterator start) const override; - uint32_t Deserialize(Buffer::Iterator start) override; - - private: - OrganizationIdentifier m_oi; ///< OI - uint8_t m_category; ///< category -}; - -/** - * \param mac a pointer to the mac object which is calling this callback - * \param oi the organization identifier of vendor specific action frame - * \param packet the vendor specific content packet received - * \param sender the address of the sender - * \returns true if the callback could handle the packet successfully; - * false otherwise. - */ -typedef Callback, - const OrganizationIdentifier&, - Ptr, - const Address&> - VscCallback; - -/** - * \ingroup wave - * - * VendorSpecificContentManager class - */ -class VendorSpecificContentManager -{ - public: - VendorSpecificContentManager(); - virtual ~VendorSpecificContentManager(); - /** - * \param oi the specific OrganizationIdentifier when receive management information - * by VendorSpecificAction management frame. - * \param cb the receive callback when oi related management packets are received - */ - void RegisterVscCallback(OrganizationIdentifier oi, VscCallback cb); - /** - * \param oi the specific OrganizationIdentifier when receive management information - * by VendorSpecificAction management frame. - */ - void DeregisterVscCallback(OrganizationIdentifier& oi); - /** - * \param oi the specific OrganizationIdentifier when receive management information - * by VendorSpecificAction management frame. - * \return true if registered - */ - bool IsVscCallbackRegistered(OrganizationIdentifier& oi); - /** - * \param oi the specific OrganizationIdentifier when receive management information - * by VendorSpecificAction management frame. - * \return VscCallback - */ - VscCallback FindVscCallback(OrganizationIdentifier& oi); - - private: - /// VSC callback typedef - typedef std::map VscCallbacks; - /// VSC callback iterator typedef - typedef std::map::iterator VscCallbacksI; - - VscCallbacks m_callbacks; ///< VSC callbacks -}; - -static std::vector OrganizationIdentifiers; ///< the OIs -} // namespace ns3 - -#endif /* Vendor_Specific_Action_H */ diff --git a/src/wave/model/vsa-manager.cc b/src/wave/model/vsa-manager.cc deleted file mode 100644 index f9647f8d6..000000000 --- a/src/wave/model/vsa-manager.cc +++ /dev/null @@ -1,293 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#include "vsa-manager.h" - -#include "higher-tx-tag.h" -#include "wave-net-device.h" - -#include "ns3/log.h" -#include "ns3/simulator.h" -#include "ns3/socket.h" -#include "ns3/wifi-phy.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("VsaManager"); - -NS_OBJECT_ENSURE_REGISTERED(VsaManager); - -/// OI bytes for use in organization identifier -const static uint8_t oi_bytes_1609[5] = {0x00, 0x50, 0xC2, 0x4A, 0x40}; -/// OI for IEEE standard 1609 -const static OrganizationIdentifier oi_1609 = OrganizationIdentifier(oi_bytes_1609, 5); - -TypeId -VsaManager::GetTypeId() -{ - static TypeId tid = TypeId("ns3::VsaManager") - .SetParent() - .SetGroupName("Wave") - .AddConstructor(); - return tid; -} - -VsaManager::VsaManager() - : m_device(nullptr) -{ - m_vsaReceived = MakeNullCallback, const Address&, uint32_t, uint32_t>(); -} - -VsaManager::~VsaManager() -{ -} - -void -VsaManager::DoDispose() -{ - NS_LOG_FUNCTION(this); - RemoveAll(); - m_device = nullptr; -} - -void -VsaManager::DoInitialize() -{ - std::map> macs = m_device->GetMacs(); - for (std::map>::iterator i = macs.begin(); i != macs.end(); ++i) - { - i->second->AddReceiveVscCallback(oi_1609, MakeCallback(&VsaManager::ReceiveVsc, this)); - } -} - -void -VsaManager::SetWaveNetDevice(Ptr device) -{ - NS_LOG_FUNCTION(this << device); - m_device = device; -} - -void -VsaManager::SendVsa(const VsaInfo& vsaInfo) -{ - NS_LOG_FUNCTION(this << &vsaInfo); - OrganizationIdentifier oi; - if (vsaInfo.oi.IsNull()) - { - // refer to 1609.4-2010 chapter 6.4.1.1 - uint8_t oibytes[5] = {0x00, 0x50, 0xC2, 0x4A, 0x40}; - oibytes[4] |= (vsaInfo.managementId & 0x0f); - oi = OrganizationIdentifier(oibytes, 5); - } - else - { - oi = vsaInfo.oi; - } - - // if destination MAC address is the unicast address or repeat rate is 0, - // then only single one VSA frame is to be sent. - if (vsaInfo.peer.IsGroup() && (vsaInfo.repeatRate != 0)) - { - VsaWork* vsa = new VsaWork(); - vsa->sentInterval = vsaInfo.sendInterval; - vsa->channelNumber = vsaInfo.channelNumber; - vsa->peer = vsaInfo.peer; - vsa->repeatPeriod = MilliSeconds(VSA_REPEAT_PERIOD * 1000 / vsaInfo.repeatRate); - vsa->vsc = vsaInfo.vsc; - vsa->oi = oi; - vsa->repeat = Simulator::Schedule(vsa->repeatPeriod, &VsaManager::DoRepeat, this, vsa); - m_vsas.push_back(vsa); - } - DoSendVsa(vsaInfo.sendInterval, vsaInfo.channelNumber, vsaInfo.vsc->Copy(), oi, vsaInfo.peer); -} - -void -VsaManager::DoRepeat(VsaWork* vsa) -{ - NS_LOG_FUNCTION(this << vsa); - vsa->repeat = Simulator::Schedule(vsa->repeatPeriod, &VsaManager::DoRepeat, this, vsa); - DoSendVsa(vsa->sentInterval, vsa->channelNumber, vsa->vsc->Copy(), vsa->oi, vsa->peer); -} - -void -VsaManager::DoSendVsa(VsaTransmitInterval interval, - uint32_t channel, - Ptr vsc, - OrganizationIdentifier oi, - Mac48Address peer) -{ - NS_LOG_FUNCTION(this << interval << channel << vsc << oi << peer); - NS_ASSERT(m_device); - Ptr coordinator = m_device->GetChannelCoordinator(); - Ptr scheduler = m_device->GetChannelScheduler(); - Ptr manager = m_device->GetChannelManager(); - - // if the request is for transmitting in SCH Interval (or CCH Interval), but currently - // is not in SCH Interval (or CCH Interval) and , then the WAVE device will wait - // some time to insert this VSA frame into MAC internal queue. - // if the request is for transmitting in any channel interval, then the WAVE device - // insert this VSA frame into MAC internal queue immediately. - if (interval == VSA_TRANSMIT_IN_SCHI) - { - Time wait = coordinator->NeedTimeToSchInterval(); - if (wait != Seconds(0)) - { - Simulator::Schedule(wait, - &VsaManager::DoSendVsa, - this, - interval, - channel, - vsc, - oi, - peer); - return; - } - } - else if (interval == VSA_TRANSMIT_IN_CCHI) - { - Time wait = coordinator->NeedTimeToCchInterval(); - if (wait != Seconds(0)) - { - Simulator::Schedule(wait, - &VsaManager::DoSendVsa, - this, - interval, - channel, - vsc, - oi, - peer); - return; - } - } - else - { - NS_ASSERT(interval == VSA_TRANSMIT_IN_BOTHI); - // do nothing here, since VSA_IN_BOTHI allows to sent VSA frames in any interval. - } - - if (!scheduler->IsChannelAccessAssigned(channel)) - { - NS_LOG_DEBUG("there is no channel access assigned for channel " << channel); - return; - } - - // refer to 1609.4-2010 chapter 5.4.1 - // Management frames are assigned the highest AC (AC_VO). - SocketPriorityTag priorityTag; - priorityTag.SetPriority(7); - vsc->AddPacketTag(priorityTag); - - WifiTxVector txVector; - txVector.SetChannelWidth(10); - txVector.SetTxPowerLevel(manager->GetManagementPowerLevel(channel)); - txVector.SetMode(manager->GetManagementDataRate(channel)); - txVector.SetPreambleType(manager->GetManagementPreamble(channel)); - HigherLayerTxVectorTag tag = - HigherLayerTxVectorTag(txVector, manager->GetManagementAdaptable(channel)); - vsc->AddPacketTag(tag); - - Ptr mac = m_device->GetMac(channel); - mac->SendVsc(vsc, peer, oi); -} - -void -VsaManager::RemoveAll() -{ - NS_LOG_FUNCTION(this); - for (std::vector::iterator i = m_vsas.begin(); i != m_vsas.end(); ++i) - { - if (!(*i)->repeat.IsExpired()) - { - (*i)->repeat.Cancel(); - } - (*i)->vsc = nullptr; - delete (*i); - } - m_vsas.clear(); -} - -void -VsaManager::RemoveByChannel(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - for (std::vector::iterator i = m_vsas.begin(); i != m_vsas.end();) - { - if ((*i)->channelNumber == channelNumber) - { - if (!(*i)->repeat.IsExpired()) - { - (*i)->repeat.Cancel(); - } - (*i)->vsc = nullptr; - delete (*i); - i = m_vsas.erase(i); - } - else - { - ++i; - } - } -} - -void -VsaManager::RemoveByOrganizationIdentifier(const OrganizationIdentifier& oi) -{ - NS_LOG_FUNCTION(this << oi); - for (std::vector::iterator i = m_vsas.begin(); i != m_vsas.end();) - { - if ((*i)->oi == oi) - { - if (!(*i)->repeat.IsExpired()) - { - (*i)->repeat.Cancel(); - } - (*i)->vsc = nullptr; - delete (*i); - i = m_vsas.erase(i); - } - else - { - ++i; - } - } -} - -void -VsaManager::SetWaveVsaCallback( - Callback, const Address&, uint32_t, uint32_t> vsaCallback) -{ - NS_LOG_FUNCTION(this); - m_vsaReceived = vsaCallback; -} - -bool -VsaManager::ReceiveVsc(Ptr mac, - const OrganizationIdentifier& oi, - Ptr vsc, - const Address& src) -{ - NS_LOG_FUNCTION(this << mac << oi << vsc << src); - NS_ASSERT(oi == oi_1609); - if (m_vsaReceived.IsNull()) - { - return true; - } - uint32_t channelNumber = mac->GetWifiPhy()->GetChannelNumber(); - uint32_t managementId = oi.GetManagementId(); - return m_vsaReceived(vsc, src, managementId, channelNumber); -} -} // namespace ns3 diff --git a/src/wave/model/vsa-manager.h b/src/wave/model/vsa-manager.h deleted file mode 100644 index 79c0c9048..000000000 --- a/src/wave/model/vsa-manager.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2013 Dalian University of Technology - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#ifndef VSA_MANAGER_H -#define VSA_MANAGER_H -#include "wave-net-device.h" - -#include - -namespace ns3 -{ - -/** - * \ingroup wave - * - * \brief indicate which interval the VSA frames will be transmitted in. - * VSA_TRANSMIT_IN_CCHI will only allow in CCH Interval; - * VSA_TRANSMIT_IN_SCHI will only allow in SCH Interval; - * VSA_TRANSMIT_IN_BOTHI will allow anytime. - */ -enum VsaTransmitInterval -{ - VSA_TRANSMIT_IN_CCHI = 1, - VSA_TRANSMIT_IN_SCHI = 2, - VSA_TRANSMIT_IN_BOTHI = 3, -}; - -/** - * \ingroup wave - * - * \param peer The address of the peer MAC entity to which the - * VSA is sent. - * \param oi Identifies the source of the data when the source - * is not an IEEE 1609 entity. See IEEE Std 802.11p. - * \param managementId Identifies the source of the data when the source - * is an IEEE 1609 entity. Values are specified in IEEE P1609.0. - * Valid range: 0-15 - * \param vsc pointer to Information that will be sent as vendor specific content. - * \param channelNumber The channel on which the transmissions are to occur. - * While section 7.2 of the standard specifies that channel identification - * comprises Country String, Operating Class, and Channel Number, the channel - * number is enough for simulation. - * \param repeatRate The number of Vendor Specific Action frames to - * be transmitted per 5 s. A value of 0 indicates a single message is to be sent. - * If Destination MAC Address is an individual address, Repeat Rate is ignored. - * \param sendInterval The channel interval in which the transmissions - * are to occur. - */ -struct VsaInfo -{ - Mac48Address peer; ///< peer - OrganizationIdentifier oi; ///< OI - uint8_t managementId; ///< management ID - Ptr vsc; ///< VSC - uint32_t channelNumber; ///< channel number - uint8_t repeatRate; ///< repeat rate - VsaTransmitInterval sendInterval; ///< send interval - - /** - * Initializer - * \param peer the peer MAC address - * \param identifier the organization identifier - * \param manageId the manage ID - * \param vscPacket the VSC packet - * \param channel the channel - * \param repeat the repeat value - * \param interval the transmit interval - */ - VsaInfo(Mac48Address peer, - OrganizationIdentifier identifier, - uint8_t manageId, - Ptr vscPacket, - uint32_t channel, - uint8_t repeat, - VsaTransmitInterval interval) - : peer(peer), - oi(identifier), - managementId(manageId), - vsc(vscPacket), - channelNumber(channel), - repeatRate(repeat), - sendInterval(interval) - { - } -}; - -/** - * \ingroup wave - * - * refer to 1609.4-2010 chapter 6.4 - * Vendor Specific Action (VSA) frames transmission. - * - * The channel interval and channel number indicating how to transmit VSA frames. - * However making the VSA transmitted strictly in required channel interval and channel number - * is hard to achieve. For example, if current channel is assigned “Alternating Access” and higher - * layer wants VSA transmitted only in CCHI (VSA_TRANSMIT_IN_CCHI), but when packet is dequeued from - * the internal queue of MAC layer in SCHI and can contend for channel access, how to deal with - * this case? Reinserting into the head of the queue and dequeuing the second packet is not a good - * choice, because it will require queue traversal. Reinserting the packet into the tail of the - * queue is worse, because it will make queue not in order. And both solutions may affect many MAC - * classes of Wifi module. Current approach is to guarantee packets can be inserted into the MAC - * internal queue strictly in channel interval and channel number required by higher layers. This - * solution will result in high probability that packets will be sent in channel interval as higher - * layer wants, while some packet may be sent practically in other channel interval that not follows - * the requirement of higher layer request due to queue delay of MAC layer. Therefore, we suggest - * users assign alternating access for sending VSAs in CCH Interval (VSA_TRANSMIT_IN_CCHI) or SCH - * Interval (VSA_TRANSMIT_IN_SCHI), and assign continuous access or extended access for sending VSAs - * in both interval (VSA_TRANSMIT_IN_BOTHI) to avoid the above cases. - */ -class VsaManager : public Object -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - VsaManager(); - ~VsaManager() override; - - /** - * \param device WaveNetDevice associated with VsaManager - */ - void SetWaveNetDevice(Ptr device); - - /** - * Set wave vsa callback function - * \param vsaCallback the callback - */ - void SetWaveVsaCallback( - Callback, const Address&, uint32_t, uint32_t> vsaCallback); - - /** - * \param vsaInfo the tx information for VSA transmissions - */ - void SendVsa(const VsaInfo& vsaInfo); - /** - * cancel all VSA transmissions - */ - void RemoveAll(); - /** - * \param channelNumber cancel VSA transmission specified by channel number - */ - void RemoveByChannel(uint32_t channelNumber); - /** - * \param oi cancel VSA transmission specified by organization identifier - */ - void RemoveByOrganizationIdentifier(const OrganizationIdentifier& oi); - - private: - void DoDispose() override; - void DoInitialize() override; - - /** - * \param mac the MAC entity which receives VSA frame - * \param oi the Organization Identifier of received VSA frame - * \param vsc the vendor specific content of received VSA frame - * \param src the source address of received VSA frame - * \return true if successful - */ - bool ReceiveVsc(Ptr mac, - const OrganizationIdentifier& oi, - Ptr vsc, - const Address& src); - - /// A number of VSA frames will be transmitted repeatedly during the period of 5s. - const static uint32_t VSA_REPEAT_PERIOD = 5; - - /// VsaWork structure - struct VsaWork - { - Mac48Address peer; ///< peer - OrganizationIdentifier oi; ///< OI - Ptr vsc; ///< VSC - uint32_t channelNumber; ///< channel number - VsaTransmitInterval sentInterval; ///< VSA transmit interval - Time repeatPeriod; ///< repeat period - EventId repeat; ///< repeat ID - }; - - /** - * \param vsa the specific VSA repeat work - * - * Repeat to send VSA frames - */ - void DoRepeat(VsaWork* vsa); - /** - * \param interval the specific channel interval for VSA transmission - * \param channel the specific channel number for VSA transmission - * \param vsc the data field of VSA frame that contains vendor specific content - * \param oi the Organization Identifier for VSA frame - * \param peer the destination address - */ - void DoSendVsa(VsaTransmitInterval interval, - uint32_t channel, - Ptr vsc, - OrganizationIdentifier oi, - Mac48Address peer); - - Callback, const Address&, uint32_t, uint32_t> - m_vsaReceived; ///< VSA received callback - std::vector m_vsas; ///< VSAs - Ptr m_device; ///< the device -}; - -} // namespace ns3 -#endif /* VSA_MANAGER_H */ diff --git a/src/wave/model/wave-frame-exchange-manager.cc b/src/wave/model/wave-frame-exchange-manager.cc deleted file mode 100644 index 11b586876..000000000 --- a/src/wave/model/wave-frame-exchange-manager.cc +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Stefano Avallone - */ - -#include "wave-frame-exchange-manager.h" - -#include "higher-tx-tag.h" - -#include "ns3/abort.h" -#include "ns3/log.h" -#include "ns3/wifi-acknowledgment.h" -#include "ns3/wifi-protection.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("WaveFrameExchangeManager"); - -NS_OBJECT_ENSURE_REGISTERED(WaveFrameExchangeManager); - -TypeId -WaveFrameExchangeManager::GetTypeId() -{ - static TypeId tid = TypeId("ns3::WaveFrameExchangeManager") - .SetParent() - .AddConstructor() - .SetGroupName("Wave"); - return tid; -} - -WaveFrameExchangeManager::WaveFrameExchangeManager() -{ - NS_LOG_FUNCTION(this); -} - -WaveFrameExchangeManager::~WaveFrameExchangeManager() -{ - NS_LOG_FUNCTION_NOARGS(); -} - -void -WaveFrameExchangeManager::SetWaveNetDevice(Ptr device) -{ - m_scheduler = device->GetChannelScheduler(); - m_coordinator = device->GetChannelCoordinator(); - NS_ASSERT(m_scheduler && m_coordinator); -} - -WifiTxVector -WaveFrameExchangeManager::GetDataTxVector(Ptr item) const -{ - NS_LOG_FUNCTION(this << *item); - HigherLayerTxVectorTag datatag; - bool found; - found = ConstCast(item->GetPacket())->PeekPacketTag(datatag); - // if high layer has not controlled transmit parameters, the real transmit parameters - // will be determined by MAC layer itself. - if (!found) - { - return m_mac->GetWifiRemoteStationManager()->GetDataTxVector(item->GetHeader(), - m_allowedWidth); - } - - // if high layer has set the transmit parameters with non-adaption mode, - // the real transmit parameters are determined by high layer. - if (!datatag.IsAdaptable()) - { - return datatag.GetTxVector(); - } - - // if high layer has set the transmit parameters with non-adaption mode, - // the real transmit parameters are determined by both high layer and MAC layer. - WifiTxVector txHigher = datatag.GetTxVector(); - WifiTxVector txMac = - m_mac->GetWifiRemoteStationManager()->GetDataTxVector(item->GetHeader(), m_allowedWidth); - WifiTxVector txAdapter; - txAdapter.SetChannelWidth(10); - // the DataRate set by higher layer is the minimum data rate - // which is the lower bound for the actual data rate. - if (txHigher.GetMode().GetDataRate(txHigher.GetChannelWidth()) > - txMac.GetMode().GetDataRate(txMac.GetChannelWidth())) - { - txAdapter.SetMode(txHigher.GetMode()); - txAdapter.SetPreambleType(txHigher.GetPreambleType()); - } - else - { - txAdapter.SetMode(txMac.GetMode()); - txAdapter.SetPreambleType(txMac.GetPreambleType()); - } - // the TxPwr_Level set by higher layer is the maximum transmit - // power which is the upper bound for the actual transmit power; - txAdapter.SetTxPowerLevel(std::min(txHigher.GetTxPowerLevel(), txMac.GetTxPowerLevel())); - - return txAdapter; -} - -bool -WaveFrameExchangeManager::StartTransmission(Ptr dcf, uint16_t allowedWidth) -{ - NS_LOG_FUNCTION(this << dcf << allowedWidth); - - uint32_t curChannel = m_phy->GetChannelNumber(); - // if current channel access is not AlternatingAccess, just do as FrameExchangeManager. - if (!m_scheduler || !m_scheduler->IsAlternatingAccessAssigned(curChannel)) - { - return FrameExchangeManager::StartTransmission(dcf, allowedWidth); - } - - m_txTimer.Cancel(); - m_dcf = dcf; - m_allowedWidth = allowedWidth; - - Ptr queue = dcf->GetWifiMacQueue(); - - if (queue->IsEmpty()) - { - NS_LOG_DEBUG("Queue empty"); - m_dcf->NotifyChannelReleased(0); - m_dcf = nullptr; - return false; - } - - m_dcf->NotifyChannelAccessed(0); - Ptr mpdu = queue->PeekFirstAvailable(0); - NS_ASSERT(mpdu); - - // assign a sequence number if this is not a fragment nor a retransmission - if (!mpdu->IsFragment() && !mpdu->GetHeader().IsRetry()) - { - uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor(&mpdu->GetHeader()); - mpdu->GetHeader().SetSequenceNumber(sequence); - } - - WifiTxParameters txParams; - txParams.m_txVector = GetDataTxVector(mpdu); - Time remainingTime = m_coordinator->NeedTimeToGuardInterval(); - - if (!TryAddMpdu(mpdu, txParams, remainingTime)) - { - // The attempt for this transmission will be canceled; - // and this packet will be pending for next transmission by QosTxop class - NS_LOG_DEBUG("Because the required transmission time exceeds the remainingTime = " - << remainingTime.As(Time::MS) - << ", currently this packet will not be transmitted."); - } - else - { - SendMpduWithProtection(mpdu, txParams); - return true; - } - return false; -} - -void -WaveFrameExchangeManager::DoDispose() -{ - NS_LOG_FUNCTION(this); - m_scheduler = nullptr; - m_coordinator = nullptr; - FrameExchangeManager::DoDispose(); -} - -} // namespace ns3 diff --git a/src/wave/model/wave-frame-exchange-manager.h b/src/wave/model/wave-frame-exchange-manager.h deleted file mode 100644 index dd4abcf59..000000000 --- a/src/wave/model/wave-frame-exchange-manager.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Junling Bu - * Stefano Avallone - */ - -#ifndef WAVE_FRAME_EXCHANGE_MANAGER_H -#define WAVE_FRAME_EXCHANGE_MANAGER_H - -#include "wave-net-device.h" - -#include "ns3/qos-frame-exchange-manager.h" - -namespace ns3 -{ - -/** - * \ingroup wave - * - * This class is the subclass of QosFrameExchangeManager to provide support for MAC extension - * (1) allows higher layer control data rate and tx power level. - * If higher layer does not set, they will be determined by WifiRemoteStationManager - * of MAC layer; - * If higher layer sets tx parameters in non-adaptable mode, the data rate - * and tx power level will be used for transmission;. - * If higher layer sets tx parameters in adaptable mode, the data rate - * will be lower bound for the actual data rate, and the power level - * will be upper bound for the actual transmit power. - * (2) implements the feature described in Annex C : avoid transmission at scheduled guard intervals - * However, the feature is extended further here that the required transmit time is determined - * by MAC layer itself rather than PHY layer, which contains RTS/CTS, DATA and ACK time. - */ -class WaveFrameExchangeManager : public QosFrameExchangeManager -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - WaveFrameExchangeManager(); - ~WaveFrameExchangeManager() override; - - // Overridden from FrameExchangeManager - bool StartTransmission(Ptr dcf, uint16_t allowedWidth) override; - - /** - * \param device WaveNetDevice associated with WaveFrameExchangeManager - */ - void SetWaveNetDevice(Ptr device); - - protected: - // Overridden from FrameExchangeManager - void DoDispose() override; - - private: - /** - * Return a TXVECTOR for the DATA frame given the destination. - * The function consults WifiRemoteStationManager, which controls the rate - * to different destinations. - * - * \param item the item being asked for TXVECTOR - * \return TXVECTOR for the given item - */ - virtual WifiTxVector GetDataTxVector(Ptr item) const; - - Ptr m_scheduler; ///< the channel scheduler - Ptr m_coordinator; ///< the channel coordinator -}; - -} // namespace ns3 - -#endif /* VHT_FRAME_EXCHANGE_MANAGER_H */ diff --git a/src/wave/model/wave-net-device.cc b/src/wave/model/wave-net-device.cc deleted file mode 100644 index 413ec165e..000000000 --- a/src/wave/model/wave-net-device.cc +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Copyright (c) 2005,2006 INRIA - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Junling Bu - */ -#include "wave-net-device.h" - -#include "higher-tx-tag.h" - -#include "ns3/channel.h" -#include "ns3/llc-snap-header.h" -#include "ns3/log.h" -#include "ns3/node.h" -#include "ns3/object-map.h" -#include "ns3/object-vector.h" -#include "ns3/socket.h" -#include "ns3/wifi-phy.h" - -#include - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("WaveNetDevice"); - -NS_OBJECT_ENSURE_REGISTERED(WaveNetDevice); - -TypeId -WaveNetDevice::GetTypeId() -{ - static TypeId tid = - TypeId("ns3::WaveNetDevice") - .SetParent() - .SetGroupName("Wave") - .AddConstructor() - .AddAttribute("Mtu", - "The MAC-level Maximum Transmission Unit", - UintegerValue(MAX_MSDU_SIZE - LLC_SNAP_HEADER_LENGTH), - MakeUintegerAccessor(&WaveNetDevice::SetMtu, &WaveNetDevice::GetMtu), - MakeUintegerChecker(1, MAX_MSDU_SIZE - LLC_SNAP_HEADER_LENGTH)) - .AddAttribute("Channel", - "The channel attached to this device", - PointerValue(), - MakePointerAccessor(&WaveNetDevice::GetChannel), - MakePointerChecker()) - .AddAttribute("PhyEntities", - "The PHY entities attached to this device.", - ObjectVectorValue(), - MakeObjectVectorAccessor(&WaveNetDevice::m_phyEntities), - MakeObjectVectorChecker()) - .AddAttribute("MacEntities", - "The MAC layer attached to this device.", - ObjectMapValue(), - MakeObjectMapAccessor(&WaveNetDevice::m_macEntities), - MakeObjectMapChecker()) - .AddAttribute("ChannelScheduler", - "The channel scheduler attached to this device.", - PointerValue(), - MakePointerAccessor(&WaveNetDevice::SetChannelScheduler, - &WaveNetDevice::GetChannelScheduler), - MakePointerChecker()) - .AddAttribute("ChannelManager", - "The channel manager attached to this device.", - PointerValue(), - MakePointerAccessor(&WaveNetDevice::SetChannelManager, - &WaveNetDevice::GetChannelManager), - MakePointerChecker()) - .AddAttribute("ChannelCoordinator", - "The channel coordinator attached to this device.", - PointerValue(), - MakePointerAccessor(&WaveNetDevice::SetChannelCoordinator, - &WaveNetDevice::GetChannelCoordinator), - MakePointerChecker()) - .AddAttribute( - "VsaManager", - "The VSA manager attached to this device.", - PointerValue(), - MakePointerAccessor(&WaveNetDevice::SetVsaManager, &WaveNetDevice::GetVsaManager), - MakePointerChecker()); - return tid; -} - -WaveNetDevice::WaveNetDevice() - : m_txProfile(nullptr) -{ - NS_LOG_FUNCTION(this); -} - -WaveNetDevice::~WaveNetDevice() -{ - NS_LOG_FUNCTION(this); -} - -void -WaveNetDevice::DoDispose() -{ - NS_LOG_FUNCTION(this); - if (m_txProfile != nullptr) - { - delete m_txProfile; - m_txProfile = nullptr; - } - for (PhyEntitiesI i = m_phyEntities.begin(); i != m_phyEntities.end(); ++i) - { - Ptr phy = (*i); - phy->Dispose(); - } - m_phyEntities.clear(); - for (MacEntitiesI i = m_macEntities.begin(); i != m_macEntities.end(); ++i) - { - Ptr mac = i->second; - Ptr stationManager = mac->GetWifiRemoteStationManager(); - stationManager->Dispose(); - mac->Dispose(); - } - m_macEntities.clear(); - m_phyEntities.clear(); - m_channelCoordinator->Dispose(); - m_channelManager->Dispose(); - m_channelScheduler->Dispose(); - m_vsaManager->Dispose(); - m_channelCoordinator = nullptr; - m_channelManager = nullptr; - m_channelScheduler = nullptr; - m_vsaManager = nullptr; - // chain up. - WifiNetDevice::DoDispose(); -} - -void -WaveNetDevice::DoInitialize() -{ - NS_LOG_FUNCTION(this); - if (m_phyEntities.empty()) - { - NS_FATAL_ERROR("there is no PHY entity in this WAVE device"); - } - for (PhyEntitiesI i = m_phyEntities.begin(); i != m_phyEntities.end(); ++i) - { - Ptr phy = (*i); - phy->Initialize(); - } - if (m_macEntities.empty()) - { - NS_FATAL_ERROR("there is no MAC entity in this WAVE device"); - } - for (MacEntitiesI i = m_macEntities.begin(); i != m_macEntities.end(); ++i) - { - Ptr mac = i->second; - mac->SetForwardUpCallback(MakeCallback(&WaveNetDevice::ForwardUp, this)); - // Make each MAC entity in sleep mode. - mac->Suspend(); - mac->Initialize(); - - Ptr stationManager = mac->GetWifiRemoteStationManager(); - // Currently PHY is not attached to MAC and will be dynamically attached and unattached to - // MAC latter, however WifiRemoteStationManager in the MAC shall know something in the PHY - // such as supported data rates. Since these information can be treated as same when same - // PHY devices are added, here we force all of WifiRemoteStationManagers in multiple MAC - // entities only associate with single PHY device even there may be multiple PHY entities. - // This approach may be strange but can work fine. - stationManager->SetupPhy(m_phyEntities[0]); - stationManager->Initialize(); - } - m_channelScheduler->SetWaveNetDevice(this); - m_vsaManager->SetWaveNetDevice(this); - m_channelScheduler->Initialize(); - m_channelCoordinator->Initialize(); - m_channelManager->Initialize(); - m_vsaManager->Initialize(); - NetDevice::DoInitialize(); -} - -void -WaveNetDevice::AddMac(uint32_t channelNumber, Ptr mac) -{ - NS_LOG_FUNCTION(this << channelNumber << mac); - if (!ChannelManager::IsWaveChannel(channelNumber)) - { - NS_FATAL_ERROR("The channel " << channelNumber << " is not a valid WAVE channel number"); - } - if (m_macEntities.find(channelNumber) != m_macEntities.end()) - { - NS_FATAL_ERROR("The MAC entity for channel " << channelNumber << " already exists."); - } - m_macEntities.insert(std::make_pair(channelNumber, mac)); -} - -Ptr -WaveNetDevice::GetMac(uint32_t channelNumber) const -{ - NS_LOG_FUNCTION(this << channelNumber); - MacEntitiesI i = m_macEntities.find(channelNumber); - if (i == m_macEntities.end()) - { - NS_FATAL_ERROR("there is no available MAC entity for channel " << channelNumber); - } - return i->second; -} - -std::map> -WaveNetDevice::GetMacs() const -{ - NS_LOG_FUNCTION(this); - return m_macEntities; -} - -void -WaveNetDevice::AddPhy(Ptr phy) -{ - NS_LOG_FUNCTION(this << phy); - if (std::find(m_phyEntities.begin(), m_phyEntities.end(), phy) != m_phyEntities.end()) - { - NS_FATAL_ERROR("This PHY entity is already inserted"); - } - m_phyEntities.push_back(phy); -} - -Ptr -WaveNetDevice::GetPhy(uint8_t index) const -{ - NS_LOG_FUNCTION(this << +index); - return m_phyEntities.at(index); -} - -const std::vector>& -WaveNetDevice::GetPhys() const -{ - NS_LOG_FUNCTION(this); - return m_phyEntities; -} - -bool -WaveNetDevice::StartVsa(const VsaInfo& vsaInfo) -{ - NS_LOG_FUNCTION(this << &vsaInfo); - if (!IsAvailableChannel(vsaInfo.channelNumber)) - { - return false; - } - if (!m_channelScheduler->IsChannelAccessAssigned(vsaInfo.channelNumber)) - { - NS_LOG_DEBUG("there is no channel access assigned for channel " << vsaInfo.channelNumber); - return false; - } - if (!vsaInfo.vsc) - { - NS_LOG_DEBUG("vendor specific information shall not be null"); - return false; - } - if (vsaInfo.oi.IsNull() && vsaInfo.managementId >= 16) - { - NS_LOG_DEBUG("when organization identifier is not set, management ID " - "shall be in range from 0 to 15"); - return false; - } - - m_vsaManager->SendVsa(vsaInfo); - return true; -} - -bool -WaveNetDevice::StopVsa(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - if (!IsAvailableChannel(channelNumber)) - { - return false; - } - m_vsaManager->RemoveByChannel(channelNumber); - return true; -} - -void -WaveNetDevice::SetWaveVsaCallback(WaveVsaCallback vsaCallback) -{ - NS_LOG_FUNCTION(this); - m_vsaManager->SetWaveVsaCallback(vsaCallback); -} - -bool -WaveNetDevice::StartSch(const SchInfo& schInfo) -{ - NS_LOG_FUNCTION(this << &schInfo); - if (!IsAvailableChannel(schInfo.channelNumber)) - { - return false; - } - return m_channelScheduler->StartSch(schInfo); -} - -bool -WaveNetDevice::StopSch(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - if (!IsAvailableChannel(channelNumber)) - { - return false; - } - return m_channelScheduler->StopSch(channelNumber); -} - -bool -WaveNetDevice::RegisterTxProfile(const TxProfile& txprofile) -{ - NS_LOG_FUNCTION(this << &txprofile); - if (m_txProfile != nullptr) - { - return false; - } - if (!IsAvailableChannel(txprofile.channelNumber)) - { - return false; - } - if (txprofile.txPowerLevel > 8) - { - return false; - } - // IP-based packets is not allowed to send in the CCH. - if (txprofile.channelNumber == CCH) - { - NS_LOG_DEBUG("IP-based packets shall not be transmitted on the CCH"); - return false; - } - if (txprofile.dataRate == WifiMode() || txprofile.txPowerLevel == 8) - { - // let MAC layer itself determine tx parameters. - NS_LOG_DEBUG("High layer does not want to control tx parameters."); - } - else - { - // if current PHY devices do not support data rate of the tx profile - for (PhyEntitiesI i = m_phyEntities.begin(); i != m_phyEntities.end(); ++i) - { - if (!((*i)->IsModeSupported(txprofile.dataRate))) - { - NS_LOG_DEBUG("This data rate " << txprofile.dataRate.GetUniqueName() - << " is not supported by current PHY device"); - return false; - } - } - } - - m_txProfile = new TxProfile(); - *m_txProfile = txprofile; - return true; -} - -bool -WaveNetDevice::DeleteTxProfile(uint32_t channelNumber) -{ - NS_LOG_FUNCTION(this << channelNumber); - if (!IsAvailableChannel(channelNumber)) - { - return false; - } - if (m_txProfile == nullptr) - { - return false; - } - if (m_txProfile->channelNumber != channelNumber) - { - return false; - } - - delete m_txProfile; - m_txProfile = nullptr; - return true; -} - -bool -WaveNetDevice::SendX(Ptr packet, - const Address& dest, - uint32_t protocol, - const TxInfo& txInfo) -{ - NS_LOG_FUNCTION(this << packet << dest << protocol << &txInfo); - if (!IsAvailableChannel(txInfo.channelNumber)) - { - return false; - } - if (!m_channelScheduler->IsChannelAccessAssigned(txInfo.channelNumber)) - { - NS_LOG_DEBUG("there is no channel access assigned for channel " << txInfo.channelNumber); - return false; - } - if ((txInfo.channelNumber == CCH) && - (protocol == IPv4_PROT_NUMBER || protocol == IPv6_PROT_NUMBER)) - { - NS_LOG_DEBUG("IP-based packets shall not be transmitted on the CCH"); - return false; - } - if ((txInfo.priority > 7) || txInfo.txPowerLevel > 8) - { - NS_LOG_DEBUG("invalid transmit parameters."); - return false; - } - - if ((txInfo.dataRate == WifiMode()) || (txInfo.txPowerLevel == 8)) - { - // let MAC layer itself determine tx parameters. - NS_LOG_DEBUG("High layer does not want to control tx parameters."); - } - else - { - // if current PHY devices do not support data rate of the tx profile - for (PhyEntitiesI i = m_phyEntities.begin(); i != m_phyEntities.end(); ++i) - { - if (!((*i)->IsModeSupported(txInfo.dataRate))) - { - return false; - } - } - WifiTxVector txVector; - txVector.SetChannelWidth(10); - txVector.SetTxPowerLevel(txInfo.txPowerLevel); - txVector.SetMode(txInfo.dataRate); - txVector.SetPreambleType(txInfo.preamble); - HigherLayerTxVectorTag tag = HigherLayerTxVectorTag(txVector, false); - packet->AddPacketTag(tag); - } - - LlcSnapHeader llc; - llc.SetType(protocol); - packet->AddHeader(llc); - - // according to channel number and priority, - // route the packet to a proper queue. - SocketPriorityTag prio; - prio.SetPriority(txInfo.priority); - packet->ReplacePacketTag(prio); - Ptr mac = GetMac(txInfo.channelNumber); - Mac48Address realTo = Mac48Address::ConvertFrom(dest); - mac->NotifyTx(packet); - mac->Enqueue(packet, realTo); - return true; -} - -void -WaveNetDevice::ChangeAddress(Address newAddress) -{ - NS_LOG_FUNCTION(this << newAddress); - Address oldAddress = GetAddress(); - if (newAddress == oldAddress) - { - return; - } - SetAddress(newAddress); - // Since MAC address is changed, the MAC layer including multiple MAC entities should be reset - // and internal MAC queues will be flushed. - for (MacEntitiesI i = m_macEntities.begin(); i != m_macEntities.end(); ++i) - { - i->second->Reset(); - } - m_addressChange(oldAddress, newAddress); -} - -void -WaveNetDevice::CancelTx(uint32_t channelNumber, AcIndex ac) -{ - if (IsAvailableChannel(channelNumber)) - { - return; - } - Ptr mac = GetMac(channelNumber); - mac->CancelTx(ac); -} - -void -WaveNetDevice::SetChannelManager(Ptr channelManager) -{ - m_channelManager = channelManager; -} - -Ptr -WaveNetDevice::GetChannelManager() const -{ - return m_channelManager; -} - -void -WaveNetDevice::SetChannelScheduler(Ptr channelScheduler) -{ - m_channelScheduler = channelScheduler; -} - -Ptr -WaveNetDevice::GetChannelScheduler() const -{ - return m_channelScheduler; -} - -void -WaveNetDevice::SetChannelCoordinator(Ptr channelCoordinator) -{ - m_channelCoordinator = channelCoordinator; -} - -Ptr -WaveNetDevice::GetChannelCoordinator() const -{ - return m_channelCoordinator; -} - -void -WaveNetDevice::SetVsaManager(Ptr vsaManager) -{ - m_vsaManager = vsaManager; -} - -Ptr -WaveNetDevice::GetVsaManager() const -{ - return m_vsaManager; -} - -void -WaveNetDevice::SetIfIndex(const uint32_t index) -{ - m_ifIndex = index; -} - -uint32_t -WaveNetDevice::GetIfIndex() const -{ - return m_ifIndex; -} - -Ptr -WaveNetDevice::GetChannel() const -{ - NS_ASSERT(!m_phyEntities.empty()); - return GetPhy(0)->GetChannel(); -} - -void -WaveNetDevice::SetAddress(Address address) -{ - for (MacEntitiesI i = m_macEntities.begin(); i != m_macEntities.end(); ++i) - { - i->second->SetAddress(Mac48Address::ConvertFrom(address)); - } -} - -Address -WaveNetDevice::GetAddress() const -{ - return (GetMac(CCH))->GetAddress(); -} - -bool -WaveNetDevice::SetMtu(const uint16_t mtu) -{ - if (mtu > MAX_MSDU_SIZE - LLC_SNAP_HEADER_LENGTH) - { - return false; - } - m_mtu = mtu; - return true; -} - -uint16_t -WaveNetDevice::GetMtu() const -{ - return m_mtu; -} - -bool -WaveNetDevice::IsLinkUp() const -{ - // Different from WifiNetDevice::IsLinkUp, a WaveNetDevice device - // is always link up so the m_linkup variable is true forever. - // Even the device is in channel switch state, packets can still be queued. - return true; -} - -void -WaveNetDevice::AddLinkChangeCallback(Callback callback) -{ - NS_LOG_WARN("WaveNetDevice is linkup forever, so this callback will be never called"); -} - -bool -WaveNetDevice::IsBroadcast() const -{ - return true; -} - -Address -WaveNetDevice::GetBroadcast() const -{ - return Mac48Address::GetBroadcast(); -} - -bool -WaveNetDevice::IsMulticast() const -{ - return true; -} - -Address -WaveNetDevice::GetMulticast(Ipv4Address multicastGroup) const -{ - return Mac48Address::GetMulticast(multicastGroup); -} - -Address -WaveNetDevice::GetMulticast(Ipv6Address addr) const -{ - return Mac48Address::GetMulticast(addr); -} - -bool -WaveNetDevice::IsPointToPoint() const -{ - return false; -} - -bool -WaveNetDevice::IsBridge() const -{ - return false; -} - -bool -WaveNetDevice::Send(Ptr packet, const Address& dest, uint16_t protocol) -{ - NS_LOG_FUNCTION(this << packet << dest << protocol); - if (m_txProfile == nullptr) - { - NS_LOG_DEBUG("there is no tx profile registered for transmission"); - return false; - } - if (!m_channelScheduler->IsChannelAccessAssigned(m_txProfile->channelNumber)) - { - NS_LOG_DEBUG("there is no channel access assigned for channel " - << m_txProfile->channelNumber); - return false; - } - if (m_txProfile->dataRate == WifiMode() || m_txProfile->txPowerLevel == 8) - { - // let MAC layer itself determine tx parameters. - NS_LOG_DEBUG("High layer does not want to control tx parameters."); - } - else - { - WifiTxVector txVector; - txVector.SetTxPowerLevel(m_txProfile->txPowerLevel); - txVector.SetMode(m_txProfile->dataRate); - txVector.SetPreambleType(m_txProfile->preamble); - HigherLayerTxVectorTag tag = HigherLayerTxVectorTag(txVector, m_txProfile->adaptable); - packet->AddPacketTag(tag); - } - - LlcSnapHeader llc; - llc.SetType(protocol); - packet->AddHeader(llc); - - // qos tag is already inserted into the packet by high layer or with default value 7 if high - // layer forget it. - Ptr mac = GetMac(m_txProfile->channelNumber); - Mac48Address realTo = Mac48Address::ConvertFrom(dest); - mac->NotifyTx(packet); - mac->Enqueue(packet, realTo); - return true; -} - -bool -WaveNetDevice::NeedsArp() const -{ - // Whether NeedsArp or not? - // For IP-based packets , yes; For WSMP packets, no; - // so return true always. - return true; -} - -void -WaveNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb) -{ - m_forwardUp = cb; -} - -bool -WaveNetDevice::IsAvailableChannel(uint32_t channelNumber) const -{ - if (!ChannelManager::IsWaveChannel(channelNumber)) - { - NS_LOG_DEBUG("this is no a valid WAVE channel for channel " << channelNumber); - return false; - } - if (m_macEntities.find(channelNumber) == m_macEntities.end()) - { - NS_LOG_DEBUG("this is no available WAVE entity for channel " << channelNumber); - return false; - } - return true; -} - -void -WaveNetDevice::ForwardUp(Ptr packet, Mac48Address from, Mac48Address to) -{ - NS_LOG_FUNCTION(this << packet << from << to); - Ptr copy = packet->Copy(); - LlcSnapHeader llc; - copy->RemoveHeader(llc); - NetDevice::PacketType type; - if (to.IsBroadcast()) - { - type = NetDevice::PACKET_BROADCAST; - } - else if (to.IsGroup()) - { - type = NetDevice::PACKET_MULTICAST; - } - else if (to == GetAddress()) - { - type = NetDevice::PACKET_HOST; - } - else - { - type = NetDevice::PACKET_OTHERHOST; - } - - if (type != NetDevice::PACKET_OTHERHOST) - { - // currently we cannot know from which MAC entity the packet is received, - // so we use the MAC entity for CCH as it receives this packet. - Ptr mac = GetMac(CCH); - mac->NotifyRx(copy); - m_forwardUp(this, copy, llc.GetType(), from); - } - - if (!m_promiscRx.IsNull()) - { - // currently we cannot know from which MAC entity the packet is received, - // so we use the MAC entity for CCH as it receives this packet. - Ptr mac = GetMac(CCH); - mac->NotifyPromiscRx(copy); - m_promiscRx(this, copy, llc.GetType(), from, to, type); - } -} - -bool -WaveNetDevice::SendFrom(Ptr packet, - const Address& source, - const Address& dest, - uint16_t protocol) -{ - NS_LOG_FUNCTION(this << packet << source << dest << protocol); - return false; -} - -void -WaveNetDevice::SetPromiscReceiveCallback(PromiscReceiveCallback cb) -{ - m_promiscRx = cb; - for (MacEntitiesI i = m_macEntities.begin(); i != m_macEntities.end(); ++i) - { - i->second->SetPromisc(); - } -} - -bool -WaveNetDevice::SupportsSendFrom() const -{ - return (GetMac(CCH))->SupportsSendFrom(); -} - -} // namespace ns3 diff --git a/src/wave/model/wave-net-device.h b/src/wave/model/wave-net-device.h deleted file mode 100644 index 7b3586094..000000000 --- a/src/wave/model/wave-net-device.h +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (c) 2005,2006 INRIA - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - * Junling Bu - */ -#ifndef WAVE_NET_DEVICE_H -#define WAVE_NET_DEVICE_H - -#include "channel-coordinator.h" -#include "channel-manager.h" -#include "channel-scheduler.h" -#include "ocb-wifi-mac.h" -#include "vendor-specific-action.h" -#include "vsa-manager.h" - -#include "ns3/mac48-address.h" -#include "ns3/packet.h" -#include "ns3/traced-callback.h" -#include "ns3/wifi-net-device.h" - -#include -#include - -namespace ns3 -{ -struct SchInfo; -struct VsaInfo; -class NetDevice; -class ChannelScheduler; -class VsaManager; -class OcbWifiMac; - -/** - * \defgroup wave WAVE module - */ - -/** - * \ingroup wave - * - * \param channelNumber the specific channel - * \param priority the priority of packet with range 0-7 - * \param dataRate the transmit data rate of packet - * \param txPowerLevel the transmit power level with range 0-7 - * \param expireTime indicate how many milliseconds the packet - * can stay before sent - * - * typically these parameters are used by higher layer to control - * the transmission characteristics of WSMP packets. - * When dataRate is an invalid WifiMode and txPowerLevel is 8, this - * indicates that high layer does not set tx parameters. - */ -struct TxInfo -{ - uint32_t channelNumber; ///< channel number - uint32_t priority; ///< priority - WifiMode dataRate; ///< data rate - WifiPreamble preamble; ///< preamble - uint32_t txPowerLevel; ///< transmit power level - - // Time expiryTime; // unsupported - /// Initializer - TxInfo() - : channelNumber(CCH), - priority(7), - txPowerLevel(8) - { - } - - /** - * Initializer - * \param channel the channel - * \param prio the priority - * \param rate the wifi mode - * \param preamble the preamble - * \param powerLevel the power level - */ - TxInfo(uint32_t channel, - uint32_t prio = 7, - WifiMode rate = WifiMode(), - WifiPreamble preamble = WIFI_PREAMBLE_LONG, - uint32_t powerLevel = 8) - : channelNumber(channel), - priority(prio), - dataRate(rate), - preamble(preamble), - txPowerLevel(powerLevel) - { - } -}; - -/** - * \ingroup wave - * - * \param channelNumber the channel number for the SCH. - * \param adaptable if true, the actual power level and data - * rate for transmission are adaptable. TxPwr_Level is the maximum - * transmit power that sets the upper bound for the actual transmit - * power; DataRate is the minimum data rate that sets the lower - * bound for the actual data rate. If false, the actual power level - * and data rate for transmission are non-adaptable. TxPwr_Level and - * DataRate are the actual values to be used for transmission. - * \param txPowerLevel transmit power level. - * \param dataRate transmit data rate - */ -struct TxProfile -{ - uint32_t channelNumber; ///< channel number - bool adaptable; ///< adaptable - uint32_t txPowerLevel; ///< transmit power level - WifiMode dataRate; ///< data rate - WifiPreamble preamble; ///< preamble - - /// Initializer - TxProfile() - : channelNumber(SCH1), - adaptable(false), - txPowerLevel(4), - preamble(WIFI_PREAMBLE_LONG) - { - dataRate = WifiMode("OfdmRate6MbpsBW10MHz"); - } - - /** - * Initializer - * \param channel the channel number - * \param adapt true to adapt - * \param powerLevel the power level - */ - TxProfile(uint32_t channel, bool adapt = true, uint32_t powerLevel = 4) - : channelNumber(channel), - adaptable(adapt), - txPowerLevel(powerLevel) - { - dataRate = WifiMode("OfdmRate6MbpsBW10MHz"); - preamble = WIFI_PREAMBLE_LONG; - } -}; - -/** - * \ingroup wave - * - * This class holds together multiple, ns3::WifiPhy, - * and ns3::OcbWifiMac (including ns3::WifiRemoteStationManager). - * Besides that, to support multiple channel operation this - * class also holds ns3::ChannelScheduler, ns3::ChannelManager, - * ns3::ChannelCoordinator and ns3::VsaManager. - * - * these primitives specified in the standard will not be implemented - * because of limited use in simulation: - * void StartTimingAdvertisement (); - * void StopTimingAdvertisement (); - * UtcTime GetUtcTime (); - * void SetUtcTime (); - */ -class WaveNetDevice : public WifiNetDevice -{ - public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId(); - WaveNetDevice(); - ~WaveNetDevice() override; - - /** - * \param channelNumber the specific channel - * \param mac add a new available MAC entity for specific channel - */ - void AddMac(uint32_t channelNumber, Ptr mac); - /** - * \param channelNumber the specific channel number - * \return corresponding MAC entity - */ - Ptr GetMac(uint32_t channelNumber) const; - /** - * \return all inserted MAC entities. - */ - std::map> GetMacs() const; - /** - * \param phy add a new available PHY entity - */ - void AddPhy(Ptr phy); - /** - * \param index the index of PHY entity - * \return corresponding PHY entity - */ - Ptr GetPhy(uint8_t index) const override; - /** - * \return all inserted PHY entities. - */ - const std::vector>& GetPhys() const override; - - /** - * \param channelScheduler the channel scheduler for multiple channel operation - */ - void SetChannelScheduler(Ptr channelScheduler); - /** - * \return current channel scheduler for multiple channel operation - */ - Ptr GetChannelScheduler() const; - /** - * \param channelManager the channel manager for multiple channel operation - */ - void SetChannelManager(Ptr channelManager); - /** - * \return currentc channel manager for multiple channel operation - */ - Ptr GetChannelManager() const; - /** - * \param channelCoordinator the channel coordinator for multiple channel operation - */ - void SetChannelCoordinator(Ptr channelCoordinator); - /** - * \return current channel coordinator for multiple channel operation - */ - Ptr GetChannelCoordinator() const; - /** - * \param vsaManager the VSA manager for multiple channel operation - */ - void SetVsaManager(Ptr vsaManager); - /** - * \return current VSA manager for multiple channel operation - */ - Ptr GetVsaManager() const; - - /** - * \param schInfo the parameters about how to start SCH service - * \return whether channel access is assigned successfully - */ - bool StartSch(const SchInfo& schInfo); - /** - * \param channelNumber the channel which access resource will be released. - * \return whether channel access is released successfully - */ - bool StopSch(uint32_t channelNumber); - - /** - * \param vsaInfo the parameters about how to send VSA frame - * \return whether the request for VSA transmission is completed - */ - bool StartVsa(const VsaInfo& vsaInfo); - /** - * \param channelNumber the channel on which VSA transmit event will be canceled. - * \return whether the request for stopping VSA transmission is completed - */ - bool StopVsa(uint32_t channelNumber); - /** - * \param packet the packet is Vendor Specific Action frame. - * \param address the address of the MAC from which the management frame - * was received. - * \param managementID identify the originator of the data. - * Values are specified in IEEE P1609.0 with range 0-15. - * \param channelNumber the channel on which the frame was received. - * \returns true if the callback could handle the packet successfully, false - * otherwise. - */ - typedef Callback, const Address&, uint32_t, uint32_t> WaveVsaCallback; - /** - * \param vsaCallback the VSA receive callback for 1609 management information - */ - void SetWaveVsaCallback(WaveVsaCallback vsaCallback); - - /** - * \param txprofile transmit profile for IP-based data - * register a transmitter profile in the MLME before - * the associated IP-based data transfer starts. - * \return whether the tx profile is registered successfully - * - * note: This method should be called before WaveNetDevice::Send method - */ - bool RegisterTxProfile(const TxProfile& txprofile); - /** - * \param channelNumber the specific channel number - * delete a registered transmitter profile in the MLME - * after the associated IP-based data transfer is complete - * \return whether the tx profile is unregistered successfully - */ - bool DeleteTxProfile(uint32_t channelNumber); - - /** - * \param packet packet sent from above down to Network Device - * \param dest mac address of the destination (already resolved) - * \param protocol identifies the type of payload contained in the packet. - * Used to call the right L3Protocol when the packet is received. - * \param txInfo WSMP or other packets parameters for sending - * \return whether the SendX operation succeeded - * - * Normally this method is called by 1609.3 standard to - * send WSMP packets, however high layers can also send packets - * in other types except IP-based packets in CCH. - */ - bool SendX(Ptr packet, const Address& dest, uint32_t protocol, const TxInfo& txInfo); - /** - * \param newAddress an immediate MAC-layer address change is required - * - * This method is similar with SetAddress method, but - * SetAddress is suggested for initializing a device, while this method - * is preferred for changing address and a addressChange TracedCallback - * will be called. - */ - void ChangeAddress(Address newAddress); - /** - * \param channelNumber the specific channel number - * \param ac the specific access category - * - * Cancel all transmissions with the particular category and channel number. - */ - void CancelTx(uint32_t channelNumber, AcIndex ac); - - /** - * \param packet packet sent from above down to Network Device - * \param dest mac address of the destination (already resolved) - * \param protocolNumber identifies the type of payload contained in - * this packet. Used to call the right L3Protocol when the packet - * is received. - * \return whether the Send operation succeeded - * - * Normally this method is called by 1609.3 standard to - * send IP-based packets, however high layers can also send packets - * in other types except IP-based packets in CCH. - */ - bool Send(Ptr packet, const Address& dest, uint16_t protocolNumber) override; - - // inherited from NetDevice base class. - void SetIfIndex(const uint32_t index) override; - uint32_t GetIfIndex() const override; - Ptr GetChannel() const override; - void SetAddress(Address address) override; - Address GetAddress() const override; - bool SetMtu(const uint16_t mtu) override; - uint16_t GetMtu() const override; - bool IsLinkUp() const override; - void AddLinkChangeCallback(Callback callback) override; - bool IsBroadcast() const override; - Address GetBroadcast() const override; - bool IsMulticast() const override; - Address GetMulticast(Ipv4Address multicastGroup) const override; - bool IsPointToPoint() const override; - bool IsBridge() const override; - bool NeedsArp() const override; - void SetReceiveCallback(NetDevice::ReceiveCallback cb) override; - Address GetMulticast(Ipv6Address addr) const override; - bool SendFrom(Ptr packet, - const Address& source, - const Address& dest, - uint16_t protocolNumber) override; - void SetPromiscReceiveCallback(PromiscReceiveCallback cb) override; - bool SupportsSendFrom() const override; - - private: - /// This value conforms to the 802.11 specification - static const uint16_t MAX_MSDU_SIZE = 2304; - - /// IP v4 Protocol number - static const uint16_t IPv4_PROT_NUMBER = 0x0800; - /// IP v6 Protocol number - static const uint16_t IPv6_PROT_NUMBER = 0x86DD; - - void DoDispose() override; - void DoInitialize() override; - /** - * \param channelNumber the specific channel - * \return whether this channel is valid and available for use - */ - bool IsAvailableChannel(uint32_t channelNumber) const; - /** - * Receive a packet from the lower layer and pass the - * packet up the stack. - * - * \param packet - * \param from - * \param to - */ - void ForwardUp(Ptr packet, Mac48Address from, Mac48Address to); - - /// MacEntities typedef - typedef std::map> MacEntities; - /// MacEntities iterator typedef - typedef std::map>::const_iterator MacEntitiesI; - MacEntities m_macEntities; ///< MAC entities - /// PhyEntities typedef - typedef std::vector> PhyEntities; - /// PhyEntities iterator typedef - typedef std::vector>::const_iterator PhyEntitiesI; - PhyEntities m_phyEntities; ///< Phy entities - - Ptr m_channelManager; ///< the channel manager - Ptr m_channelScheduler; ///< the channel scheduler - Ptr m_channelCoordinator; ///< the channel coordinator - Ptr m_vsaManager; ///< the VSA manager - TxProfile* m_txProfile; ///< transmit profile - /** - * \todo The Address arguments should be passed - * by const reference, since they are large. - */ - TracedCallback m_addressChange; - - // copy from WifiNetDevice - NetDevice::ReceiveCallback m_forwardUp; ///< forward up receive callback - NetDevice::PromiscReceiveCallback m_promiscRx; ///< promiscious receive callback - uint32_t m_ifIndex; ///< IF index - mutable uint16_t m_mtu; ///< MTU -}; - -} // namespace ns3 - -#endif /* WAVE_NET_DEVICE_H */ diff --git a/src/wave/test/examples-to-run.py b/src/wave/test/examples-to-run.py deleted file mode 100644 index c83d2b98b..000000000 --- a/src/wave/test/examples-to-run.py +++ /dev/null @@ -1,23 +0,0 @@ -#! /usr/bin/env python3 - -# A list of C++ examples to run in order to ensure that they remain -# buildable and runnable over time. Each tuple in the list contains -# -# (example_name, do_run, do_valgrind_run). -# -# See test.py for more information. -cpp_examples = [ - ("wave-simple-80211p", "True", "True"), - ("wave-simple-device", "True", "True"), - ("vanet-routing-compare --totaltime=2 --80211Mode=1", "True", "True"), - ("vanet-routing-compare --totaltime=2 --80211Mode=2", "True", "True"), - ("vanet-routing-compare --totaltime=2 --80211Mode=3", "True", "True"), -] - -# A list of Python examples to run in order to ensure that they remain -# runnable over time. Each tuple in the list contains -# -# (example_name, do_run). -# -# See test.py for more information. -python_examples = [] diff --git a/src/wave/test/mac-extension-test-suite.cc b/src/wave/test/mac-extension-test-suite.cc deleted file mode 100644 index 0459543b0..000000000 --- a/src/wave/test/mac-extension-test-suite.cc +++ /dev/null @@ -1,1558 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ -#include "ns3/config.h" -#include "ns3/mobility-helper.h" -#include "ns3/mobility-model.h" -#include "ns3/node-list.h" -#include "ns3/string.h" -#include "ns3/test.h" -#include "ns3/wave-helper.h" -#include "ns3/wave-mac-helper.h" -#include "ns3/wave-net-device.h" -#include "ns3/yans-wifi-helper.h" - -#include - -using namespace ns3; - -/** - * \ingroup wave - * \defgroup wave-test wave module tests - */ - -/** - * \ingroup wave-test - * \ingroup tests - * - * \brief This test case tests the channel coordination. - * In particular, it checks the following: - * - channel interval calculation including CCH Interval, SCH Interval, - * Guard Interval and Sync Interval - * - current interval state for current time and future time - * - channel coordination events notified at the correct time. - */ -class ChannelCoordinationTestCase : public TestCase -{ - public: - ChannelCoordinationTestCase(); - ~ChannelCoordinationTestCase() override; - - // below three methods are used in CoordinationTestListener - /** - * Notify CCS start now function - * \param duration the duration - */ - void NotifyCchStartNow(Time duration); - /** - * Notify SCH start now function - * \param duration the duration - */ - void NotifySchStartNow(Time duration); - /** - * Notify guard start now function - * \param duration the duration - * \param inCchInterval the CCH interval - */ - void NotifyGuardStartNow(Time duration, bool inCchInterval); - - private: - /** - * Test interval after function - * \param cchi the CCHI - * \param schi the SCHI - * \param guardi the guard - */ - void TestIntervalAfter(bool cchi, bool schi, bool guardi); - void DoRun() override; - Ptr m_coordinator; ///< coordinator -}; - -/** - * \ingroup wave-test - * \ingroup tests - * - * \brief CoordinationTestListener is used to test channel coordination events - */ -class CoordinationTestListener : public ChannelCoordinationListener -{ - public: - /** - * Constructor - * - * \param coordinatorTest channel coordination test case - */ - CoordinationTestListener(ChannelCoordinationTestCase* coordinatorTest) - : m_coordinatorTest(coordinatorTest) - { - } - - ~CoordinationTestListener() override - { - } - - void NotifyCchSlotStart(Time duration) override - { - m_coordinatorTest->NotifyCchStartNow(duration); - } - - void NotifySchSlotStart(Time duration) override - { - m_coordinatorTest->NotifySchStartNow(duration); - } - - void NotifyGuardSlotStart(Time duration, bool cchi) override - { - m_coordinatorTest->NotifyGuardStartNow(duration, cchi); - } - - ChannelCoordinationTestCase* m_coordinatorTest; ///< coordinator test -}; - -ChannelCoordinationTestCase::ChannelCoordinationTestCase() - : TestCase("channel-coordination") -{ -} - -ChannelCoordinationTestCase::~ChannelCoordinationTestCase() -{ -} - -void -ChannelCoordinationTestCase::TestIntervalAfter(bool cchi, bool schi, bool guardi) -{ - uint32_t now = Now().GetMilliSeconds(); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->IsCchInterval(), - cchi, - "now is " << now - << "ms " - "check whether is CCH interval"); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->IsSchInterval(), - schi, - "now is " << now - << "ms " - "check whether is SCH interval"); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->IsGuardInterval(), - guardi, - "now is " << now - << "ms " - "check whether is Guard interval"); -} - -void -ChannelCoordinationTestCase::NotifyCchStartNow(Time duration) -{ - // this method shall be called at 4ms, 104ms, ... synci * n + guardi - // synci is sync interval with default value 100ms - // guardi is guard interval with default value 4ms - // n is sequence number - int64_t now = Now().GetMilliSeconds(); - int64_t synci = m_coordinator->GetSyncInterval().GetMilliSeconds(); - int64_t guardi = m_coordinator->GetGuardInterval().GetMilliSeconds(); - bool test = (((now - guardi) % synci) == 0); - NS_TEST_EXPECT_MSG_EQ(test, true, "the time of now shall be synci * n + guardi"); - - // besides that, the argument duration shall be cchi - guardi - Time d = m_coordinator->GetCchInterval() - m_coordinator->GetGuardInterval(); - NS_TEST_EXPECT_MSG_EQ((duration == d), true, "the duration shall be cchi - guardi"); -} - -void -ChannelCoordinationTestCase::NotifySchStartNow(Time duration) -{ - // this method shall be called at 54ms, 154ms, ... synci * n + cchi + guardi - // synci is sync interval with default value 100ms - // cchi is CCH interval with default value 50ms - // guardi is guard interval with default value 4ms - // n is sequence number - int64_t now = Now().GetMilliSeconds(); - int64_t synci = m_coordinator->GetSyncInterval().GetMilliSeconds(); - int64_t cchi = m_coordinator->GetCchInterval().GetMilliSeconds(); - int64_t guardi = m_coordinator->GetGuardInterval().GetMilliSeconds(); - bool test = ((now - guardi - cchi) % synci == 0); - NS_TEST_EXPECT_MSG_EQ(test, true, "the time of now shall be synci * n + cchi + guardi"); - - // besides that, the argument duration shall be schi - guardi - Time d = m_coordinator->GetSchInterval() - m_coordinator->GetGuardInterval(); - NS_TEST_EXPECT_MSG_EQ((duration == d), true, "the duration shall be schi - guardi"); -} - -void -ChannelCoordinationTestCase::NotifyGuardStartNow(Time duration, bool inCchInterval) -{ - int64_t now = Now().GetMilliSeconds(); - int64_t sync = m_coordinator->GetSyncInterval().GetMilliSeconds(); - int64_t cchi = m_coordinator->GetCchInterval().GetMilliSeconds(); - bool test = false; - if (inCchInterval) - { - // if cchi, this method will be called at 0ms, 100ms, sync * n - test = ((now % sync) == 0); - NS_TEST_EXPECT_MSG_EQ(test, true, "the time of now shall be sync * n"); - } - else - { - // if schi, this method will be called at 50ms, 150ms, sync * n + cchi - test = (((now - cchi) % sync) == 0); - NS_TEST_EXPECT_MSG_EQ(test, true, "the time of now shall be sync * n"); - } - // the duration shall be guardi - test = (duration == m_coordinator->GetGuardInterval()); - NS_TEST_EXPECT_MSG_EQ(test, true, "the duration shall be guard interval"); -} - -void -ChannelCoordinationTestCase::DoRun() -{ - // first test configure method - m_coordinator = CreateObject(); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->GetCchInterval(), - MilliSeconds(50), - "normally CCH interval is 50ms"); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->GetSchInterval(), - MilliSeconds(50), - "normally SCH interval is 50ms"); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->GetSyncInterval(), - MilliSeconds(100), - "normally Sync interval is 50ms"); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->GetGuardInterval(), - MilliSeconds(4), - "normally Guard interval is 50ms"); - m_coordinator->SetCchInterval(MilliSeconds(40)); - m_coordinator->SetSchInterval(MilliSeconds(60)); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->IsValidConfig(), - true, - "valid configuration of channel intervals"); - m_coordinator->SetCchInterval(MilliSeconds(40)); - m_coordinator->SetSchInterval(MilliSeconds(50)); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->IsValidConfig(), - false, - "invalid configuration of channel intervals"); - m_coordinator->SetGuardInterval(MilliSeconds(50)); - m_coordinator->SetCchInterval(MilliSeconds(40)); - m_coordinator->SetSchInterval(MilliSeconds(50)); - NS_TEST_EXPECT_MSG_EQ(m_coordinator->IsValidConfig(), - false, - "invalid configuration of channel intervals"); - - // second test member method - m_coordinator = CreateObject(); - Simulator::Schedule(MilliSeconds(0), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Schedule(MilliSeconds(1), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Schedule(MilliSeconds(3), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Schedule(MilliSeconds(4), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - false); - Simulator::Schedule(MilliSeconds(5), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - false); - Simulator::Schedule(MilliSeconds(50), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - true); - Simulator::Schedule(MilliSeconds(51), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - true); - Simulator::Schedule(MilliSeconds(53), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - true); - Simulator::Schedule(MilliSeconds(54), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - false); - Simulator::Schedule(MilliSeconds(55), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - false); - Simulator::Schedule(MilliSeconds(100), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Schedule(MilliSeconds(200), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Schedule(MilliSeconds(201), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Schedule(MilliSeconds(203), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Schedule(MilliSeconds(204), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - false); - Simulator::Schedule(MilliSeconds(205), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - false); - Simulator::Schedule(MilliSeconds(250), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - true); - Simulator::Schedule(MilliSeconds(251), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - true); - Simulator::Schedule(MilliSeconds(253), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - true); - Simulator::Schedule(MilliSeconds(254), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - false); - Simulator::Schedule(MilliSeconds(255), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - false, - true, - false); - Simulator::Schedule(MilliSeconds(300), - &ChannelCoordinationTestCase::TestIntervalAfter, - this, - true, - false, - true); - Simulator::Stop(Seconds(1.0)); - Simulator::Run(); - Simulator::Destroy(); - - m_coordinator = CreateObject(); - // third test channel coordination events - Ptr ptr = Create(this); - m_coordinator->RegisterListener(ptr); - Simulator::Stop(Seconds(100.0)); - Simulator::Run(); - Simulator::Destroy(); -} - -/** - * \ingroup wave-test - * \ingroup tests - * - * \brief Test Case Helper - */ -class TestCaseHelper -{ - public: - /** - * Create WAVE device function - * \param nodesNumber the number of nodes - * \returns the collection of nodes - */ - static NetDeviceContainer CreatWaveDevice(uint32_t nodesNumber = 2); -}; - -#define PI 3.14159265 - -NetDeviceContainer -TestCaseHelper::CreatWaveDevice(uint32_t nodesNumber) -{ - NodeContainer nodes; - nodes.Create(nodesNumber); - - MobilityHelper mobility; - mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); - mobility.Install(nodes); - // this is a circle with radius 10 - Ptr model = NodeList::GetNode(0)->GetObject(); - model->SetPosition(Vector(0, 0, 0)); - for (uint32_t n = 1; n != nodesNumber; ++n) - { - double angle = (PI / 180) * (360 / (nodesNumber - 1) * n); - double x = cos(angle) * 10; - double y = sin(angle) * 10; - Ptr model = NodeList::GetNode(n)->GetObject(); - model->SetPosition(Vector(x, y, 0)); - } - - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); - YansWavePhyHelper wifiPhy = YansWavePhyHelper::Default(); - wifiPhy.SetChannel(wifiChannel.Create()); - QosWaveMacHelper waveMac = QosWaveMacHelper::Default(); - WaveHelper waveHelper = WaveHelper::Default(); - NetDeviceContainer devices = waveHelper.Install(wifiPhy, waveMac, nodes); - return devices; -} - -/** - * route packets or frames in different approaches - * see 1609.4-2010 chapter 5.3.4 - */ -class ChannelRoutingTestCase : public TestCase -{ - public: - ChannelRoutingTestCase(); - ~ChannelRoutingTestCase() override; - - /** - * Send IP-based packets - * - * \param shouldSucceed is used to check whether packet sent should be successful. - * \param ipv6 is IPv6? - */ - void SendIp(bool shouldSucceed, bool ipv6); - /** - * Send WSMP or other packets - * \param shouldSucceed is used to check whether packet sent should be successful. - * \param txInfo transmit info - */ - void SendWsmp(bool shouldSucceed, const TxInfo& txInfo); - /** - * Send VSA management frames - * \param shouldSucceed is used to check whether packet sent should be successful. - * \param vsaInfo VSA info - */ - void SendWsa(bool shouldSucceed, const VsaInfo& vsaInfo); - - private: - void DoRun() override; - /** - * Receive function - * \param dev the device - * \param pkt the packet - * \param mode the mode - * \param sender the sender address - * \returns true if successful - */ - bool Receive(Ptr dev, Ptr pkt, uint16_t mode, const Address& sender); - /** - * Receive VSA function - * \param pkt the packet - * \param address the address - * \returns true if successful - */ - bool ReceiveVsa(Ptr pkt, const Address& address, uint32_t, uint32_t); - - Ptr m_sender; ///< sender -}; - -ChannelRoutingTestCase::ChannelRoutingTestCase() - : TestCase("channel-routing") -{ -} - -ChannelRoutingTestCase::~ChannelRoutingTestCase() -{ -} - -void -ChannelRoutingTestCase::SendWsmp(bool shouldSucceed, const TxInfo& txInfo) -{ - Ptr packet = Create(100); - const Address dest = Mac48Address::GetBroadcast(); - uint16_t protocol = 0x80dd; // any number is OK even ipv4 and ipv6 - bool result = m_sender->SendX(packet, dest, protocol, txInfo); - NS_TEST_EXPECT_MSG_EQ(result, shouldSucceed, "test SendWsmp method error"); -} - -void -ChannelRoutingTestCase::SendIp(bool shouldSucceed, bool ipv6) -{ - Ptr packet = Create(100); - const Address dest = Mac48Address::GetBroadcast(); - const static uint16_t IPv4_PROT_NUMBER = 0x0800; - const static uint16_t IPv6_PROT_NUMBER = 0x86DD; - uint16_t protocol = ipv6 ? IPv6_PROT_NUMBER : IPv4_PROT_NUMBER; - bool result = m_sender->Send(packet, dest, protocol); - NS_TEST_EXPECT_MSG_EQ(result, shouldSucceed, "test SendIp method error"); -} - -void -ChannelRoutingTestCase::SendWsa(bool shouldSucceed, const VsaInfo& vsaInfo) -{ - bool result = m_sender->StartVsa(vsaInfo); - NS_TEST_EXPECT_MSG_EQ(result, shouldSucceed, "test SendWsa method error"); -} - -void -ChannelRoutingTestCase::DoRun() -{ - // check SendX method for WSMP packets - { - NetDeviceContainer devices = TestCaseHelper::CreatWaveDevice(1); - m_sender = DynamicCast(devices.Get(0)); - - Simulator::Schedule(Seconds(0.1), - &ChannelRoutingTestCase::SendWsmp, - this, - true, - TxInfo(CCH)); - Simulator::Schedule(Seconds(0.1), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH1)); - Simulator::Schedule(Seconds(0.1), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH2)); - - const SchInfo schInfo = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(0.2), &WaveNetDevice::StartSch, m_sender, schInfo); - - Simulator::Schedule(Seconds(0.3), - &ChannelRoutingTestCase::SendWsmp, - this, - true, - TxInfo(CCH)); - Simulator::Schedule(Seconds(0.3), - &ChannelRoutingTestCase::SendWsmp, - this, - true, - TxInfo(SCH1)); - Simulator::Schedule(Seconds(0.3), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH2)); - Simulator::Schedule(Seconds(0.3), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH3)); - Simulator::Schedule(Seconds(0.3), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH4)); - Simulator::Schedule(Seconds(0.3), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH5)); - Simulator::Schedule(Seconds(0.3), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH6)); - - // invalid channel number - Simulator::Schedule(Seconds(0.4), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(0)); - // invalid user priority - Simulator::Schedule(Seconds(0.4), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(CCH, 8)); - // invalid tx parameters - Simulator::Schedule(Seconds(0.4), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(CCH, 7, WifiMode("OfdmRate6Mbps"), WIFI_PREAMBLE_LONG, 7)); - Simulator::Schedule( - Seconds(0.4), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(CCH, 7, WifiMode("OfdmRate3MbpsBW10MHz"), WIFI_PREAMBLE_LONG, 10)); - // valid tx parameters - Simulator::Schedule( - Seconds(0.4), - &ChannelRoutingTestCase::SendWsmp, - this, - true, - TxInfo(CCH, 7, WifiMode("OfdmRate3MbpsBW10MHz"), WIFI_PREAMBLE_LONG, 7)); - Simulator::Schedule(Seconds(0.4), - &ChannelRoutingTestCase::SendWsmp, - this, - true, - TxInfo(CCH, 7, WifiMode(), WIFI_PREAMBLE_LONG, 8)); - - // release channel access at 0.6s - Simulator::Schedule(Seconds(0.5), &WaveNetDevice::StopSch, m_sender, SCH1); - - // the packet will be dropped because channel access is not assigned again - Simulator::Schedule(Seconds(0.6), - &ChannelRoutingTestCase::SendWsmp, - this, - true, - TxInfo(CCH)); - Simulator::Schedule(Seconds(0.6), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH1)); - Simulator::Schedule(Seconds(0.6), - &ChannelRoutingTestCase::SendWsmp, - this, - false, - TxInfo(SCH2)); - - Simulator::Stop(Seconds(1.0)); - Simulator::Run(); - Simulator::Destroy(); - } - - // check Send method for IP-based packets - { - NetDeviceContainer devices = TestCaseHelper::CreatWaveDevice(1); - m_sender = DynamicCast(devices.Get(0)); - - bool ipv6 = true; - bool ipv4 = false; - Simulator::Schedule(Seconds(0.1), &ChannelRoutingTestCase::SendIp, this, false, ipv6); - Simulator::Schedule(Seconds(0.1), &ChannelRoutingTestCase::SendIp, this, false, ipv4); - - const SchInfo schInfo = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(0.2), &WaveNetDevice::StartSch, m_sender, schInfo); - - Simulator::Schedule(Seconds(0.3), &ChannelRoutingTestCase::SendIp, this, false, ipv6); - Simulator::Schedule(Seconds(0.3), &ChannelRoutingTestCase::SendIp, this, false, ipv4); - - TxProfile txProfile = TxProfile(SCH1); - Simulator::Schedule(Seconds(0.4), &WaveNetDevice::RegisterTxProfile, m_sender, txProfile); - - Simulator::Schedule(Seconds(0.5), &ChannelRoutingTestCase::SendIp, this, true, ipv6); - Simulator::Schedule(Seconds(0.5), &ChannelRoutingTestCase::SendIp, this, true, ipv4); - - // unregister txprofile - Simulator::Schedule(Seconds(0.5), &WaveNetDevice::DeleteTxProfile, m_sender, SCH1); - - Simulator::Schedule(Seconds(0.6), &ChannelRoutingTestCase::SendIp, this, false, ipv6); - Simulator::Schedule(Seconds(0.6), &ChannelRoutingTestCase::SendIp, this, false, ipv4); - - // release channel access - // mac entities have no channel resource even phy device has ability to send - Simulator::Schedule(Seconds(0.7), &WaveNetDevice::StopSch, m_sender, SCH1); - - Simulator::Schedule(Seconds(0.8), &ChannelRoutingTestCase::SendIp, this, false, ipv6); - Simulator::Schedule(Seconds(0.8), &ChannelRoutingTestCase::SendIp, this, false, ipv4); - - Simulator::Stop(Seconds(1.0)); - Simulator::Run(); - Simulator::Destroy(); - } - - // check StartVsa method for WSA management frames - { - NetDeviceContainer devices = TestCaseHelper::CreatWaveDevice(1); - m_sender = DynamicCast(devices.Get(0)); - - Ptr packet = Create(100); - const Mac48Address dest = Mac48Address::GetBroadcast(); - VsaInfo vsaInfo = - VsaInfo(dest, OrganizationIdentifier(), 3, packet, SCH1, 50, VSA_TRANSMIT_IN_BOTHI); - Simulator::Schedule(Seconds(0.1), &ChannelRoutingTestCase::SendWsa, this, false, vsaInfo); - - vsaInfo.channelNumber = 0; - Simulator::Schedule(Seconds(0.2), &ChannelRoutingTestCase::SendWsa, this, false, vsaInfo); - - vsaInfo.channelNumber = CCH; - Simulator::Schedule(Seconds(0.3), &ChannelRoutingTestCase::SendWsa, this, true, vsaInfo); - Simulator::Schedule(Seconds(0.39), &WaveNetDevice::StopVsa, m_sender, CCH); - - const SchInfo schInfo = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(0.4), &WaveNetDevice::StartSch, m_sender, schInfo); - vsaInfo.channelNumber = CCH; - Simulator::Schedule(Seconds(0.4), &ChannelRoutingTestCase::SendWsa, this, true, vsaInfo); - vsaInfo.channelNumber = SCH1; - Simulator::Schedule(Seconds(0.4), &ChannelRoutingTestCase::SendWsa, this, true, vsaInfo); - vsaInfo.channelNumber = SCH2; - Simulator::Schedule(Seconds(0.4), &ChannelRoutingTestCase::SendWsa, this, false, vsaInfo); - - Simulator::Schedule(Seconds(0.49), &WaveNetDevice::StopVsa, m_sender, CCH); - Simulator::Schedule(Seconds(0.49), &WaveNetDevice::StopVsa, m_sender, SCH1); - Simulator::Schedule(Seconds(0.49), &WaveNetDevice::StopSch, m_sender, SCH1); - - vsaInfo.channelNumber = CCH; - Simulator::Schedule(Seconds(0.5), &ChannelRoutingTestCase::SendWsa, this, true, vsaInfo); - vsaInfo.channelNumber = SCH1; - Simulator::Schedule(Seconds(0.5), &ChannelRoutingTestCase::SendWsa, this, false, vsaInfo); - vsaInfo.channelNumber = SCH2; - Simulator::Schedule(Seconds(0.5), &ChannelRoutingTestCase::SendWsa, this, false, vsaInfo); - - Simulator::Stop(Seconds(1.0)); - Simulator::Run(); - Simulator::Destroy(); - } -} - -/** - * This test case tests channel access assignments which is done by - * StartSch and StopSch method of WaveNetDevice. - * channel access assignments include ContinuousAccess, ExtendedAccess, - * and AlternatingAccess. - * The results of this test case depend on the implementation of ChannelScheduler - * In this case, the results depend on class "DefaultChannelScheduler". - */ -class ChannelAccessTestCase : public TestCase -{ - public: - ChannelAccessTestCase(); - ~ChannelAccessTestCase() override; - - private: - /** - * Test continuous function - * \param info the schedule info - * \param shouldSucceed true if it should succeed - */ - void TestContinuous(SchInfo& info, bool shouldSucceed); - /** - * Test continuous after function - * \param channelNumber the channel number - * \param isAccessAssigned true if access assigned - */ - void TestContinuousAfter(uint32_t channelNumber, bool isAccessAssigned); - /** - * Test extended function - * \param info the schedule info - * \param shouldSucceed true if it should succeed - */ - void TestExtended(SchInfo& info, bool shouldSucceed); - /** - * Test extended after function - * \param channelNumber the channel number - * \param isAccessAssigned true if access assigned - */ - void TestExtendedAfter(uint32_t channelNumber, bool isAccessAssigned); - /** - * Test aternating function - * \param info the schedule info - * \param shouldSucceed true if it should succeed - */ - void TestAlternating(SchInfo& info, bool shouldSucceed); - /** - * Test alternating after function - * \param channelNumber the channel number - * \param isAccessAssigned true if access assigned - */ - void TestAlternatingAfter(uint32_t channelNumber, bool isAccessAssigned); - - /** - * Send X function - * \param channel the channel number - * \param receiverId - */ - void SendX(uint32_t channel, uint32_t receiverId); - /** - * Receive function - * \param dev the device - * \param pkt the packet - * \param mode the mode - * \param sender the sender address - * \returns true if successful - */ - bool Receive(Ptr dev, Ptr pkt, uint16_t mode, const Address& sender); - - void DoRun() override; - - NetDeviceContainer m_devices; ///< the devices - Ptr m_sender; ///< sender - uint32_t m_received; ///< received -}; - -ChannelAccessTestCase::ChannelAccessTestCase() - : TestCase("channel-access") -{ -} - -ChannelAccessTestCase::~ChannelAccessTestCase() -{ -} - -void -ChannelAccessTestCase::TestContinuous(SchInfo& info, bool shouldSucceed) -{ - bool result = m_sender->StartSch(info); - NS_TEST_EXPECT_MSG_EQ(result, shouldSucceed, "TestContinuous fail at " << Now().As(Time::S)); -} - -void -ChannelAccessTestCase::TestContinuousAfter(uint32_t channelNumber, bool isAccessAssigned) -{ - bool result = m_sender->GetChannelScheduler()->IsContinuousAccessAssigned(channelNumber); - NS_TEST_EXPECT_MSG_EQ(result, - isAccessAssigned, - "TestContinuousAfter fail at " << Now().As(Time::S)); -} - -void -ChannelAccessTestCase::TestExtended(SchInfo& info, bool shouldSucceed) -{ - bool result = m_sender->StartSch(info); - NS_TEST_EXPECT_MSG_EQ(result, shouldSucceed, "TestExtended fail at " << Now().As(Time::S)); -} - -void -ChannelAccessTestCase::TestExtendedAfter(uint32_t channelNumber, bool isAccessAssigned) -{ - bool result = m_sender->GetChannelScheduler()->IsExtendedAccessAssigned(channelNumber); - NS_TEST_EXPECT_MSG_EQ(result, - isAccessAssigned, - "TestExtendedAfter fail at " << Now().As(Time::S)); -} - -void -ChannelAccessTestCase::TestAlternating(SchInfo& info, bool shouldSucceed) -{ - bool result = m_sender->StartSch(info); - NS_TEST_EXPECT_MSG_EQ(result, shouldSucceed, "TestAlternating fail at " << Now().As(Time::S)); -} - -void -ChannelAccessTestCase::TestAlternatingAfter(uint32_t channelNumber, bool isAccessAssigned) -{ - bool result = m_sender->GetChannelScheduler()->IsAlternatingAccessAssigned(channelNumber); - NS_TEST_EXPECT_MSG_EQ(result, - isAccessAssigned, - "TestAlternating fail at " << Now().As(Time::S)); -} - -void -ChannelAccessTestCase::SendX(uint32_t channel, uint32_t receiverId) -{ - const static uint16_t WSMP_PROT_NUMBER = 0x88DC; - const Mac48Address dest = Mac48Address::GetBroadcast(); - const TxInfo txInfo = TxInfo(channel); - - uint8_t* data = new uint8_t[112]; - data[0] = (receiverId >> 24) & 0xFF; - data[1] = (receiverId >> 16) & 0xFF; - data[2] = (receiverId >> 8) & 0xFF; - data[3] = (receiverId >> 0) & 0xFF; - - uint64_t ts = Simulator::Now().GetTimeStep(); - data[4] = (ts >> 56) & 0xFF; - data[5] = (ts >> 48) & 0xFF; - data[6] = (ts >> 40) & 0xFF; - data[7] = (ts >> 32) & 0xFF; - data[8] = (ts >> 24) & 0xFF; - data[9] = (ts >> 16) & 0xFF; - data[10] = (ts >> 8) & 0xFF; - data[11] = (ts >> 0) & 0xFF; - - Ptr p = Create(data, 112); - - m_sender->SendX(p, dest, WSMP_PROT_NUMBER, txInfo); - - delete[] data; -} - -bool -ChannelAccessTestCase::Receive(Ptr dev, - Ptr pkt, - uint16_t mode, - const Address& sender) -{ - uint8_t* data = new uint8_t[pkt->GetSize()]; - pkt->CopyData(data, pkt->GetSize()); - - uint32_t seq = data[0]; - seq <<= 8; - seq |= data[1]; - seq <<= 8; - seq |= data[2]; - seq <<= 8; - seq |= data[3]; - - uint64_t ts = data[4]; - ts <<= 8; - ts |= data[5]; - ts <<= 8; - ts |= data[6]; - ts <<= 8; - ts |= data[7]; - ts <<= 8; - ts |= data[8]; - ts <<= 8; - ts |= data[9]; - ts <<= 8; - ts |= data[10]; - ts <<= 8; - ts |= data[11]; - Time sendTime = TimeStep(ts); - - delete[] data; - - // SeqTsHeader seqTs; - // ConstCast (pkt)->RemoveHeader (seqTs); - uint32_t curNodeId = dev->GetNode()->GetId(); - NS_TEST_EXPECT_MSG_EQ(curNodeId, seq, "fail to assign channel access"); - m_received++; - return true; -} - -void -ChannelAccessTestCase::DoRun() -{ - // test ContinuousAccess in the sender side - { - m_devices = TestCaseHelper::CreatWaveDevice(1); - m_sender = DynamicCast(m_devices.Get(0)); - - // there is no need for assigning CCH continuous access. - SchInfo info = SchInfo(CCH, false, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(1), &ChannelAccessTestCase::TestContinuous, this, info, false); - - info = SchInfo(SCH1, false, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(2), &ChannelAccessTestCase::TestContinuous, this, info, true); - - // BE ATTENTION !!! - // because channel access is assigned in non-immediate mode, the first CCH Interval will be - // the wait time with DefaultCchAccess assigned, thus there is no ContinuousAccess assigned. - Simulator::Schedule(Seconds(2), - &ChannelAccessTestCase::TestContinuousAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.01), - &ChannelAccessTestCase::TestContinuousAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.049), - &ChannelAccessTestCase::TestContinuousAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.05), - &ChannelAccessTestCase::TestContinuousAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.051), - &ChannelAccessTestCase::TestContinuousAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(2.99), - &ChannelAccessTestCase::TestContinuousAfter, - this, - SCH1, - true); - - // it's OK to assign same access again, - Simulator::Schedule(Seconds(3), &ChannelAccessTestCase::TestContinuous, this, info, true); - // fail to assign continuous access for other SCH if current channel is assigned - info = SchInfo(SCH2, false, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(4), &ChannelAccessTestCase::TestContinuous, this, info, false); - - // then we release channel access at 0.5s - Simulator::Schedule(Seconds(5), &WaveNetDevice::StopSch, m_sender, SCH1); - - info = SchInfo(SCH2, false, EXTENDED_CONTINUOUS); - // succeed to assign access for other SCH is previous SCH access is released - Simulator::Schedule(Seconds(6), &ChannelAccessTestCase::TestContinuous, this, info, true); - - Simulator::Stop(Seconds(7.0)); - Simulator::Run(); - Simulator::Destroy(); - } - - // test ContinuousAccess again in the receiver side - { - m_devices = TestCaseHelper::CreatWaveDevice(8); - m_sender = DynamicCast(m_devices.Get(0)); - m_received = 0; - - for (uint32_t i = 1; i != 8; ++i) - { - Ptr device = DynamicCast(m_devices.Get(i)); - device->SetReceiveCallback(MakeCallback(&ChannelAccessTestCase::Receive, this)); - - // at 0s, receivers are assigned ContinuousAccess from CCH, SCH1 to SCH6 - static std::vector WaveChannels = ChannelManager::GetWaveChannels(); - uint32_t channel = WaveChannels[i - 1]; - const SchInfo info = SchInfo(channel, false, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(0), &WaveNetDevice::StartSch, device, info); - } - - // at 0s, the sender is assigned DefaultCchAccess, so only node-1 can receive packets. - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, CCH, 1); - // if receivers assigned for SCH access can receive packets, there shall be crashed - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH1, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH6, 0); - - // at 1s, the sender is assigned ContinuousAccess for SCH1, so only node-2 can receive - // packets. - SchInfo info = SchInfo(SCH1, false, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(1), &WaveNetDevice::StartSch, m_sender, info); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH1, 2); - // other channel access cannot receive packets - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, CCH, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH6, 0); - - Simulator::Stop(Seconds(10.0)); - Simulator::Run(); - Simulator::Destroy(); - - NS_TEST_EXPECT_MSG_EQ(m_received, 2, "test ContinuousAccess fail in receive side"); - } - - // test ExtendedAccess in the sender side - { - m_devices = TestCaseHelper::CreatWaveDevice(1); - m_sender = DynamicCast(m_devices.Get(0)); - - // there is no need for assigning CCH extended access. - SchInfo info = SchInfo(CCH, false, 10); - Simulator::Schedule(Seconds(1), &ChannelAccessTestCase::TestExtended, this, info, false); - - info = SchInfo(SCH1, false, 10); - Simulator::Schedule(Seconds(2), &ChannelAccessTestCase::TestExtended, this, info, true); - // succeed because request for extends 8 can be fulfilled by previous extends 10.. - info = SchInfo(SCH1, false, 8); - Simulator::Schedule(Seconds(2), &ChannelAccessTestCase::TestExtended, this, info, true); - // fail because request for extends 12 cannot be fulfilled by previous extends 10.. - info = SchInfo(SCH1, false, 12); - Simulator::Schedule(Seconds(2), &ChannelAccessTestCase::TestExtended, this, info, false); - - // BE ATTENTION !!! - // because channel access is assigned in non-immediate mode, the first CCH Interval will be - // the wait time with DefaultCchAccess assigned, while there is no ExtendedAccess assigned. - Simulator::Schedule(Seconds(2), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.01), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.049), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.05), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(2.051), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(2.99), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - true); - - // the end of extended access is (2s + 100ms + 100ms * 10) = 3.1s - Simulator::Schedule(Seconds(3), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(3.1), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(3.2), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - false); - Simulator::Schedule(Seconds(3.3), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH1, - false); - - // succeed to assign extended access for other SCH since previous extended access is - // released automatically - info = SchInfo(SCH2, false, 10); - Simulator::Schedule(Seconds(4), &ChannelAccessTestCase::TestExtended, this, info, true); - - // stop it at 5s even the end of extended access is (4s + 100ms + 100ms * 10) = 5.1s - Simulator::Schedule(Seconds(5), &WaveNetDevice::StopSch, m_sender, SCH2); - - Simulator::Schedule(Seconds(5), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH2, - false); - Simulator::Schedule(Seconds(5.1), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH2, - false); - Simulator::Schedule(Seconds(5.2), - &ChannelAccessTestCase::TestExtendedAfter, - this, - SCH2, - false); - - Simulator::Stop(Seconds(6.0)); - Simulator::Run(); - Simulator::Destroy(); - } - - // test ExtendedAccess again in the receiver side - { - m_devices = TestCaseHelper::CreatWaveDevice(8); - m_sender = DynamicCast(m_devices.Get(0)); - m_received = 0; - - for (uint32_t i = 1; i != 8; ++i) - { - Ptr device = DynamicCast(m_devices.Get(i)); - device->SetReceiveCallback(MakeCallback(&ChannelAccessTestCase::Receive, this)); - - // at 0s, receivers are assigned ContinuousAccess from CCH, SCH1 to SCH6 - static std::vector WaveChannels = ChannelManager::GetWaveChannels(); - uint32_t channel = WaveChannels[i - 1]; - const SchInfo info = SchInfo(channel, false, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(0), &WaveNetDevice::StartSch, device, info); - } - - // at 0s, the sender is assigned DefaultCchAccess, so only node-1 can receive packets. - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, CCH, 1); - // if receivers assigned for SCH access can receive packets, there shall be crashed - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH1, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH6, 0); - - // at 1s, the sender is assigned ExtendedAccess for SCH1 with extends 10, - //, so only node-2 can receive packets from 1s - 2.1s ( 1s + 100ms + 100ms * 10) - SchInfo info = SchInfo(SCH1, false, 10); - Simulator::Schedule(Seconds(1), &WaveNetDevice::StartSch, m_sender, info); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH1, 2); - // other channel access cannot receive packets - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, CCH, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH6, 0); - // at 2.2s the node-2 cannot receive this packet because of extended access released in - // node-0 but sended is assigned DefaultCchAccess again, thus node-1 can receive broadcasted - // packets. - Simulator::Schedule(Seconds(2.2), &ChannelAccessTestCase::SendX, this, CCH, 1); - Simulator::Schedule(Seconds(2.2), &ChannelAccessTestCase::SendX, this, SCH1, 0); - Simulator::Schedule(Seconds(2.2), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(2.2), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(2.2), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(2.2), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(2.2), &ChannelAccessTestCase::SendX, this, SCH6, 0); - - Simulator::Stop(Seconds(10.0)); - Simulator::Run(); - Simulator::Destroy(); - - NS_TEST_EXPECT_MSG_EQ(m_received, 3, "test ExtendedAccess fail in receive side"); - } - - // test AlternatingAccess in the sender side - { - m_devices = TestCaseHelper::CreatWaveDevice(1); - m_sender = DynamicCast(m_devices.Get(0)); - - // there is no need for assigning CCH alternating access. - SchInfo info = SchInfo(CCH, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(1), &ChannelAccessTestCase::TestAlternating, this, info, false); - - info = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(2), &ChannelAccessTestCase::TestAlternating, this, info, true); - - // BE ATTENTION !!! - // No matter whether channel access is assigned in immediate mode or non-immediate mode, - // the channel access will assigned immediately which is different from the test results in - // ExtendedAccess assignment and ContinuousAccess assignment. - Simulator::Schedule(Seconds(2), - &ChannelAccessTestCase::TestAlternatingAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(2.01), - &ChannelAccessTestCase::TestAlternatingAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(2.049), - &ChannelAccessTestCase::TestAlternatingAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(2.05), - &ChannelAccessTestCase::TestAlternatingAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(2.051), - &ChannelAccessTestCase::TestAlternatingAfter, - this, - SCH1, - true); - Simulator::Schedule(Seconds(2.99), - &ChannelAccessTestCase::TestAlternatingAfter, - this, - SCH1, - true); - - Simulator::Schedule(Seconds(3), &ChannelAccessTestCase::TestAlternating, this, info, true); - info = SchInfo(SCH2, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(3), &ChannelAccessTestCase::TestAlternating, this, info, false); - info = SchInfo(0, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(3), &ChannelAccessTestCase::TestAlternating, this, info, false); - - // then we release channel access at 0.5s - Simulator::Schedule(Seconds(4), &WaveNetDevice::StopSch, m_sender, SCH1); - - info = SchInfo(SCH2, false, EXTENDED_ALTERNATING); - // succeed to assign access for other SCH is previous SCH access is released - Simulator::Schedule(Seconds(5), &ChannelAccessTestCase::TestAlternating, this, info, true); - - Simulator::Stop(Seconds(6.0)); - Simulator::Run(); - Simulator::Destroy(); - } - - // test AlternatingAccess again in the receiver side - { - m_devices = TestCaseHelper::CreatWaveDevice(8); - m_sender = DynamicCast(m_devices.Get(0)); - m_received = 0; - - for (uint32_t i = 1; i != 8; ++i) - { - Ptr device = DynamicCast(m_devices.Get(i)); - device->SetReceiveCallback(MakeCallback(&ChannelAccessTestCase::Receive, this)); - - // at 0s, receivers are assigned ContinuousAccess from CCH, SCH1 to SCH6 - static std::vector WaveChannels = ChannelManager::GetWaveChannels(); - uint32_t channel = WaveChannels[i - 1]; - const SchInfo info = SchInfo(channel, false, EXTENDED_CONTINUOUS); - Simulator::Schedule(Seconds(0), &WaveNetDevice::StartSch, device, info); - } - - // at 0s, the sender is assigned DefaultCchAccess, so only node-1 can receive packets. - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, CCH, 1); - // if receivers assigned for SCH access can receive packets, there shall be crashed - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH1, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(0.1), &ChannelAccessTestCase::SendX, this, SCH6, 0); - - // at 1s, the sender is assigned ContinuousAccess for SCH1, so only node-2 can receive - // packets. - SchInfo info = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(Seconds(1), &WaveNetDevice::StartSch, m_sender, info); - // node-1 (assigned CCH access) and node-2 (assigned SCH1 access) can receive packets - // in different channel interval - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH1, 2); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, CCH, 1); - // other channel access cannot receive packets - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(1.1), &ChannelAccessTestCase::SendX, this, SCH6, 0); - - Simulator::Schedule(Seconds(2), &WaveNetDevice::StopSch, m_sender, SCH1); - // if ContinuousAccess for SCH1 is released, node-2 cannot receive packets again - Simulator::Schedule(Seconds(2.1), &ChannelAccessTestCase::SendX, this, CCH, 1); - Simulator::Schedule(Seconds(2.1), &ChannelAccessTestCase::SendX, this, SCH1, 0); - Simulator::Schedule(Seconds(2.1), &ChannelAccessTestCase::SendX, this, SCH2, 0); - Simulator::Schedule(Seconds(2.1), &ChannelAccessTestCase::SendX, this, SCH3, 0); - Simulator::Schedule(Seconds(2.1), &ChannelAccessTestCase::SendX, this, SCH4, 0); - Simulator::Schedule(Seconds(2.1), &ChannelAccessTestCase::SendX, this, SCH5, 0); - Simulator::Schedule(Seconds(2.1), &ChannelAccessTestCase::SendX, this, SCH6, 0); - - Simulator::Stop(Seconds(10.0)); - Simulator::Run(); - Simulator::Destroy(); - - NS_TEST_EXPECT_MSG_EQ(m_received, 4, "test AlternatingAccess fail in receive side"); - } -} - -/** - * \ingroup wave-test - * \ingroup tests - * - * \brief The Annex C of IEEE 1609.4 : "Avoiding transmission at scheduled guard intervals" - * This feature is implemented in WaveMacLow::StartTransmission method - */ -class AnnexC_TestCase : public TestCase -{ - public: - AnnexC_TestCase(); - ~AnnexC_TestCase() override; - - private: - void DoRun() override; - - /** - * Send packet function - * \param packetSize the packet size - * \param txInfo the transmit info - * \param sequence the sequence - */ - void SendPacket(uint32_t packetSize, const TxInfo& txInfo, uint32_t sequence); - /** - * Receive function - * \param dev the device - * \param pkt the packet - * \param mode the mode - * \param sender the sender address - * \returns true if successful - */ - bool Receive(Ptr dev, Ptr pkt, uint16_t mode, const Address& sender); - - NetDeviceContainer m_devices; ///< devices - Ptr m_sender; ///< sender - Ptr m_receiver; ///< receiver -}; - -AnnexC_TestCase::AnnexC_TestCase() - : TestCase("annex-c") -{ -} - -AnnexC_TestCase::~AnnexC_TestCase() -{ -} - -void -AnnexC_TestCase::SendPacket(uint32_t packetSize, const TxInfo& txInfo, uint32_t sequence) -{ - const static uint16_t WSMP_PROT_NUMBER = 0x88DC; - const Mac48Address dest = Mac48Address::ConvertFrom(m_receiver->GetAddress()); - - uint8_t* data = new uint8_t[packetSize]; - data[0] = (sequence >> 24) & 0xFF; - data[1] = (sequence >> 16) & 0xFF; - data[2] = (sequence >> 8) & 0xFF; - data[3] = (sequence >> 0) & 0xFF; - - uint64_t ts = Simulator::Now().GetTimeStep(); - data[4] = (ts >> 56) & 0xFF; - data[5] = (ts >> 48) & 0xFF; - data[6] = (ts >> 40) & 0xFF; - data[7] = (ts >> 32) & 0xFF; - data[8] = (ts >> 24) & 0xFF; - data[9] = (ts >> 16) & 0xFF; - data[10] = (ts >> 8) & 0xFF; - data[11] = (ts >> 0) & 0xFF; - - Ptr p = Create(data, packetSize); - - m_sender->SendX(p, dest, WSMP_PROT_NUMBER, txInfo); - - delete[] data; -} - -bool -AnnexC_TestCase::Receive(Ptr dev, - Ptr pkt, - uint16_t mode, - const Address& sender) -{ - uint8_t* data = new uint8_t[pkt->GetSize()]; - pkt->CopyData(data, pkt->GetSize()); - - uint32_t seq = data[0]; - seq <<= 8; - seq |= data[1]; - seq <<= 8; - seq |= data[2]; - seq <<= 8; - seq |= data[3]; - - uint64_t ts = data[4]; - ts <<= 8; - ts |= data[5]; - ts <<= 8; - ts |= data[6]; - ts <<= 8; - ts |= data[7]; - ts <<= 8; - ts |= data[8]; - ts <<= 8; - ts |= data[9]; - ts <<= 8; - ts |= data[10]; - ts <<= 8; - ts |= data[11]; - Time sendTime = TimeStep(ts); - - delete[] data; - - Time curTime = Now(); - Time duration = curTime - sendTime; - - if (seq == 1) - { - NS_TEST_EXPECT_MSG_GT(duration, - ChannelCoordinator::GetDefaultSchInterval(), - "fail to test Annex C when packet sequence is " << seq); - } - else if (seq == 2) - { - NS_TEST_EXPECT_MSG_LT(duration, - ChannelCoordinator::GetDefaultSchInterval(), - "fail to test Annex C when packet sequence is " << seq); - } - else if (seq == 3) - { - NS_TEST_EXPECT_MSG_GT(duration, - ChannelCoordinator::GetDefaultCchInterval(), - "fail to test Annex C when packet sequence is " << seq); - } - else if (seq == 4) - { - NS_TEST_EXPECT_MSG_LT(duration, - ChannelCoordinator::GetDefaultCchInterval(), - "fail to test Annex C when packet sequence is " << seq); - } - return true; -} - -void -AnnexC_TestCase::DoRun() -{ - m_devices = TestCaseHelper::CreatWaveDevice(2); - m_sender = DynamicCast(m_devices.Get(0)); - m_receiver = DynamicCast(m_devices.Get(1)); - m_receiver->SetReceiveCallback(MakeCallback(&AnnexC_TestCase::Receive, this)); - - // at 0s, the receiver is assigned AlternatingAccess for SCH1 - SchInfo infoReceiver = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(MilliSeconds(0), &WaveNetDevice::StartSch, m_receiver, infoReceiver); - - // at 0s, the sender is assigned AlternatingAccess for SCH1 - SchInfo infoSender = SchInfo(SCH1, false, EXTENDED_ALTERNATING); - Simulator::Schedule(MilliSeconds(0), &WaveNetDevice::StartSch, m_sender, infoSender); - - TxInfo txInfo = TxInfo(CCH, 0, WifiMode("OfdmRate3MbpsBW10MHz"), WIFI_PREAMBLE_LONG, 0); - // the packet size with 2312 bytes costs 6.42s, which will cancel this transmission in the CCH - // Interval so the receiver will receive this packet in next CCH Interval - Simulator::Schedule(MilliSeconds(45), &AnnexC_TestCase::SendPacket, this, 2304, txInfo, 1); - - // the packet size with 312 bytes costs 1.104ms, which will not cancel transmission in the CCH - // Interval so the receiver can this packet is this CCH Interval - Simulator::Schedule(MilliSeconds(145), &AnnexC_TestCase::SendPacket, this, 312, txInfo, 2); - - txInfo = TxInfo(SCH1, 0, WifiMode("OfdmRate3MbpsBW10MHz"), WIFI_PREAMBLE_LONG, 0); - // the packet size with 2312 bytes costs 6.42ms, which will cancel this transmission in the SCH - // Interval so the receiver will receive this packet in next SCH Interval - Simulator::Schedule(MilliSeconds(295), &AnnexC_TestCase::SendPacket, this, 2304, txInfo, 3); - - // the packet size with 312 bytes costs 1.104ms, which will not cancel transmission in the SCH - // Interval so the receiver can this packet is this SCH Interval - Simulator::Schedule(MilliSeconds(395), &AnnexC_TestCase::SendPacket, this, 312, txInfo, 4); - - Simulator::Stop(Seconds(1.0)); - Simulator::Run(); - Simulator::Destroy(); -} - -/** - * \ingroup wave-test - * \ingroup tests - * - * \brief Wave Mac Test Suite - */ -class WaveMacTestSuite : public TestSuite -{ - public: - WaveMacTestSuite(); -}; - -WaveMacTestSuite::WaveMacTestSuite() - : TestSuite("wave-mac-extension", UNIT) -{ - // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER - AddTestCase(new ChannelCoordinationTestCase, TestCase::QUICK); - AddTestCase(new ChannelRoutingTestCase, TestCase::QUICK); - AddTestCase(new ChannelAccessTestCase, TestCase::QUICK); - AddTestCase(new AnnexC_TestCase, TestCase::QUICK); -} - -// Do not forget to allocate an instance of this TestSuite -static WaveMacTestSuite waveMacTestSuite; ///< the test suite diff --git a/src/wave/test/ocb-test-suite.cc b/src/wave/test/ocb-test-suite.cc deleted file mode 100644 index 4b6336d35..000000000 --- a/src/wave/test/ocb-test-suite.cc +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (c) 2013 Dalian University of Technology - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Junling Bu - */ - -#include "ns3/config.h" -#include "ns3/data-rate.h" -#include "ns3/mobility-helper.h" -#include "ns3/mobility-model.h" -#include "ns3/ocb-wifi-mac.h" -#include "ns3/packet-socket-address.h" -#include "ns3/packet-socket-client.h" -#include "ns3/packet-socket-helper.h" -#include "ns3/packet-socket-server.h" -#include "ns3/position-allocator.h" -#include "ns3/qos-txop.h" -#include "ns3/rng-seed-manager.h" -#include "ns3/sta-wifi-mac.h" -#include "ns3/string.h" -#include "ns3/test.h" -#include "ns3/vector.h" -#include "ns3/wave-mac-helper.h" -#include "ns3/wifi-80211p-helper.h" -#include "ns3/wifi-net-device.h" -#include "ns3/yans-wifi-helper.h" - -#include - -using namespace ns3; - -// helper function to assign streams to random variables, to control -// randomness in the tests -static void -AssignWifiRandomStreams(Ptr mac, int64_t stream) -{ - int64_t currentStream = stream; - PointerValue ptr; - if (!mac->GetQosSupported()) - { - mac->GetAttribute("Txop", ptr); - Ptr txop = ptr.Get(); - currentStream += txop->AssignStreams(currentStream); - } - else - { - mac->GetAttribute("VO_Txop", ptr); - Ptr vo_txop = ptr.Get(); - currentStream += vo_txop->AssignStreams(currentStream); - - mac->GetAttribute("VI_Txop", ptr); - Ptr vi_txop = ptr.Get(); - currentStream += vi_txop->AssignStreams(currentStream); - - mac->GetAttribute("BE_Txop", ptr); - Ptr be_txop = ptr.Get(); - currentStream += be_txop->AssignStreams(currentStream); - - mac->GetAttribute("BK_Txop", ptr); - Ptr bk_txop = ptr.Get(); - currentStream += bk_txop->AssignStreams(currentStream); - } -} - -/** - * \ingroup wave-test - * \ingroup tests - * - * \brief Ocb Wifi Mac Test Case - */ -class OcbWifiMacTestCase : public TestCase -{ - public: - OcbWifiMacTestCase(); - ~OcbWifiMacTestCase() override; - - private: - void DoRun() override; - - /** - * MAC associate function - * \param context the context - * \param bssid the BSSID - */ - void MacAssoc(std::string context, Mac48Address bssid); - /** - * Phy receive ok trace function - * \param context the context - * \param packet the packet - * \param snr the SNR - * \param mode the mode - * \param preamble the preamble - */ - void PhyRxOkTrace(std::string context, - Ptr packet, - double snr, - WifiMode mode, - WifiPreamble preamble); - /** - * Phy transmit trace function - * \param context the context - * \param packet the packet - * \param mode the mode - * \param preamble the preamble - * \param txPower the transmit power - */ - void PhyTxTrace(std::string context, - Ptr packet, - WifiMode mode, - WifiPreamble preamble, - uint8_t txPower); - /** - * Get current position function - * \param i the current position index - * \returns the current position vector - */ - Vector GetCurrentPosition(uint32_t i); - /** - * Advance position function - * \param node the node - */ - void AdvancePosition(Ptr node); - - /// Pre random configuration function - void PreRandomConfiguration(); - /** - * Configure AP STA mode function - * \param static_node the static node - * \param mobile_node the mobile node - */ - void ConfigureApStaMode(Ptr static_node, Ptr mobile_node); - /** - * Configure adhoc mode function - * \param static_node the static node - * \param mobile_node the mobile node - */ - void ConfigureAdhocMode(Ptr static_node, Ptr mobile_node); - /** - * Configure OCB mode function - * \param static_node the static node - * \param mobile_node the mobile node - */ - void ConfigureOcbMode(Ptr static_node, Ptr mobile_node); - /** - * Post device configuration function - * \param static_node the static node - * \param mobile_node the mobile node - */ - void PostDeviceConfiguration(Ptr static_node, Ptr mobile_node); - - Time phytx_time; ///< Phy transmit time - Vector phytx_pos; ///< Phy transmit position - - Time macassoc_time; ///< MAC associate time - Vector macassoc_pos; ///< MAC associate position - - Time phyrx_time; ///< Phy receive time - Vector phyrx_pos; ///< Phy receive position - - // nodes.Get (0) is static node - // nodes.Get (1) is mobile node - NodeContainer nodes; ///< the nodes -}; - -OcbWifiMacTestCase::OcbWifiMacTestCase() - : TestCase("Association time: Ap+Sta mode vs Adhoc mode vs Ocb mode") -{ -} - -OcbWifiMacTestCase::~OcbWifiMacTestCase() -{ -} - -// mobility is like walk on line with velocity 5 m/s -// We prefer to update 0.5m every 0.1s rather than 5m every 1s -void -OcbWifiMacTestCase::AdvancePosition(Ptr node) -{ - Ptr mobility = node->GetObject(); - Vector pos = mobility->GetPosition(); - pos.x -= 0.5; - if (pos.x < 1.0) - { - pos.x = 1.0; - return; - } - mobility->SetPosition(pos); - - Simulator::Schedule(Seconds(0.1), &OcbWifiMacTestCase::AdvancePosition, this, node); -} - -// here are only two nodes, a stationary and a mobile one -// the i value of the first = 0; the i value of second = 1. -Vector -OcbWifiMacTestCase::GetCurrentPosition(uint32_t i) -{ - NS_ASSERT(i < 2); - Ptr node = nodes.Get(i); - Ptr mobility = node->GetObject(); - Vector pos = mobility->GetPosition(); - return pos; -} - -void -OcbWifiMacTestCase::MacAssoc(std::string context, Mac48Address bssid) -{ - if (macassoc_time == Time(0)) - { - macassoc_time = Now(); - macassoc_pos = GetCurrentPosition(1); - std::cout << "MacAssoc time = " << macassoc_time.As(Time::NS) - << " position = " << macassoc_pos << std::endl; - } -} - -// We want to get the time that sta receives the first beacon frame from AP -// it means that in this time this sta has ability to receive frame -void -OcbWifiMacTestCase::PhyRxOkTrace(std::string context, - Ptr packet, - double snr, - WifiMode mode, - WifiPreamble preamble) -{ - if (phyrx_time == Time(0)) - { - phyrx_time = Now(); - phyrx_pos = GetCurrentPosition(1); - std::cout << "PhyRxOk time = " << phyrx_time.As(Time::NS) << " position = " << phyrx_pos - << std::endl; - } -} - -// We want to get the time that STA sends the first data packet successfully -void -OcbWifiMacTestCase::PhyTxTrace(std::string context, - Ptr packet, - WifiMode mode, - WifiPreamble preamble, - uint8_t txPower) -{ - WifiMacHeader h; - packet->PeekHeader(h); - if ((phytx_time == Time(0)) && h.IsData()) - { - phytx_time = Now(); - phytx_pos = GetCurrentPosition(1); - std::cout << "PhyTx data time = " << phytx_time.As(Time::NS) << " position = " << phytx_pos - << std::endl; - } -} - -void -OcbWifiMacTestCase::ConfigureApStaMode(Ptr static_node, Ptr mobile_node) -{ - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); - YansWifiPhyHelper wifiPhy; - wifiPhy.SetChannel(wifiChannel.Create()); - - Ssid ssid = Ssid("wifi-default"); - WifiMacHelper wifiStaMac; - wifiStaMac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid)); - WifiMacHelper wifiApMac; - wifiApMac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid)); - - WifiHelper wifi; - wifi.SetStandard(WIFI_STANDARD_80211p); - wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue("OfdmRate6MbpsBW10MHz"), - "ControlMode", - StringValue("OfdmRate6MbpsBW10MHz")); - wifi.Install(wifiPhy, wifiStaMac, mobile_node); - wifi.Install(wifiPhy, wifiApMac, static_node); -} - -void -OcbWifiMacTestCase::ConfigureAdhocMode(Ptr static_node, Ptr mobile_node) -{ - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); - YansWifiPhyHelper wifiPhy; - wifiPhy.SetChannel(wifiChannel.Create()); - - WifiMacHelper wifiMac; - wifiMac.SetType("ns3::AdhocWifiMac"); - - WifiHelper wifi; - wifi.SetStandard(WIFI_STANDARD_80211p); - wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue("OfdmRate6MbpsBW10MHz"), - "ControlMode", - StringValue("OfdmRate6MbpsBW10MHz")); - wifi.Install(wifiPhy, wifiMac, mobile_node); - wifi.Install(wifiPhy, wifiMac, static_node); -} - -void -OcbWifiMacTestCase::ConfigureOcbMode(Ptr static_node, Ptr mobile_node) -{ - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); - YansWifiPhyHelper wifiPhy; - wifiPhy.SetChannel(wifiChannel.Create()); - - NqosWaveMacHelper wifi80211pMac = NqosWaveMacHelper::Default(); - - Wifi80211pHelper wifi80211p = Wifi80211pHelper::Default(); - wifi80211p.SetRemoteStationManager("ns3::ConstantRateWifiManager", - "DataMode", - StringValue("OfdmRate6MbpsBW10MHz"), - "ControlMode", - StringValue("OfdmRate6MbpsBW10MHz")); - wifi80211p.Install(wifiPhy, wifi80211pMac, mobile_node); - wifi80211p.Install(wifiPhy, wifi80211pMac, static_node); -} - -void -OcbWifiMacTestCase::PostDeviceConfiguration(Ptr static_node, Ptr mobile_node) -{ - Ptr static_device = DynamicCast(static_node->GetDevice(0)); - Ptr mobile_device = DynamicCast(mobile_node->GetDevice(0)); - - // Fix the stream assignment to the Dcf Txop objects (backoffs) - // The below stream assignment will result in the Txop object - // using a backoff value of zero for this test when the - // Txop::EndTxNoAck() calls to StartBackoffNow() - AssignWifiRandomStreams(static_device->GetMac(), 21); - AssignWifiRandomStreams(mobile_device->GetMac(), 22); - - // setup mobility - // the initial position of static node is at 0, - // and the initial position of mobile node is 350. - MobilityHelper mobility; - mobility.Install(mobile_node); - mobility.Install(static_node); - Ptr mm = mobile_node->GetObject(); - Vector possta = mm->GetPosition(); - possta.x = 350; - mm->SetPosition(possta); - Simulator::Schedule(Seconds(1.0), &OcbWifiMacTestCase::AdvancePosition, this, mobile_node); - - PacketSocketAddress socket; - socket.SetSingleDevice(mobile_device->GetIfIndex()); - socket.SetPhysicalAddress(static_device->GetAddress()); - socket.SetProtocol(1); - - // give packet socket powers to nodes. - PacketSocketHelper packetSocket; - packetSocket.Install(static_node); - packetSocket.Install(mobile_node); - - Ptr client = CreateObject(); - client->SetRemote(socket); - mobile_node->AddApplication(client); - client->SetStartTime(Seconds(0.5)); - client->SetStopTime(Seconds(70.0)); - - Ptr server = CreateObject(); - server->SetLocal(socket); - static_node->AddApplication(server); - server->SetStartTime(Seconds(0.0)); - server->SetStopTime(Seconds(70.5)); - - phytx_time = macassoc_time = phyrx_time = Time(); - phytx_pos = macassoc_pos = phyrx_pos = Vector(); - - if (DynamicCast(mobile_device->GetMac())) - { - // This trace is available only in a StaWifiMac - Config::Connect("/NodeList/1/DeviceList/*/Mac/Assoc", - MakeCallback(&OcbWifiMacTestCase::MacAssoc, this)); - } - Config::Connect("/NodeList/1/DeviceList/*/Phy/State/RxOk", - MakeCallback(&OcbWifiMacTestCase::PhyRxOkTrace, this)); - Config::Connect("/NodeList/1/DeviceList/*/Phy/State/Tx", - MakeCallback(&OcbWifiMacTestCase::PhyTxTrace, this)); -} - -/** - * - * static-node:0 <---- mobile-node:1 - * * ------ 350m ------- * - * - * the node transmit range is less than 150m - * - * Ap+Sta mode vs Adhoc mode vs Ocb mode - * first test the time point when the stationary node is - * an AP and the mobile node is a Sta - * then test when one Ad-hoc node and another Ad-hoc node - * last test when one OCB node and another OCB node - */ -void -OcbWifiMacTestCase::DoRun() -{ - std::cout << "test time point for Ap-Sta mode" << std::endl; - PreRandomConfiguration(); - nodes = NodeContainer(); - nodes.Create(2); - Ptr static_node = nodes.Get(0); - Ptr mobile_node = nodes.Get(1); - ConfigureApStaMode(static_node, mobile_node); - PostDeviceConfiguration(static_node, mobile_node); - Simulator::Stop(Seconds(71.0)); - Simulator::Run(); - Simulator::Destroy(); - NS_TEST_ASSERT_MSG_LT( - phyrx_time, - macassoc_time, - "In Sta mode with AP, you cannot associate until receive beacon or AssocResponse frame"); - NS_TEST_ASSERT_MSG_LT(macassoc_time, - phytx_time, - "In Sta mode with AP, you cannot send data packet until associate"); - // Are these position tests redundant with time check tests? - // NS_TEST_ASSERT_MSG_GT ((phyrx_pos.x - macassoc_pos.x), 0.0, ""); - // actually macassoc_pos.x - phytx_pos.x is greater than 0 - // however associate switch to send is so fast with less than 100ms - // and in our mobility model that every 0.1s update position, - // so turn out to be that macassoc_pos.x - phytx_pos.x is equal to 0 - // NS_TEST_ASSERT_MSG_GT ((macassoc_pos.x - phytx_pos.x), 0.0, ""); - - std::cout << "test time point for Adhoc mode" << std::endl; - PreRandomConfiguration(); - nodes = NodeContainer(); - nodes.Create(2); - static_node = nodes.Get(0); - mobile_node = nodes.Get(1); - ConfigureAdhocMode(static_node, mobile_node); - PostDeviceConfiguration(static_node, mobile_node); - Simulator::Stop(Seconds(71.0)); - Simulator::Run(); - Simulator::Destroy(); - // below test assert will fail, because AdhocWifiMac has not implement state machine. - // if someone takes a look at the output in adhoc mode and in Ocb mode - // he will find these two outputs are almost same. - // NS_TEST_ASSERT_MSG_LT (phyrx_time, macassoc_time, "In Adhoc mode, you cannot associate until - // receive beacon or AssocResponse frame" ); NS_TEST_ASSERT_MSG_LT (macassoc_time, phytx_time, - // "In Adhoc mode, you cannot send data packet until associate" ); NS_TEST_ASSERT_MSG_GT - // ((phyrx_pos.x - macassoc_pos.x), 0.0, ""); - // below test assert result refer to Ap-Sta mode - // NS_TEST_ASSERT_MSG_GT ((macassoc_pos.x - phytx_pos.x), 0.0, ""); - - std::cout << "test time point for Ocb mode" << std::endl; - PreRandomConfiguration(); - nodes = NodeContainer(); - nodes.Create(2); - static_node = nodes.Get(0); - mobile_node = nodes.Get(1); - ConfigureOcbMode(static_node, mobile_node); - PostDeviceConfiguration(static_node, mobile_node); - Simulator::Stop(Seconds(71.0)); - Simulator::Run(); - Simulator::Destroy(); - NS_TEST_ASSERT_MSG_EQ(macassoc_time.GetNanoSeconds(), - 0, - "In Ocb mode, there is no associate state machine"); - NS_TEST_ASSERT_MSG_LT(phytx_time, - phyrx_time, - "before mobile node receives frames from far static node, it can send " - "data packet directly"); - NS_TEST_ASSERT_MSG_EQ(macassoc_pos.x, 0.0, ""); - NS_TEST_ASSERT_MSG_GT((phytx_pos.x - phyrx_pos.x), 0.0, ""); -} - -void -OcbWifiMacTestCase::PreRandomConfiguration() -{ - // Assign a seed and run number, and later fix the assignment of streams to - // WiFi random variables, so that the first backoff used is zero slots - RngSeedManager::SetSeed(1); - RngSeedManager::SetRun(17); - // the WiFi random variables is set in PostDeviceConfiguration method. -} - -/** - * \ingroup wave-test - * \ingroup tests - * - * \brief Ocb Test Suite - */ -class OcbTestSuite : public TestSuite -{ - public: - OcbTestSuite(); -}; - -OcbTestSuite::OcbTestSuite() - : TestSuite("wave-80211p-ocb", UNIT) -{ - // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER - AddTestCase(new OcbWifiMacTestCase, TestCase::QUICK); -} - -// Do not forget to allocate an instance of this TestSuite -static OcbTestSuite ocbTestSuite; ///< the test suite diff --git a/src/wifi/helper/wifi-mac-helper.cc b/src/wifi/helper/wifi-mac-helper.cc index 54009aeed..40079a773 100644 --- a/src/wifi/helper/wifi-mac-helper.cc +++ b/src/wifi/helper/wifi-mac-helper.cc @@ -70,9 +70,9 @@ WifiMacHelper::Create(Ptr device, WifiStandard standard) const Ptr queueScheduler = m_queueScheduler.Create(); mac->SetMacQueueScheduler(queueScheduler); - // WaveNetDevice stores PHY entities in a different member than WifiNetDevice, hence - // GetNPhys() would return 0. We have to attach a protection manager and an ack manager - // to the unique instance of frame exchange manager anyway + // WaveNetDevice (through ns-3.38) stores PHY entities in a different member than WifiNetDevice, + // hence GetNPhys() would return 0. We have to attach a protection manager and an ack manager to + // the unique instance of frame exchange manager anyway for (uint8_t linkId = 0; linkId < std::max(device->GetNPhys(), 1); ++linkId) { auto fem = mac->GetFrameExchangeManager(linkId);