From b6f22f62e3683ca3a05ec50614f592efeb93af11 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 28 Sep 2018 06:49:25 -0700 Subject: [PATCH 1/8] Change file format from dos to unix --- README | 286 ++-- doc/simple-wireless.rst | 1038 +++++++------- examples/directional_test.cc | 882 ++++++------ examples/error_model_test.cc | 746 +++++----- examples/fixed_contention_test.cc | 800 +++++------ examples/mixed_directional_network.cc | 642 ++++----- examples/multiple_interface_example.cc | 580 ++++---- examples/queue_test.cc | 824 +++++------ examples/wscript | 96 +- model/drop-head-queue.cc | 318 ++--- model/drop-head-queue.h | 162 +-- model/priority-queue.cc | 386 +++--- model/priority-queue.h | 242 ++-- model/simple-wireless-channel.cc | 896 ++++++------ model/simple-wireless-channel.h | 286 ++-- model/simple-wireless-net-device.cc | 1754 ++++++++++++------------ model/simple-wireless-net-device.h | 724 +++++----- wscript | 46 +- 18 files changed, 5354 insertions(+), 5354 deletions(-) diff --git a/README b/README index 6832e07..82f08a7 100644 --- a/README +++ b/README @@ -1,143 +1,143 @@ -ll-simple-wireless has the following contents: -============================================== -ll-simple-wireless/: - /doc - /examples - /model - wscript - README - -ll-simple-wireless/doc: - simple-wireless.rst - -ll-simple-wireless/examples: - directional_test.cc - error_model_test.cc - fixed_contention_test.cc - mixed_directional_network.cc - multiple_interface_example.cc - queue_test.cc - wscript - -ll-simple-wireless/model: - drop-head-queue.cc - drop-head-queue.h - priority-queue.cc - priority-queue.h - simple-wireless-channel.cc - simple-wireless-channel.h - simple-wireless-net-device.cc - simple-wireless-net-device.h - - -*** Please refer to the file simple-wireless.rst in the /doc folder for more information about this model. - -Installation Instructions -============================================================ -(assumes NS3 is already installed; see below for NS3/DCE installation instructions) - -1. Modify the NS3 wscript file to include simple-wireless in the build - - For example, if using DCE add the following line at ~line 96 in dce/source/ns-3-dce/wscript - ns3waf.check_modules(conf, ['simple-wireless'], mandatory = False) - -2. Install the simple wireless in NS3 source using one of these methods: - a) Copy the files directly to the NS3 directory: /src/simple-wireless - OR - b) Use a softlink to your location of ll-simple-wireless to create the NS3 directory /src/simple-wireless - - NOTE: the directory from the tar file is named ll_simple_wireless but it is installed in NS3 as simple-wireless - -3. Add the simple-wireless as a module in the wscript used to build your NS3 scenario. - - For example: - def configure(conf): - ns3waf.check_modules(conf, ['core', 'internet', 'simple-wireless'], mandatory = True) - - def build(bld): - bld.build_a_script('dce', needed = ['core', 'internet', 'dce', 'mobility', 'simple-wireless'], - target='bin/my_test_script', - cxxflags=['-std=c++0x'], - source=[ my_test_script.cc'] ) - -4. Rebuild NS3 being sure to enable examples if you want to run the example models provided with the Simple Wireless model - -Miscellaneous Notes -=========================================================== -* The Simple Wireless model has been run with NS3.22/DCE1.5, NS3.21/DCE1.4 and NS3.20/DCE1.3 -* The PriorityQueue uses libpcap to classify control packets so this must be installed to use priority queues. - -Installation Instructions for NS3/DCE -============================================================ -The Simple Wireless model works in NS3.20/DCE1.3, NS3.21/DCE1.4 and NS3.22/DCE1.5. -If you have any of these versions currently installed you do not need to install a different version. -The instructions below are for installing NS3.22 and DCE1.5 release but it is not necessary to install -these if you have an earlier, compatible version already installed. - -NOTE: It is assumed that DCE will be installed at ~/dce - -1. Install Bake from your home directory - hg clone http://code.nsnam.org/bake bake - -2. Set path variables - Add the following lines to .profile: - BAKE_HOME="$HOME/bake" - PATH="$PATH:$BAKE_HOME" - PYTHONPATH="/usr/lib/python2.7:$BAKE_HOME" - - Execute the .profile: - . .profile - -3. Increase file descriptor limit to 2048 - To check the current value: $ ulimit –n - To change the current value: $ ulimit –n 2048 - -4. Create a directory for DCE - mkdir dce - -5. Configure, download and build DCE 1.5 (note: this automatically includes ns3.22) - cd dce - bake.py configure -e dce-ns3-1.5 - bake.py download [See note below] - bake.py build - - During download and build, you may run into missing packages. If so, install them using - sudo apt-get install xxxx (where xxxx is the name of the missing package) - Then after installing re-run the download or build command before proceeding to the next step. - - If the gccxml package is missing, the build may complain about pybindgen instead. Install gccxml and the pybindgen problem will probably go away. - - To diagnose a build failure, you may need to use the –vvv flag to get more information: - bake.py build -vvv - - NOTE: Some of the package names may not match what the dce install says is missing. Examples: - DCE name Actual Install Name - -------------------- ------------------- - pybindgen-0.17.0.868 bzr - qt4 qt4-dev-tools - lib_debug libc6-dbg - pygraphviz python-pygraphviz - pygoocanvas python-pygoocanvas - - -********************************************************************************************************************************** -Distribution Statement ----------------------- - - Copyright (C) 2015 Massachusetts Institute of Technology - All rights reserved. - - 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 - -********************************************************************************************************************************** +ll-simple-wireless has the following contents: +============================================== +ll-simple-wireless/: + /doc + /examples + /model + wscript + README + +ll-simple-wireless/doc: + simple-wireless.rst + +ll-simple-wireless/examples: + directional_test.cc + error_model_test.cc + fixed_contention_test.cc + mixed_directional_network.cc + multiple_interface_example.cc + queue_test.cc + wscript + +ll-simple-wireless/model: + drop-head-queue.cc + drop-head-queue.h + priority-queue.cc + priority-queue.h + simple-wireless-channel.cc + simple-wireless-channel.h + simple-wireless-net-device.cc + simple-wireless-net-device.h + + +*** Please refer to the file simple-wireless.rst in the /doc folder for more information about this model. + +Installation Instructions +============================================================ +(assumes NS3 is already installed; see below for NS3/DCE installation instructions) + +1. Modify the NS3 wscript file to include simple-wireless in the build + + For example, if using DCE add the following line at ~line 96 in dce/source/ns-3-dce/wscript + ns3waf.check_modules(conf, ['simple-wireless'], mandatory = False) + +2. Install the simple wireless in NS3 source using one of these methods: + a) Copy the files directly to the NS3 directory: /src/simple-wireless + OR + b) Use a softlink to your location of ll-simple-wireless to create the NS3 directory /src/simple-wireless + + NOTE: the directory from the tar file is named ll_simple_wireless but it is installed in NS3 as simple-wireless + +3. Add the simple-wireless as a module in the wscript used to build your NS3 scenario. + + For example: + def configure(conf): + ns3waf.check_modules(conf, ['core', 'internet', 'simple-wireless'], mandatory = True) + + def build(bld): + bld.build_a_script('dce', needed = ['core', 'internet', 'dce', 'mobility', 'simple-wireless'], + target='bin/my_test_script', + cxxflags=['-std=c++0x'], + source=[ my_test_script.cc'] ) + +4. Rebuild NS3 being sure to enable examples if you want to run the example models provided with the Simple Wireless model + +Miscellaneous Notes +=========================================================== +* The Simple Wireless model has been run with NS3.22/DCE1.5, NS3.21/DCE1.4 and NS3.20/DCE1.3 +* The PriorityQueue uses libpcap to classify control packets so this must be installed to use priority queues. + +Installation Instructions for NS3/DCE +============================================================ +The Simple Wireless model works in NS3.20/DCE1.3, NS3.21/DCE1.4 and NS3.22/DCE1.5. +If you have any of these versions currently installed you do not need to install a different version. +The instructions below are for installing NS3.22 and DCE1.5 release but it is not necessary to install +these if you have an earlier, compatible version already installed. + +NOTE: It is assumed that DCE will be installed at ~/dce + +1. Install Bake from your home directory + hg clone http://code.nsnam.org/bake bake + +2. Set path variables + Add the following lines to .profile: + BAKE_HOME="$HOME/bake" + PATH="$PATH:$BAKE_HOME" + PYTHONPATH="/usr/lib/python2.7:$BAKE_HOME" + + Execute the .profile: + . .profile + +3. Increase file descriptor limit to 2048 + To check the current value: $ ulimit –n + To change the current value: $ ulimit –n 2048 + +4. Create a directory for DCE + mkdir dce + +5. Configure, download and build DCE 1.5 (note: this automatically includes ns3.22) + cd dce + bake.py configure -e dce-ns3-1.5 + bake.py download [See note below] + bake.py build + + During download and build, you may run into missing packages. If so, install them using + sudo apt-get install xxxx (where xxxx is the name of the missing package) + Then after installing re-run the download or build command before proceeding to the next step. + + If the gccxml package is missing, the build may complain about pybindgen instead. Install gccxml and the pybindgen problem will probably go away. + + To diagnose a build failure, you may need to use the –vvv flag to get more information: + bake.py build -vvv + + NOTE: Some of the package names may not match what the dce install says is missing. Examples: + DCE name Actual Install Name + -------------------- ------------------- + pybindgen-0.17.0.868 bzr + qt4 qt4-dev-tools + lib_debug libc6-dbg + pygraphviz python-pygraphviz + pygoocanvas python-pygoocanvas + + +********************************************************************************************************************************** +Distribution Statement +---------------------- + + Copyright (C) 2015 Massachusetts Institute of Technology + All rights reserved. + + 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 + +********************************************************************************************************************************** diff --git a/doc/simple-wireless.rst b/doc/simple-wireless.rst index 8fca45c..468bd5d 100644 --- a/doc/simple-wireless.rst +++ b/doc/simple-wireless.rst @@ -1,519 +1,519 @@ -.. include:: replace.txt -.. highlight:: cpp - -SimpleWireless --------------- - -|ns3| nodes can contain a collection of NetDevice objects, much like an actual -computer contains separate interface cards for Ethernet, Wifi, Bluetooth, etc. -This chapter describes the |ns3| SimpleWirelessNetDevice and related models. -By adding SimpleWirelessNetDevice objects to |ns3| nodes, one can create models -for wireless infrastructure and ad hoc networks. - -Overview of the model -********************* - -SimpleWireless models a wireless network interface controller that is -not based on any specific protocol. Instead, it provides a wireless interface that -is simple in protocol but still allows the user to configure it with useful features. -We will go into more detail below on these features but in brief, -|ns3| SimpleWireless provides models for these aspects of wireless communications: - -* propagation delay -* transmission delay based on the channel data rate (MIT LL) -* support for specifying transmission range -* support for multiple types of error including constant, range based, and stochastic (MIT LL) -* queue support with user configurable queue method (MIT LL) -* queueing of packets to limit the data rate (MIT LL) -* support for differentiating control and data traffic (MIT LL) -* pcap capture of packets sent and received (MIT LL) -* support for simulated directional networking through fixed neighbor lists (MIT LL) -* support for fixed contention (MIT LL) - - -The items marked with (MITLL) are items that have been added by MIT Lincoln Laboratory to -the basic simple wireless model developed by Tom Henderson (available at -http://code.nsnam.org/tomh/ns-3-simple-wireless) - -SimpleWireless does not include MAC protocols and does not model interference. - -In |ns3|, nodes can have multiple SimpleWirelessNetDevices on separate channels, and the -SimpleWirelessNetDevice can coexist with other device types. Presently, however, there is -no model for cross-channel interference or coupling. - -The source code for the SimpleWireless should be installed in the directory -``src/simplewireless``. - -The implementation provides two levels of models: - -* the PHY layer models (SimpleWirelessChannel) -* the device layer model (SimpleWirelessNetDevice) - -Change Log -======================= -**Version 0.3.3** -* Added MacTx and MacRx traces to net-device so that simple wireless has this -trace that exists in MAC models -* Fix bug in net-device which switches the source and destination MAC addresses -during enqueing. Bug only affected scenarios in which queues are NOT used. -* Modify the queue latency trace in net-device to take a pointer to the packet -* Modify net-device to call queue latency trace before stripping the Ethernet -header from packet so that information from the header is available in the -trace for users to access - -**Version 0.3.2** -* Modify implementation for directional networks so the packets are queued -at the device for each directional neighbor that is a destination for the -packet being sent. This includes support for sending unicast such that the -packet is only queued for that one directional neighbor. -* Modify the contention implementation so that the node itself is included -in the count of nodes sharing the bandwidth and also add support for -directional networks. - -**Version 0.3.1** -* Fix bug in drop head queue which can cause a segmentation fault. -Call to DropHeadQueue::DoDequeue was replaced with call to Dequeue method -of the base class so that the accounting of # of packets in the queue is -correct. - -**Version 0.3** -* Add stochastic error model -* Add PhyRxBegin and PhyRxEnd traces to SimpleWirelessNetDevice -* Add source Ethernet address to the SimpleWirelessNetDevice traces (destination Ethernet -address and protocol were already provided to the traces) - -**Version 0.2** -* Add support for simulated directional networking through fixed neighbor lists -* Add support for contention based transmisstion -* Fix bug in Priority Queue which caused segfault when running DCE in optimized mode -* Fix memory leak in Priority Queue in Classify function - -**Version 0.1** -* Implement transmission delay based on the channel data rate -* Implement support for specifying transmission range -* Implement multiple types of error including constant and range based error curves -* Create two new queue types (DropHead and Priority Queue) -* Implement support for user selectable queue method limit the data rate -* Add support for differentiating control and data traffic -* Add pcap capture of packets sent and received - - -SimpleWirelessChannel -======================= - -The SimpleWirelessChannel models the wireless channel used to transmit packets and this -includes the following features: -- Propogation Delay - calculated using packet size and spped of light -- Transmission Delay - calculated using packet size and the channel's data rate -- Transmission Range - user specified -- Packet Error - determined from the user configured range and error model - -When the SimpleWirelessChannel receives a packet from the upper layer to transmit, it -iterates over all the devices attached to channel to determine if it should send -the packet to each device. - -First, the channel looks to see if the device is attached to the node itself. -The channel does not send the packet to the device that is attached to -the node itself (preventing the node from receiving its own packets). - -Second, if directional networking is being used, the channel checks if the device -is attached to the destination node of the packet. If not then the packet is not -sent to the device. - -Next, the channel checks if stochastic error is being used and if so whether or not the -link between the sender and destination is currently on or off. If off, the packet is not -sent to the destiation node device. - -Next, the channel checks if the destination node is within the maximum transmission range -of the sending node based on distance between the sender and the destination. -If the destination node is out of range then the packet is not sent to the destination -node device. - -Finally, the channel checks if the packet would be in error if it were to be transmitted -to the device. This decision is based on the configured error model as follows: -+ If the error model is CONSTANT, then the packet is in error if a randomly -selected error value exceeds the configured error rate. Note that the error rate -is per packet and based on the size of the packet. -+ If the error model is PER_CURVE, then the packet error is determined using the -packet error rate curve specified by the user. The distance between the sender -and the receive is used to pick an error value from this curve, linearly interpolating -between points on the curve. If a random selected value exceeds this error rate, then -the packet is considered in error and is not sent to the device. This too is packet based -error rate. -+ If the error model is STOCHASTIC, then there is no packet error. The decision on handling -of packets (sent or not sent) is made earlier when the state of the link is checked. - -If a device passes all tests (the device is not on the sending node, the device is -in view of the sending, the link to the device is not in the OFF state if STOCHASTIC error -model is being use, the device is in range and the packet error rate is below the threshold) -then a reception event is scheduled for the destination device. - -This process is repeated for all the devices on the channel. - -The SimpleWirelessChannel is only involved on the send side and has no functions -associated with receiving packets. - -It is important to note that packets that are in error are NOT sent. In other words, the -decision is made on the send side and not the receive side. This minimizes the overhead -of a simulation because there are no resources spent on transmitting and receiving a packet -that ultimately will fail reception due to errors. However, this does impede the modeling -of packet interference if it were to be implemented in the SimpleWireless model. Since that -is currently not implemented, it is perfectly fine to drop packets at the source and conserve -simulation resources. - - -SimpleWirelessNetDevice -======================= -The SimpleWirelessNetDevice models the wireless device on the interface of a node and -includes the following features: -- Queue support with user configurable queue method -- Transmission limited by data rate -- Support for differentiating control and data traffic -- Support for pcap capture of packets sent and received -- Support for simulated directional networking through fixed neighbor lists -- Support for fixed contention - -The SimpleWirelessNetDevice supports the use of queue in which to hold packets for transmission. -When queues are used, their purpose is essentially to force a data rate for the device. -Queues are always FIFO but the drop method of the queue is configurable to be either -drop head or drop tail. In addition, there is support for priority queue which implements -separate control and data queues, each of which can be set independently as drop head or drop tail. -When a priority queue is used, a pcap string filter is used to differentiate control and -data packets. Note that it is possible to use no queuing which is the behavior of the original -simple wireless model. - -When queues are used, the SimpleWirelessNetDevice maintains a transmit state flag to indicate -if the device is currently transmitting or is idle. When the SimpleWirelessNetDevice receives -a packet from the upper layer to transmit, it places the packet into the queue and if currently -idle, immediately transmits the packet and sets the flag to busy. After the tranmission -is complete, it sets the flag back to idle and checks the queue to see if there is another -packet waiting to be sent. The transmission time of a packet is based on the packet size -and the data rate (configurable). - -Note that the busy state is set at the net device and not at the channel. As indicated above, -the channel does not actually send any packets that would be delivered in error at the -destination node. The device does not know about this and will be considered "busy" for the -amount of time required to transmit the packet even it the channel does not actually send it. - -When queues are not used, the SimpleWirelessNetDevice immediately sends a packet when it -receives it and does not maintain a busy flag. - -The SimpleWirelessNetDevice implements a simple version of directional networks with -the use of a "neighbor list" which is used to identify the nodes that are in view of the -node as though there was a directional antenna. If this feature is disabled then all nodes -are within view of the node. If this feature is enabled, then only the nodes listed in -the node's neighbor list are considered in view of the node. When directional networking -is enabled for the device, the SimpleWirelessNetDevice enqueues outbound packets as follows: -- A broadcast packet is duplicated and enqueued once for each directional neighbor. -- A unicast packet is enqueued only if the destination is a directional neighbor. - -Note that when the directional network feature is enabled, packets are enqueued for a specific -destination so that when the SimpleWirelessChannel gets the packet, there will be only one -destination device to which the packet will be sent. This differs from the case without a -directional network when only one packet is enqueued. As an example, suppose a node has -3 neighbors. If directional networks are enabled, the device will enqueue 3 packets -- 1 for each -destination. When the channel receives the packet to send, it will only deliver it to one -device on that destination node. If directional networks are not enabled, the device enqueues -one packet. When the channel receives the packet to send, it will deliver it to the three -devices on each of its neighbor nodes. - -The simple wireless model also implements a feature to account for contention. This is -called "fixed contention" feature. The model counts up the number of neigbor nodes that could -cause contention on the channel and reduces the data rate available to a sending node -based on this count. Thus the data rate becomes data rate/# neighbors. -The device uses this new data rate when it determines the transmit time used for setting -how long to keep the busy flag for the device set and for delay associated with transmission. -The manner in which the number of neighbors is counted is as follows: -the count first includes the node itself. Then when the channel transmits -a packet, it loops over all devices on the channel. During this loop the number of destination -devices that are within the user specificed contention range are counted and this is the count -that is used for the next time that a packet arrives on the device to be queued (or sent). -This the information is not the exact number of nodes within contention range at the instant -when a packet is queued but is based on the previous transmit. - -The SimpleWirelessNetDevice supports pcap tracing of packets that are sent and -received by the device. - -The SimpleWirelessNetDevice also supports a receive error model. - -SimpleWireless Model Configuration Items -**************************************** -The following items are configurable on the Simple Wireless Channel - -MaxRange -+ description: Error model used on the send side -+ units: --- -+ default: CONSTANT -+ possible values: CONSTANT, PER_CURVE, or STOCHASTIC - -ErrorModel -+ description: Error model used on the send side -+ units: --- -+ default: CONSTANT -+ possible values: CONSTANT, PER_CURVE, or STOCHASTIC - -ErrorRate -+ description: Error rate associated with the CONSTANT error model. Not used if ErrorModel is set to PER_CURVE. -+ units: --- -+ default: 0.0 -+ possible values: 0.0 to 1.0 inclusive - -AvgLinkUpDuration -+ description: Average duration of link ON state for STOCHASTIC error model. -+ units: TimeValue -+ default: 10000 usec -+ possible values: any TimeValue - -AvgLinkDownDuration -+ description: Avergage duration of link OFF state for STOCHASTIC error model. -+ units: TimeValue -+ default: 100 usec -+ possible values: any TimeValue - -EnableFixedContention -+ description: Flag used to enabled or disable the Fixed Contention feature -+ units: --- -+ default: false -+ possible values: true/false - -FixedContentionRange -+ description: Range used to count the number of neighbors for fixed contention. - If fixed contention is enabled and this value is 0, then uses the value set for MaxRange. -+ units: meters -+ default: 0 -+ possible values: any value > 0 - -PER Curve -+ description: Pairs of used to build the packet error rate (PER) curve. -+ units: meters,error -+ default: --- -+ possible values: distance: > 0 and error: 0.0-1.0 - - -+ description: -+ units: -+ default: -+ possible values: - - -The following items are configurable on the Simple Wireless Device - -ReceiveErrorModel -+ description: Error model used on the receive side. -+ units: --- -+ default: none -+ possible values: --- - -DataRate -+ description: Datarate to use for the device. -+ units: data rate -+ default: 1000000b/s -+ possible values: --- - -FixedNeighborListEnabled -+ description: Flag used to enabled or disable the simulated directional network with fixed neighbor list feature -+ units: --- -+ default: false -+ possible values: true/false - -Fixed Neighbor List -+ description: Node ids to add to the fixed neighbor list when simulating directional networks with neighbor lists. -+ units: node id -+ default: none -+ possible values: any value >= 0 - -TxQueue -+ description: Type of queuing to use if any. -+ units: --- -+ default: NULL (no queue) -+ possible values: NULL, DropTailQueue, DropHeadQueue, PriorityQueue - - -The following items are configurable on the Queues - -Mode -+ description: Drop mode for the queue. - If PACKETS, then packets are dropped from the queue when it is at capacity without regard to size. - If BYTES, then the size of the packets is considered when dropping packets. -+ units: -+ default: QUEUE_MODE_PACKETS -+ possible values: QUEUE_MODE_PACKETS or QUEUE_MODE_BYTES - -MaxPackets -+ description: Maximum number of packets to allow in the queue. Used when mode is QUEUE_MODE_PACKETS. -+ units: --- -+ default: 100 -+ possible values: any value > 0 - -MaxBytes -+ description: Maximum number of bytes to allow in the queue. Used when mode is QUEUE_MODE_BYTES. -+ units: --- -+ default: 6,553,500 -+ possible values: any value > 0 - -ControlPacketClassifier -+ description: String used to classify control packets using a pcap filter when Priority Queues are used. - Examples: - To classify packets based on port: StringValue ("port 698") - To classify packets based on ether type: StringValue ("ether proto 0x88B5") -+ units: --- -+ default: none -+ possible values: any string - - -Using the SimpleWireless Model -****************************** -To use the SimpleWireless model, users need to configure in the following steps: - -1) Create the SimpleWirelessChannel - Ptr phy = CreateObject (); - -2) Configure the SimpleWirelessChannel - a) Set the range for the channel - phy->SetDeviceAttribute ("MaxRange", DoubleValue (txRange)); - - Default value can be set as follows but this must be done BEFORE creating the channel: - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (txRange)); - - b) Set the error model type - phy->setErrorModelType(CONSTANT); - - c) If the error model type is CONSTANT, set the error rate - phy->setErrorRate(errorRate); - - d) If the error model type is PER_CURVE, build the error curve by calling the function - phy->addToPERmodel(0.0, 0.0); - phy->addToPERmodel(10.0, 0.0); - phy->addToPERmodel(20.0, 0.0); - phy->addToPERmodel(30.0, 0.007); - phy->addToPERmodel(40.0, 0.1); - phy->addToPERmodel(50.0, 0.4); - phy->addToPERmodel(60.0, 0.7); - phy->addToPERmodel(70.0, 0.9); - - e) If the error model type is STOCHASTIC, set the up and down durations - phy->SetAttribute("AvgLinkUpDuration", TimeValue (MicroSeconds (errorUpAvg))); - phy->SetAttribute("AvgLinkDownDuration", TimeValue (MicroSeconds (errorDownAvg))); - - f) If using the fixed contention feature, enable the feature - phy->EnableFixedContention(); - - g) If using the fixed contention feature with a non-default value for the contention range (default value is channel's transmission range) set the contention range value - phy->SetFixedContentionRange(contentionRange); - -3) On EACH node, create SimpleWirelessNetDevice - Ptr simpleWireless = CreateObject (); - -4) Configure the SimpleWirelessChannel - a) Set the channel - simpleWireless->SetChannel(phy); - - b) Set the node - simpleWireless->SetNode(node); - - c) Set the data rate - simpleWireless->SetDataRate(DataRate ("1Mb/s")) - - Default value can be set as follows but this must be done BEFORE creating the devices: - Config::SetDefault ("ns3::SimpleWirelessNetDevice::DataRate", DataRateValue (DataRate (dataRate))); - - d) Set the address - simpleWireless->SetAddress(Mac48Address::Allocate ()); - - e) Create a queue and set this on the device. For example: - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - - The example model queue_test.cc show how to configure each type of queue - - f) Add the device to the node and device container - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - g) Enable pcap capture if desired: - std::ostringstream stringStream; - stringStream << "scenario_name_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - -5) If being use, enable directional networking and pass a list of neighbors - This must be done AFTER adding all the devices to each node - NOTE that the code checks the return code from the call to AddDirectionalNeighbors - - Example: In this example, Node 0 has directional neighbors 1, 3, 4, 7, 10, and 11 - Ptr dev0 = devices.Get(0); - Ptr swDev0 = DynamicCast(dev0); - simpleWireless->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - // build a map of directional neighbor nodes and mac addresses - std::map nbrSet; - for ( NetDeviceContainer::Iterator dIt = devices.Begin(); dIt != devices.End(); ++dIt) - { - Ptr node = (*dIt)->GetNode(); - uint32_t id = node->GetId(); - // in this example, specific node ids are directional neighbors - if ( id == 1 || id == 3 || id == 4 || id == 7 || id == 10 || id == 11 ) - { - // Get mac addr of node and add to map - Address addr = (*dIt)->GetAddress(); - Mac48Address macAddr = Mac48Address::ConvertFrom (addr); - nbrSet.insert(std::pair(id, macAddr)); - std::cout << "Adding node " << id << " with mac address " << macAddr<< std::endl; - } - } - // Now add to dev on node 0 - if (!swDev0->AddDirectionalNeighbors(nbrSet)) - { - NS_FATAL_ERROR ("Call to AddDirectionalNeighbors failed. Please enabled directional neighbors."); - return 0; - } - - There are also functions to allow dynamic simulated directional networking through fixed neighbor lists - by adding and removing neighbor to/from the list over time. This can be done using calls to the methods: - AddDirectionalNeighbor - DeleteDirectionalNeighbor - - -6) Initial the Stochastic error model. This must be done AFTER adding all the devices and does nothing if not running STOCHASTIC error model - phy->InitStochasticModel(); - -SimpleWirelessNetDevice Model Traces -************************************ -The following traces are available for the device: - -* PhyTxBegin - called when the device sends the packet to the channel for Tx - -* PhyRxBegin - called when a packet has begun being received by the device - -* PhyRxEnd - called when a packet has been completely received by the device - -* PhyRxDrop - called if a packet is dropped by the device during receive - -* PromiscSniffer - called for pcap capture of packets; captures on send and receive - -* QueueLatency - called when a packet is dequeued for transmission - -* MacTx - called when a packet has been received from higher layers and is being queued for transmission - -* MacRx - called when a packet has been received over the air and is being forwarded up the local protocol stack - -SimpleWirelessChannel Model Traces -************************************ -NONE - -SimpleWireless Examples -************************************ -The examples directory has the following examples which show how to configure the -Simple Wireless model and use the features that it has. - -directional_test.cc Provides an example of how to use the simulated directional network feature - -error_model_test.cc Provides an example of how to use the error models added to the send side (CONSTANT, PER_CURVE and STOCHASTIC) - -fixed_contention_test.cc Provides an example of how to use the fixed contention feature - -multiple_interface_example.cc Provides a simple 2 node example of how to configure multiple interfaces on a node - -mixed_directional_network.cc Provides a more complex example of multiple interfaces per node in combination with the simulated directional networks. - -queue_test.cc Provides examples of how to configure each type of queuing. - +.. include:: replace.txt +.. highlight:: cpp + +SimpleWireless +-------------- + +|ns3| nodes can contain a collection of NetDevice objects, much like an actual +computer contains separate interface cards for Ethernet, Wifi, Bluetooth, etc. +This chapter describes the |ns3| SimpleWirelessNetDevice and related models. +By adding SimpleWirelessNetDevice objects to |ns3| nodes, one can create models +for wireless infrastructure and ad hoc networks. + +Overview of the model +********************* + +SimpleWireless models a wireless network interface controller that is +not based on any specific protocol. Instead, it provides a wireless interface that +is simple in protocol but still allows the user to configure it with useful features. +We will go into more detail below on these features but in brief, +|ns3| SimpleWireless provides models for these aspects of wireless communications: + +* propagation delay +* transmission delay based on the channel data rate (MIT LL) +* support for specifying transmission range +* support for multiple types of error including constant, range based, and stochastic (MIT LL) +* queue support with user configurable queue method (MIT LL) +* queueing of packets to limit the data rate (MIT LL) +* support for differentiating control and data traffic (MIT LL) +* pcap capture of packets sent and received (MIT LL) +* support for simulated directional networking through fixed neighbor lists (MIT LL) +* support for fixed contention (MIT LL) + + +The items marked with (MITLL) are items that have been added by MIT Lincoln Laboratory to +the basic simple wireless model developed by Tom Henderson (available at +http://code.nsnam.org/tomh/ns-3-simple-wireless) + +SimpleWireless does not include MAC protocols and does not model interference. + +In |ns3|, nodes can have multiple SimpleWirelessNetDevices on separate channels, and the +SimpleWirelessNetDevice can coexist with other device types. Presently, however, there is +no model for cross-channel interference or coupling. + +The source code for the SimpleWireless should be installed in the directory +``src/simplewireless``. + +The implementation provides two levels of models: + +* the PHY layer models (SimpleWirelessChannel) +* the device layer model (SimpleWirelessNetDevice) + +Change Log +======================= +**Version 0.3.3** +* Added MacTx and MacRx traces to net-device so that simple wireless has this +trace that exists in MAC models +* Fix bug in net-device which switches the source and destination MAC addresses +during enqueing. Bug only affected scenarios in which queues are NOT used. +* Modify the queue latency trace in net-device to take a pointer to the packet +* Modify net-device to call queue latency trace before stripping the Ethernet +header from packet so that information from the header is available in the +trace for users to access + +**Version 0.3.2** +* Modify implementation for directional networks so the packets are queued +at the device for each directional neighbor that is a destination for the +packet being sent. This includes support for sending unicast such that the +packet is only queued for that one directional neighbor. +* Modify the contention implementation so that the node itself is included +in the count of nodes sharing the bandwidth and also add support for +directional networks. + +**Version 0.3.1** +* Fix bug in drop head queue which can cause a segmentation fault. +Call to DropHeadQueue::DoDequeue was replaced with call to Dequeue method +of the base class so that the accounting of # of packets in the queue is +correct. + +**Version 0.3** +* Add stochastic error model +* Add PhyRxBegin and PhyRxEnd traces to SimpleWirelessNetDevice +* Add source Ethernet address to the SimpleWirelessNetDevice traces (destination Ethernet +address and protocol were already provided to the traces) + +**Version 0.2** +* Add support for simulated directional networking through fixed neighbor lists +* Add support for contention based transmisstion +* Fix bug in Priority Queue which caused segfault when running DCE in optimized mode +* Fix memory leak in Priority Queue in Classify function + +**Version 0.1** +* Implement transmission delay based on the channel data rate +* Implement support for specifying transmission range +* Implement multiple types of error including constant and range based error curves +* Create two new queue types (DropHead and Priority Queue) +* Implement support for user selectable queue method limit the data rate +* Add support for differentiating control and data traffic +* Add pcap capture of packets sent and received + + +SimpleWirelessChannel +======================= + +The SimpleWirelessChannel models the wireless channel used to transmit packets and this +includes the following features: +- Propogation Delay - calculated using packet size and spped of light +- Transmission Delay - calculated using packet size and the channel's data rate +- Transmission Range - user specified +- Packet Error - determined from the user configured range and error model + +When the SimpleWirelessChannel receives a packet from the upper layer to transmit, it +iterates over all the devices attached to channel to determine if it should send +the packet to each device. + +First, the channel looks to see if the device is attached to the node itself. +The channel does not send the packet to the device that is attached to +the node itself (preventing the node from receiving its own packets). + +Second, if directional networking is being used, the channel checks if the device +is attached to the destination node of the packet. If not then the packet is not +sent to the device. + +Next, the channel checks if stochastic error is being used and if so whether or not the +link between the sender and destination is currently on or off. If off, the packet is not +sent to the destiation node device. + +Next, the channel checks if the destination node is within the maximum transmission range +of the sending node based on distance between the sender and the destination. +If the destination node is out of range then the packet is not sent to the destination +node device. + +Finally, the channel checks if the packet would be in error if it were to be transmitted +to the device. This decision is based on the configured error model as follows: ++ If the error model is CONSTANT, then the packet is in error if a randomly +selected error value exceeds the configured error rate. Note that the error rate +is per packet and based on the size of the packet. ++ If the error model is PER_CURVE, then the packet error is determined using the +packet error rate curve specified by the user. The distance between the sender +and the receive is used to pick an error value from this curve, linearly interpolating +between points on the curve. If a random selected value exceeds this error rate, then +the packet is considered in error and is not sent to the device. This too is packet based +error rate. ++ If the error model is STOCHASTIC, then there is no packet error. The decision on handling +of packets (sent or not sent) is made earlier when the state of the link is checked. + +If a device passes all tests (the device is not on the sending node, the device is +in view of the sending, the link to the device is not in the OFF state if STOCHASTIC error +model is being use, the device is in range and the packet error rate is below the threshold) +then a reception event is scheduled for the destination device. + +This process is repeated for all the devices on the channel. + +The SimpleWirelessChannel is only involved on the send side and has no functions +associated with receiving packets. + +It is important to note that packets that are in error are NOT sent. In other words, the +decision is made on the send side and not the receive side. This minimizes the overhead +of a simulation because there are no resources spent on transmitting and receiving a packet +that ultimately will fail reception due to errors. However, this does impede the modeling +of packet interference if it were to be implemented in the SimpleWireless model. Since that +is currently not implemented, it is perfectly fine to drop packets at the source and conserve +simulation resources. + + +SimpleWirelessNetDevice +======================= +The SimpleWirelessNetDevice models the wireless device on the interface of a node and +includes the following features: +- Queue support with user configurable queue method +- Transmission limited by data rate +- Support for differentiating control and data traffic +- Support for pcap capture of packets sent and received +- Support for simulated directional networking through fixed neighbor lists +- Support for fixed contention + +The SimpleWirelessNetDevice supports the use of queue in which to hold packets for transmission. +When queues are used, their purpose is essentially to force a data rate for the device. +Queues are always FIFO but the drop method of the queue is configurable to be either +drop head or drop tail. In addition, there is support for priority queue which implements +separate control and data queues, each of which can be set independently as drop head or drop tail. +When a priority queue is used, a pcap string filter is used to differentiate control and +data packets. Note that it is possible to use no queuing which is the behavior of the original +simple wireless model. + +When queues are used, the SimpleWirelessNetDevice maintains a transmit state flag to indicate +if the device is currently transmitting or is idle. When the SimpleWirelessNetDevice receives +a packet from the upper layer to transmit, it places the packet into the queue and if currently +idle, immediately transmits the packet and sets the flag to busy. After the tranmission +is complete, it sets the flag back to idle and checks the queue to see if there is another +packet waiting to be sent. The transmission time of a packet is based on the packet size +and the data rate (configurable). + +Note that the busy state is set at the net device and not at the channel. As indicated above, +the channel does not actually send any packets that would be delivered in error at the +destination node. The device does not know about this and will be considered "busy" for the +amount of time required to transmit the packet even it the channel does not actually send it. + +When queues are not used, the SimpleWirelessNetDevice immediately sends a packet when it +receives it and does not maintain a busy flag. + +The SimpleWirelessNetDevice implements a simple version of directional networks with +the use of a "neighbor list" which is used to identify the nodes that are in view of the +node as though there was a directional antenna. If this feature is disabled then all nodes +are within view of the node. If this feature is enabled, then only the nodes listed in +the node's neighbor list are considered in view of the node. When directional networking +is enabled for the device, the SimpleWirelessNetDevice enqueues outbound packets as follows: +- A broadcast packet is duplicated and enqueued once for each directional neighbor. +- A unicast packet is enqueued only if the destination is a directional neighbor. + +Note that when the directional network feature is enabled, packets are enqueued for a specific +destination so that when the SimpleWirelessChannel gets the packet, there will be only one +destination device to which the packet will be sent. This differs from the case without a +directional network when only one packet is enqueued. As an example, suppose a node has +3 neighbors. If directional networks are enabled, the device will enqueue 3 packets -- 1 for each +destination. When the channel receives the packet to send, it will only deliver it to one +device on that destination node. If directional networks are not enabled, the device enqueues +one packet. When the channel receives the packet to send, it will deliver it to the three +devices on each of its neighbor nodes. + +The simple wireless model also implements a feature to account for contention. This is +called "fixed contention" feature. The model counts up the number of neigbor nodes that could +cause contention on the channel and reduces the data rate available to a sending node +based on this count. Thus the data rate becomes data rate/# neighbors. +The device uses this new data rate when it determines the transmit time used for setting +how long to keep the busy flag for the device set and for delay associated with transmission. +The manner in which the number of neighbors is counted is as follows: +the count first includes the node itself. Then when the channel transmits +a packet, it loops over all devices on the channel. During this loop the number of destination +devices that are within the user specificed contention range are counted and this is the count +that is used for the next time that a packet arrives on the device to be queued (or sent). +This the information is not the exact number of nodes within contention range at the instant +when a packet is queued but is based on the previous transmit. + +The SimpleWirelessNetDevice supports pcap tracing of packets that are sent and +received by the device. + +The SimpleWirelessNetDevice also supports a receive error model. + +SimpleWireless Model Configuration Items +**************************************** +The following items are configurable on the Simple Wireless Channel + +MaxRange ++ description: Error model used on the send side ++ units: --- ++ default: CONSTANT ++ possible values: CONSTANT, PER_CURVE, or STOCHASTIC + +ErrorModel ++ description: Error model used on the send side ++ units: --- ++ default: CONSTANT ++ possible values: CONSTANT, PER_CURVE, or STOCHASTIC + +ErrorRate ++ description: Error rate associated with the CONSTANT error model. Not used if ErrorModel is set to PER_CURVE. ++ units: --- ++ default: 0.0 ++ possible values: 0.0 to 1.0 inclusive + +AvgLinkUpDuration ++ description: Average duration of link ON state for STOCHASTIC error model. ++ units: TimeValue ++ default: 10000 usec ++ possible values: any TimeValue + +AvgLinkDownDuration ++ description: Avergage duration of link OFF state for STOCHASTIC error model. ++ units: TimeValue ++ default: 100 usec ++ possible values: any TimeValue + +EnableFixedContention ++ description: Flag used to enabled or disable the Fixed Contention feature ++ units: --- ++ default: false ++ possible values: true/false + +FixedContentionRange ++ description: Range used to count the number of neighbors for fixed contention. + If fixed contention is enabled and this value is 0, then uses the value set for MaxRange. ++ units: meters ++ default: 0 ++ possible values: any value > 0 + +PER Curve ++ description: Pairs of used to build the packet error rate (PER) curve. ++ units: meters,error ++ default: --- ++ possible values: distance: > 0 and error: 0.0-1.0 + + ++ description: ++ units: ++ default: ++ possible values: + + +The following items are configurable on the Simple Wireless Device + +ReceiveErrorModel ++ description: Error model used on the receive side. ++ units: --- ++ default: none ++ possible values: --- + +DataRate ++ description: Datarate to use for the device. ++ units: data rate ++ default: 1000000b/s ++ possible values: --- + +FixedNeighborListEnabled ++ description: Flag used to enabled or disable the simulated directional network with fixed neighbor list feature ++ units: --- ++ default: false ++ possible values: true/false + +Fixed Neighbor List ++ description: Node ids to add to the fixed neighbor list when simulating directional networks with neighbor lists. ++ units: node id ++ default: none ++ possible values: any value >= 0 + +TxQueue ++ description: Type of queuing to use if any. ++ units: --- ++ default: NULL (no queue) ++ possible values: NULL, DropTailQueue, DropHeadQueue, PriorityQueue + + +The following items are configurable on the Queues + +Mode ++ description: Drop mode for the queue. + If PACKETS, then packets are dropped from the queue when it is at capacity without regard to size. + If BYTES, then the size of the packets is considered when dropping packets. ++ units: ++ default: QUEUE_MODE_PACKETS ++ possible values: QUEUE_MODE_PACKETS or QUEUE_MODE_BYTES + +MaxPackets ++ description: Maximum number of packets to allow in the queue. Used when mode is QUEUE_MODE_PACKETS. ++ units: --- ++ default: 100 ++ possible values: any value > 0 + +MaxBytes ++ description: Maximum number of bytes to allow in the queue. Used when mode is QUEUE_MODE_BYTES. ++ units: --- ++ default: 6,553,500 ++ possible values: any value > 0 + +ControlPacketClassifier ++ description: String used to classify control packets using a pcap filter when Priority Queues are used. + Examples: + To classify packets based on port: StringValue ("port 698") + To classify packets based on ether type: StringValue ("ether proto 0x88B5") ++ units: --- ++ default: none ++ possible values: any string + + +Using the SimpleWireless Model +****************************** +To use the SimpleWireless model, users need to configure in the following steps: + +1) Create the SimpleWirelessChannel + Ptr phy = CreateObject (); + +2) Configure the SimpleWirelessChannel + a) Set the range for the channel + phy->SetDeviceAttribute ("MaxRange", DoubleValue (txRange)); + + Default value can be set as follows but this must be done BEFORE creating the channel: + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (txRange)); + + b) Set the error model type + phy->setErrorModelType(CONSTANT); + + c) If the error model type is CONSTANT, set the error rate + phy->setErrorRate(errorRate); + + d) If the error model type is PER_CURVE, build the error curve by calling the function + phy->addToPERmodel(0.0, 0.0); + phy->addToPERmodel(10.0, 0.0); + phy->addToPERmodel(20.0, 0.0); + phy->addToPERmodel(30.0, 0.007); + phy->addToPERmodel(40.0, 0.1); + phy->addToPERmodel(50.0, 0.4); + phy->addToPERmodel(60.0, 0.7); + phy->addToPERmodel(70.0, 0.9); + + e) If the error model type is STOCHASTIC, set the up and down durations + phy->SetAttribute("AvgLinkUpDuration", TimeValue (MicroSeconds (errorUpAvg))); + phy->SetAttribute("AvgLinkDownDuration", TimeValue (MicroSeconds (errorDownAvg))); + + f) If using the fixed contention feature, enable the feature + phy->EnableFixedContention(); + + g) If using the fixed contention feature with a non-default value for the contention range (default value is channel's transmission range) set the contention range value + phy->SetFixedContentionRange(contentionRange); + +3) On EACH node, create SimpleWirelessNetDevice + Ptr simpleWireless = CreateObject (); + +4) Configure the SimpleWirelessChannel + a) Set the channel + simpleWireless->SetChannel(phy); + + b) Set the node + simpleWireless->SetNode(node); + + c) Set the data rate + simpleWireless->SetDataRate(DataRate ("1Mb/s")) + + Default value can be set as follows but this must be done BEFORE creating the devices: + Config::SetDefault ("ns3::SimpleWirelessNetDevice::DataRate", DataRateValue (DataRate (dataRate))); + + d) Set the address + simpleWireless->SetAddress(Mac48Address::Allocate ()); + + e) Create a queue and set this on the device. For example: + Ptr queue = CreateObject (); + simpleWireless->SetQueue(queue); + + The example model queue_test.cc show how to configure each type of queue + + f) Add the device to the node and device container + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + g) Enable pcap capture if desired: + std::ostringstream stringStream; + stringStream << "scenario_name_" << node->GetId() << ".pcap"; + fileStr = stringStream.str(); + simpleWireless->EnablePcapAll(fileStr); + +5) If being use, enable directional networking and pass a list of neighbors + This must be done AFTER adding all the devices to each node + NOTE that the code checks the return code from the call to AddDirectionalNeighbors + + Example: In this example, Node 0 has directional neighbors 1, 3, 4, 7, 10, and 11 + Ptr dev0 = devices.Get(0); + Ptr swDev0 = DynamicCast(dev0); + simpleWireless->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + // build a map of directional neighbor nodes and mac addresses + std::map nbrSet; + for ( NetDeviceContainer::Iterator dIt = devices.Begin(); dIt != devices.End(); ++dIt) + { + Ptr node = (*dIt)->GetNode(); + uint32_t id = node->GetId(); + // in this example, specific node ids are directional neighbors + if ( id == 1 || id == 3 || id == 4 || id == 7 || id == 10 || id == 11 ) + { + // Get mac addr of node and add to map + Address addr = (*dIt)->GetAddress(); + Mac48Address macAddr = Mac48Address::ConvertFrom (addr); + nbrSet.insert(std::pair(id, macAddr)); + std::cout << "Adding node " << id << " with mac address " << macAddr<< std::endl; + } + } + // Now add to dev on node 0 + if (!swDev0->AddDirectionalNeighbors(nbrSet)) + { + NS_FATAL_ERROR ("Call to AddDirectionalNeighbors failed. Please enabled directional neighbors."); + return 0; + } + + There are also functions to allow dynamic simulated directional networking through fixed neighbor lists + by adding and removing neighbor to/from the list over time. This can be done using calls to the methods: + AddDirectionalNeighbor + DeleteDirectionalNeighbor + + +6) Initial the Stochastic error model. This must be done AFTER adding all the devices and does nothing if not running STOCHASTIC error model + phy->InitStochasticModel(); + +SimpleWirelessNetDevice Model Traces +************************************ +The following traces are available for the device: + +* PhyTxBegin - called when the device sends the packet to the channel for Tx + +* PhyRxBegin - called when a packet has begun being received by the device + +* PhyRxEnd - called when a packet has been completely received by the device + +* PhyRxDrop - called if a packet is dropped by the device during receive + +* PromiscSniffer - called for pcap capture of packets; captures on send and receive + +* QueueLatency - called when a packet is dequeued for transmission + +* MacTx - called when a packet has been received from higher layers and is being queued for transmission + +* MacRx - called when a packet has been received over the air and is being forwarded up the local protocol stack + +SimpleWirelessChannel Model Traces +************************************ +NONE + +SimpleWireless Examples +************************************ +The examples directory has the following examples which show how to configure the +Simple Wireless model and use the features that it has. + +directional_test.cc Provides an example of how to use the simulated directional network feature + +error_model_test.cc Provides an example of how to use the error models added to the send side (CONSTANT, PER_CURVE and STOCHASTIC) + +fixed_contention_test.cc Provides an example of how to use the fixed contention feature + +multiple_interface_example.cc Provides a simple 2 node example of how to configure multiple interfaces on a node + +mixed_directional_network.cc Provides a more complex example of multiple interfaces per node in combination with the simulated directional networks. + +queue_test.cc Provides examples of how to configure each type of queuing. + diff --git a/examples/directional_test.cc b/examples/directional_test.cc index 131aeb7..b47d7a3 100644 --- a/examples/directional_test.cc +++ b/examples/directional_test.cc @@ -1,441 +1,441 @@ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * All rights reserved. - * - * 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 -*/ - -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - -#include -#include -#include -#include -#include -#include "ns3/core-module.h" -#include "ns3/network-module.h" -#include "ns3/olsr-module.h" -#include "ns3/mobility-module.h" -#include "ns3/applications-module.h" -#include "ns3/internet-module.h" -#include "ns3/simple-wireless-module.h" - - -// This file is used to test the directional network option. -// For directional networks, the user must specify a list of neighbors that -// can be seen. If a neighbor can not be seen, all packets are dropped for -// that neighbr. If a neighbor can be seen, the configured error is then -// applied to the packet transmit. -// -// The scenario has the following: -// - 13 nodes -// - node 0 is at the center of a circle -// - nodes 1-12 are placed on a circle of radius 50 in a clock face layout -// (i.e., node 1 at 1 o'clock position, node 2 at 2 o'clock position, etc.) -// - no mobility -// - simple wireless model has: -// + constant error rate of 0 -// + tx range of 100 so that all nodes are in range of node 0 -// + drop head queue -// + 10Mbps data rate -// + simple wireless is configured to NOT drop any packets due to queueing -// - OLSR used for routing -// - On/Off application used for node 0 to send 1Mb/s to all 12 neighbor nodes -// - capability to enable pcap capture - -// The following nodes are added to the list of neighbors for directional networking: -// 1, 3, 4, 7, 10, 11 -// -// X -// 11 1 -// 10 X -// X O 3 -// X 4 -// 7 X -// X - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE ("directional_test"); - -uint32_t app_count_sent = 0; -uint32_t app_count_recv = 0; -uint32_t pkts_sent_data = 0; -uint32_t pkts_rcvd_data = 0; -uint32_t pkts_sent_cntl = 0; - -// variables for queue latency: overall, data and control -double_t avg_queue_latency = 0.0; -uint32_t queue_pkt_count = 0; -double_t avg_queue_latency_data = 0.0; -uint32_t queue_pkt_count_data = 0; -double_t avg_queue_latency_cntl = 0.0; -uint32_t queue_pkt_count_cntl = 0; - -#define NUM_NODES 13 -#define NUM_DIR_NBR_NODES 6 // nodes 1, 3, 4, 7, 10, 11 are directional neighbors -uint32_t pkts_rcvd_by_node[NUM_NODES]; - -#define APP_PKT_SIZE 1000 -std::string PktSize = "1000"; - - -// ****************************************************************** -// This function supports OLSR when running on Simple Wireless -// ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) -{ - // Figure out if this is OLSR or data - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_sent_data++; - } - else - { - pkts_sent_cntl++; - } - - -} - - -static void MacRxSuccess (std::string context, Ptr p) -{ - int id = atoi(context.c_str()); - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_by_node[id]++; - pkts_rcvd_data++; - } -} - -// ****************************************************************** -// This function supports Simple Wireless -// ****************************************************************** -static void QueueLatencyStats (Ptr p, Time latency) -{ - double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; - - queue_pkt_count++; - avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; - - // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. - // Packet passed in this trace still has the Ethernet header - if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) - { - queue_pkt_count_data++; - avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; - //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } - else - { - queue_pkt_count_cntl++; - avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; - //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } - -} - - -// ****************************************************************** -// These functions support OLSR and are related to the Applications -// ****************************************************************** - -static void SinkReceivedBytes (Ptr p, const Address & from) -{ - app_count_recv++; - //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; -} - -static void AppSendBytes (Ptr p) -{ - app_count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; -} - - -// ****************************************************************** -// MAIN -// ****************************************************************** - -int -main (int argc, char *argv[]) -{ - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 65; - bool collectPcap = false; - double dataRate = 10000000.0; - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.Parse (argc,argv); - - std::cout << "Running scenario for " << simtime << " seconds "<< std::endl; - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer myNodes; - myNodes.Create (NUM_NODES); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - phy->setErrorRate(0.0); - phy->setErrorModelType(CONSTANT); - - // Uncomment these two lines if you would like to also use contention - //phy->EnableFixedContention(); - //phy->SetFixedContentionRange(100.0); - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - std::cout << "node id " << node->GetId() << " has macAddress of " << simpleWireless->GetAddress() << std::endl; - - // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "QUEUE_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - - // ------------------------------------------------------------------------ - // Set up directional network. Do this after adding all the devices because - // we need to get MAC addresses for the neighbors we want to add - // Only node 0 has directional neighbors. - - // Get node 0 device on the container. - // we added them in numerical order so we know that 0 is node0 - Ptr dev0 = devices.Get(0); - Ptr swDev0 = DynamicCast(dev0); - swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - std::map nbrSet; - // Now in this example, we use an iterator to get the devices. - for ( NetDeviceContainer::Iterator dIt = devices.Begin(); dIt != devices.End(); ++dIt) - { - Ptr node = (*dIt)->GetNode(); - uint32_t id = node->GetId(); - - if ( id == 1 || id == 3 || id == 4 || id == 7 || id == 10 || id == 11 ) - { - // Get mac addr of node and add to map - Address addr = (*dIt)->GetAddress(); - Mac48Address macAddr = Mac48Address::ConvertFrom (addr); - nbrSet.insert(std::pair(id, macAddr)); - std::cout << "Adding node " << id << " with mac address " << macAddr<< std::endl; - } - } - // Now add to dev on node 0 - if (!swDev0->AddDirectionalNeighbors(nbrSet)) - { - NS_FATAL_ERROR ("Call to AddDirectionalNeighbors failed. Please enabled directional neighbors."); - return 0; - } - // ------------------------------------------------------------------------ - - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - - // *********************************************************************** - // Define positions. - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); - positionAlloc->Add (Vector (25.0, 43.0, 0.0)); - positionAlloc->Add (Vector (43.0, 25.0, 0.0)); - positionAlloc->Add (Vector (50.0, 0.0, 0.0)); - positionAlloc->Add (Vector (43.0, -25.0, 0.0)); - positionAlloc->Add (Vector (25.0, -43.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); - positionAlloc->Add (Vector (-25.0,-43.0, 0.0)); - positionAlloc->Add (Vector (-43.0,-25.0, 0.0)); - positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); - positionAlloc->Add (Vector (-43.0, 25.0, 0.0)); - positionAlloc->Add (Vector (-25.0, 43.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (myNodes); - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (myNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. - - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; - - // start the OnOff app on source to destinations (using unicast) - //OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); - //std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; - - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - - ApplicationContainer apps = onoff.Install (myNodes.Get (0)); - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - } - else - { - // on all other nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); - ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; - } - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // For OLSR we need to get some stats - // *********************************************************************** - double rcvPercentData = 0.0; - uint32_t dataDropped = app_count_sent*NUM_DIR_NBR_NODES - app_count_recv; - if (app_count_sent) - rcvPercentData = ((double)app_count_recv/((double)app_count_sent*NUM_DIR_NBR_NODES))*100.0; - - std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv - << "\nControl Packets Sent: " << pkts_sent_cntl - << "\nData Packets Sent: " << pkts_sent_data - << "\nData Packets Received: " << pkts_rcvd_data - << "\nData Packets Dropped: " << dataDropped - << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0)< dev = devices.Get(0); - PointerValue val; - dev->GetAttribute("TxQueue", val); - Ptr queue = val.Get(); - Ptr dropHead = DynamicCast(queue); - std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets() << std::endl; - - for (int i = 1; i < NUM_NODES; i++) - { - std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; - } - - - - NS_LOG_INFO ("Run Completed Successfully"); - - return 0; -} +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * All rights reserved. + * + * 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 +*/ + +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include +#include +#include +#include +#include +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/olsr-module.h" +#include "ns3/mobility-module.h" +#include "ns3/applications-module.h" +#include "ns3/internet-module.h" +#include "ns3/simple-wireless-module.h" + + +// This file is used to test the directional network option. +// For directional networks, the user must specify a list of neighbors that +// can be seen. If a neighbor can not be seen, all packets are dropped for +// that neighbr. If a neighbor can be seen, the configured error is then +// applied to the packet transmit. +// +// The scenario has the following: +// - 13 nodes +// - node 0 is at the center of a circle +// - nodes 1-12 are placed on a circle of radius 50 in a clock face layout +// (i.e., node 1 at 1 o'clock position, node 2 at 2 o'clock position, etc.) +// - no mobility +// - simple wireless model has: +// + constant error rate of 0 +// + tx range of 100 so that all nodes are in range of node 0 +// + drop head queue +// + 10Mbps data rate +// + simple wireless is configured to NOT drop any packets due to queueing +// - OLSR used for routing +// - On/Off application used for node 0 to send 1Mb/s to all 12 neighbor nodes +// - capability to enable pcap capture + +// The following nodes are added to the list of neighbors for directional networking: +// 1, 3, 4, 7, 10, 11 +// +// X +// 11 1 +// 10 X +// X O 3 +// X 4 +// 7 X +// X + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("directional_test"); + +uint32_t app_count_sent = 0; +uint32_t app_count_recv = 0; +uint32_t pkts_sent_data = 0; +uint32_t pkts_rcvd_data = 0; +uint32_t pkts_sent_cntl = 0; + +// variables for queue latency: overall, data and control +double_t avg_queue_latency = 0.0; +uint32_t queue_pkt_count = 0; +double_t avg_queue_latency_data = 0.0; +uint32_t queue_pkt_count_data = 0; +double_t avg_queue_latency_cntl = 0.0; +uint32_t queue_pkt_count_cntl = 0; + +#define NUM_NODES 13 +#define NUM_DIR_NBR_NODES 6 // nodes 1, 3, 4, 7, 10, 11 are directional neighbors +uint32_t pkts_rcvd_by_node[NUM_NODES]; + +#define APP_PKT_SIZE 1000 +std::string PktSize = "1000"; + + +// ****************************************************************** +// This function supports OLSR when running on Simple Wireless +// ****************************************************************** +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +{ + // Figure out if this is OLSR or data + if (p->GetSize() == (APP_PKT_SIZE + 28)) + { + pkts_sent_data++; + } + else + { + pkts_sent_cntl++; + } + + +} + + +static void MacRxSuccess (std::string context, Ptr p) +{ + int id = atoi(context.c_str()); + if (p->GetSize() == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_by_node[id]++; + pkts_rcvd_data++; + } +} + +// ****************************************************************** +// This function supports Simple Wireless +// ****************************************************************** +static void QueueLatencyStats (Ptr p, Time latency) +{ + double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; + + queue_pkt_count++; + avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; + + // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. + // Packet passed in this trace still has the Ethernet header + if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) + { + queue_pkt_count_data++; + avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; + //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } + else + { + queue_pkt_count_cntl++; + avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; + //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } + +} + + +// ****************************************************************** +// These functions support OLSR and are related to the Applications +// ****************************************************************** + +static void SinkReceivedBytes (Ptr p, const Address & from) +{ + app_count_recv++; + //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; +} + +static void AppSendBytes (Ptr p) +{ + app_count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; +} + + +// ****************************************************************** +// MAIN +// ****************************************************************** + +int +main (int argc, char *argv[]) +{ + NodeContainer::Iterator it; + NodeContainer::Iterator it2; + std::list destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 65; + bool collectPcap = false; + double dataRate = 10000000.0; + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.Parse (argc,argv); + + std::cout << "Running scenario for " << simtime << " seconds "<< std::endl; + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer myNodes; + myNodes.Create (NUM_NODES); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); + + // create channel + Ptr phy = CreateObject (); + phy->setErrorRate(0.0); + phy->setErrorModelType(CONSTANT); + + // Uncomment these two lines if you would like to also use contention + //phy->EnableFixedContention(); + //phy->SetFixedContentionRange(100.0); + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel(phy); + simpleWireless->SetNode(node); + simpleWireless->SetAddress(Mac48Address::Allocate ()); + simpleWireless->SetDataRate((DataRate (dataRate))); + std::cout << "node id " << node->GetId() << " has macAddress of " << simpleWireless->GetAddress() << std::endl; + + // Set queue type to use + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue(queue); + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId(); + simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "QUEUE_node_" << node->GetId() << ".pcap"; + fileStr = stringStream.str(); + simpleWireless->EnablePcapAll(fileStr); + } + } + + + // ------------------------------------------------------------------------ + // Set up directional network. Do this after adding all the devices because + // we need to get MAC addresses for the neighbors we want to add + // Only node 0 has directional neighbors. + + // Get node 0 device on the container. + // we added them in numerical order so we know that 0 is node0 + Ptr dev0 = devices.Get(0); + Ptr swDev0 = DynamicCast(dev0); + swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + std::map nbrSet; + // Now in this example, we use an iterator to get the devices. + for ( NetDeviceContainer::Iterator dIt = devices.Begin(); dIt != devices.End(); ++dIt) + { + Ptr node = (*dIt)->GetNode(); + uint32_t id = node->GetId(); + + if ( id == 1 || id == 3 || id == 4 || id == 7 || id == 10 || id == 11 ) + { + // Get mac addr of node and add to map + Address addr = (*dIt)->GetAddress(); + Mac48Address macAddr = Mac48Address::ConvertFrom (addr); + nbrSet.insert(std::pair(id, macAddr)); + std::cout << "Adding node " << id << " with mac address " << macAddr<< std::endl; + } + } + // Now add to dev on node 0 + if (!swDev0->AddDirectionalNeighbors(nbrSet)) + { + NS_FATAL_ERROR ("Call to AddDirectionalNeighbors failed. Please enabled directional neighbors."); + return 0; + } + // ------------------------------------------------------------------------ + + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + + // *********************************************************************** + // Define positions. + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (25.0, 43.0, 0.0)); + positionAlloc->Add (Vector (43.0, 25.0, 0.0)); + positionAlloc->Add (Vector (50.0, 0.0, 0.0)); + positionAlloc->Add (Vector (43.0, -25.0, 0.0)); + positionAlloc->Add (Vector (25.0, -43.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); + positionAlloc->Add (Vector (-25.0,-43.0, 0.0)); + positionAlloc->Add (Vector (-43.0,-25.0, 0.0)); + positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); + positionAlloc->Add (Vector (-43.0, 25.0, 0.0)); + positionAlloc->Add (Vector (-25.0, 43.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (myNodes); + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (myNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId(); + + if (id == 0) + { + // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. + + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; + + // start the OnOff app on source to destinations (using unicast) + //OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); + //std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; + + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + + ApplicationContainer apps = onoff.Install (myNodes.Get (0)); + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + } + else + { + // on all other nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); + ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; + } + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds(simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // For OLSR we need to get some stats + // *********************************************************************** + double rcvPercentData = 0.0; + uint32_t dataDropped = app_count_sent*NUM_DIR_NBR_NODES - app_count_recv; + if (app_count_sent) + rcvPercentData = ((double)app_count_recv/((double)app_count_sent*NUM_DIR_NBR_NODES))*100.0; + + std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv + << "\nControl Packets Sent: " << pkts_sent_cntl + << "\nData Packets Sent: " << pkts_sent_data + << "\nData Packets Received: " << pkts_rcvd_data + << "\nData Packets Dropped: " << dataDropped + << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0)< dev = devices.Get(0); + PointerValue val; + dev->GetAttribute("TxQueue", val); + Ptr queue = val.Get(); + Ptr dropHead = DynamicCast(queue); + std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets() << std::endl; + + for (int i = 1; i < NUM_NODES; i++) + { + std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; + } + + + + NS_LOG_INFO ("Run Completed Successfully"); + + return 0; +} diff --git a/examples/error_model_test.cc b/examples/error_model_test.cc index 2f9f879..c742e19 100644 --- a/examples/error_model_test.cc +++ b/examples/error_model_test.cc @@ -1,373 +1,373 @@ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * All rights reserved. - * - * 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 -*/ - -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - -#include -#include -#include -#include -#include -#include "ns3/core-module.h" -#include "ns3/network-module.h" -#include "ns3/olsr-module.h" -#include "ns3/mobility-module.h" -#include "ns3/applications-module.h" -#include "ns3/internet-module.h" -#include "ns3/simple-wireless-module.h" - - -// This file is used to test the error models added to the send side and -// support CONSTANT, PER_CURVE and STOCHASTIC. -// -// The scenario has the following: -// - 101 nodes -// - node 0 is at the center of a circle -// - nodes 1-100 are randomly placed on a circle of radius 100 -// - NO mobility -// - simple wireless model has: -// + User specified error type -// + tx range of 100 -// + NO queue -// - OLSR used for routing -// - On/Off application used for node 0 to send 1Mb/s to all 100 neighbor nodes - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE ("error_model_test"); - -uint32_t count_sent = 0; -// These are only used by OLSR -uint32_t count_recv = 0; -uint32_t pkts_sent_data = 0; -uint32_t bytes_sent_data = 0; -uint32_t pkts_sent_cntl = 0; -uint32_t bytes_sent_cntl = 0; - -#define APP_PKT_SIZE 1000 -std::string PktSize = "1000"; - -#define NUM_NODES 101 // node 0 is source + N neighbors -uint32_t pkts_rcvd_by_node[NUM_NODES]; - -// ****************************************************************** -// This function supports OLSR when running on Simple Wireless -// ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) -{ - // Figure out if this is OLSR or data - if (to.IsBroadcast () && p->GetSize() != (APP_PKT_SIZE + 28)) - { - pkts_sent_cntl++; - bytes_sent_cntl += p->GetSize(); - //std::cout << Simulator::Now ().GetSeconds () << " Node sending CONTROL packet of " << p->GetSize() << " bytes to address " << to << std::endl; - } - else - { - pkts_sent_data++; - bytes_sent_data += p->GetSize(); - //std::cout << Simulator::Now ().GetSeconds () << " Node sending DATA packet of " << p->GetSize() << " bytes to address " << to << std::endl; - } -} - -static void MacRxSuccess (std::string context, Ptr p) -{ - int id = atoi(context.c_str()); - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_by_node[id]++; - // Uncomment this line for STOCHASTIC so that you can graph packets received vs time - std::cout << Simulator::Now ().GetSeconds () << " Node " << id << " receiving packet of " << p->GetSize() << " bytes."<< std::endl; - } - - -} - - -// ****************************************************************** -// These functions are related to the Applications -// ****************************************************************** -static void SinkReceivedBytes (Ptr p, const Address & from) -{ - count_recv++; - //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; -} - -static void AppSendBytes (Ptr p) -{ - count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; -} - - -// ****************************************************************** -// MAIN -// ****************************************************************** - -int -main (int argc, char *argv[]) -{ - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 65; - double dataRate = 1000000.0; - - bool collectPcap = false; - std::string errorModel = "CONSTANT"; - double errorRate = 0.0; - double errorUpAvg = 15000000.0; // 15 seconds up - double errorDownAvg = 5000000.0; // 5 second down - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.AddValue ("errorModel", "Error model to use. Must be one of: CONSTANT, CURVE, STOCHASTIC", errorModel); - cmd.AddValue ("errorRate", "Error rate if CONSTANT error model is used", errorRate); - cmd.AddValue ("errorUpAvg", "Average link up duration (microseconds) if STOCHASTIC error model is used", errorUpAvg); - cmd.AddValue ("errorDownAvg", "Average link down duration (microseconds) if STOCHASTIC error model is used", errorDownAvg); - cmd.Parse (argc,argv); - - if ((errorModel != "CONSTANT") && (errorModel != "CURVE") && (errorModel != "STOCHASTIC") ) - { - NS_ABORT_MSG ("Invalid errorModel type: Use --errorModel=CONSTANT or --errorModel=CURVE or --errorModel=STOCHASTIC"); - } - - std::cout << "Running scenario for " << simtime << " seconds using error type of "<< errorModel << std::endl; - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer myNodes; - myNodes.Create (NUM_NODES); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - if ( errorModel.compare ("CURVE") == 0 ) - { - phy->setErrorModelType(PER_CURVE); - phy->addToPERmodel(0.0, 0.0); - phy->addToPERmodel(10.0, 0.0); - phy->addToPERmodel(20.0, 0.05); - phy->addToPERmodel(30.0, 0.07); - phy->addToPERmodel(40.0, 0.12); - phy->addToPERmodel(50.0, 0.15); - phy->addToPERmodel(60.0, 0.5); - phy->addToPERmodel(70.0, 0.6); - phy->addToPERmodel(80.0, 0.70); - phy->addToPERmodel(90.0, 0.80); - phy->addToPERmodel(100.0, 1.0); - } - else if ( errorModel.compare ("CONSTANT") == 0 ) - { - phy->setErrorModelType (CONSTANT); - phy->setErrorRate (errorRate); - } - else if ( errorModel.compare ("STOCHASTIC") == 0 ) - { - phy->setErrorModelType(STOCHASTIC); - phy->SetAttribute("AvgLinkUpDuration", TimeValue (MicroSeconds (errorUpAvg))); - phy->SetAttribute("AvgLinkDownDuration", TimeValue (MicroSeconds (errorDownAvg))); - } - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "ErrorModelTest_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - // Must be done AFTER adding all the devices. Does nothing if not running STOCHASTIC error model - phy->InitStochasticModel(); - - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - - // *********************************************************************** - // Define positions. - ObjectFactory pos; - pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); - pos.Set ("X", DoubleValue (0.0)); - pos.Set ("Y", DoubleValue (0.0)); - pos.Set ("rho", DoubleValue (100)); - Ptr positionAlloc = pos.Create ()->GetObject (); - - // *********************************************************************** - // Define and install random mobility. Here we are using the circle set up above - // as the position allocator for mobility (i.e., the area they can move in) - // *********************************************************************** - MobilityHelper mobility; - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (myNodes); - - // print starting positions - for (it = n.Begin (); it != n.End (); ++it) - { - // get node ptr, position and node id - Ptr node = *it; - Ptr mob = node->GetObject (); - int id = node->GetId(); - - // set up source node - if (id == 0) - { - // placed at the center and is the source node! - mob->SetPosition (Vector (0.0,0.0,0.0)); - } - Vector pos = mob->GetPosition (); - double distance = sqrt(pos.x*pos.x + pos.y*pos.y); - std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: "<< distance << std::endl; - } - - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (myNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (myNodes.Get (0)); - std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - } - else - { - // on all other nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); - ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); - apps_sink.Start (Seconds (0.0)); - //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; - pkts_rcvd_by_node[id] = 0; - } - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // For OLSR we need to get some stats - // *********************************************************************** - std::cout << "App Sent Count: " << count_sent << "\nApp Receive Count: " << count_recv << std::endl; - std::cout << "Control Sent Count: " << pkts_sent_cntl << "\nData Sent Count: " << pkts_sent_data << std::endl; - for (int i = 1; i < NUM_NODES; i++) - { - std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; - } - - - NS_LOG_INFO ("Run Completed Successfully"); - - return 0; -} +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * All rights reserved. + * + * 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 +*/ + +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include +#include +#include +#include +#include +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/olsr-module.h" +#include "ns3/mobility-module.h" +#include "ns3/applications-module.h" +#include "ns3/internet-module.h" +#include "ns3/simple-wireless-module.h" + + +// This file is used to test the error models added to the send side and +// support CONSTANT, PER_CURVE and STOCHASTIC. +// +// The scenario has the following: +// - 101 nodes +// - node 0 is at the center of a circle +// - nodes 1-100 are randomly placed on a circle of radius 100 +// - NO mobility +// - simple wireless model has: +// + User specified error type +// + tx range of 100 +// + NO queue +// - OLSR used for routing +// - On/Off application used for node 0 to send 1Mb/s to all 100 neighbor nodes + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("error_model_test"); + +uint32_t count_sent = 0; +// These are only used by OLSR +uint32_t count_recv = 0; +uint32_t pkts_sent_data = 0; +uint32_t bytes_sent_data = 0; +uint32_t pkts_sent_cntl = 0; +uint32_t bytes_sent_cntl = 0; + +#define APP_PKT_SIZE 1000 +std::string PktSize = "1000"; + +#define NUM_NODES 101 // node 0 is source + N neighbors +uint32_t pkts_rcvd_by_node[NUM_NODES]; + +// ****************************************************************** +// This function supports OLSR when running on Simple Wireless +// ****************************************************************** +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +{ + // Figure out if this is OLSR or data + if (to.IsBroadcast () && p->GetSize() != (APP_PKT_SIZE + 28)) + { + pkts_sent_cntl++; + bytes_sent_cntl += p->GetSize(); + //std::cout << Simulator::Now ().GetSeconds () << " Node sending CONTROL packet of " << p->GetSize() << " bytes to address " << to << std::endl; + } + else + { + pkts_sent_data++; + bytes_sent_data += p->GetSize(); + //std::cout << Simulator::Now ().GetSeconds () << " Node sending DATA packet of " << p->GetSize() << " bytes to address " << to << std::endl; + } +} + +static void MacRxSuccess (std::string context, Ptr p) +{ + int id = atoi(context.c_str()); + if (p->GetSize() == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_by_node[id]++; + // Uncomment this line for STOCHASTIC so that you can graph packets received vs time + std::cout << Simulator::Now ().GetSeconds () << " Node " << id << " receiving packet of " << p->GetSize() << " bytes."<< std::endl; + } + + +} + + +// ****************************************************************** +// These functions are related to the Applications +// ****************************************************************** +static void SinkReceivedBytes (Ptr p, const Address & from) +{ + count_recv++; + //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; +} + +static void AppSendBytes (Ptr p) +{ + count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; +} + + +// ****************************************************************** +// MAIN +// ****************************************************************** + +int +main (int argc, char *argv[]) +{ + NodeContainer::Iterator it; + NodeContainer::Iterator it2; + std::list destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 65; + double dataRate = 1000000.0; + + bool collectPcap = false; + std::string errorModel = "CONSTANT"; + double errorRate = 0.0; + double errorUpAvg = 15000000.0; // 15 seconds up + double errorDownAvg = 5000000.0; // 5 second down + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.AddValue ("errorModel", "Error model to use. Must be one of: CONSTANT, CURVE, STOCHASTIC", errorModel); + cmd.AddValue ("errorRate", "Error rate if CONSTANT error model is used", errorRate); + cmd.AddValue ("errorUpAvg", "Average link up duration (microseconds) if STOCHASTIC error model is used", errorUpAvg); + cmd.AddValue ("errorDownAvg", "Average link down duration (microseconds) if STOCHASTIC error model is used", errorDownAvg); + cmd.Parse (argc,argv); + + if ((errorModel != "CONSTANT") && (errorModel != "CURVE") && (errorModel != "STOCHASTIC") ) + { + NS_ABORT_MSG ("Invalid errorModel type: Use --errorModel=CONSTANT or --errorModel=CURVE or --errorModel=STOCHASTIC"); + } + + std::cout << "Running scenario for " << simtime << " seconds using error type of "<< errorModel << std::endl; + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer myNodes; + myNodes.Create (NUM_NODES); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); + + // create channel + Ptr phy = CreateObject (); + if ( errorModel.compare ("CURVE") == 0 ) + { + phy->setErrorModelType(PER_CURVE); + phy->addToPERmodel(0.0, 0.0); + phy->addToPERmodel(10.0, 0.0); + phy->addToPERmodel(20.0, 0.05); + phy->addToPERmodel(30.0, 0.07); + phy->addToPERmodel(40.0, 0.12); + phy->addToPERmodel(50.0, 0.15); + phy->addToPERmodel(60.0, 0.5); + phy->addToPERmodel(70.0, 0.6); + phy->addToPERmodel(80.0, 0.70); + phy->addToPERmodel(90.0, 0.80); + phy->addToPERmodel(100.0, 1.0); + } + else if ( errorModel.compare ("CONSTANT") == 0 ) + { + phy->setErrorModelType (CONSTANT); + phy->setErrorRate (errorRate); + } + else if ( errorModel.compare ("STOCHASTIC") == 0 ) + { + phy->setErrorModelType(STOCHASTIC); + phy->SetAttribute("AvgLinkUpDuration", TimeValue (MicroSeconds (errorUpAvg))); + phy->SetAttribute("AvgLinkDownDuration", TimeValue (MicroSeconds (errorDownAvg))); + } + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel(phy); + simpleWireless->SetNode(node); + simpleWireless->SetAddress(Mac48Address::Allocate ()); + simpleWireless->SetDataRate((DataRate (dataRate))); + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId(); + simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "ErrorModelTest_node_" << node->GetId() << ".pcap"; + fileStr = stringStream.str(); + simpleWireless->EnablePcapAll(fileStr); + } + } + + // Must be done AFTER adding all the devices. Does nothing if not running STOCHASTIC error model + phy->InitStochasticModel(); + + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + + // *********************************************************************** + // Define positions. + ObjectFactory pos; + pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); + pos.Set ("X", DoubleValue (0.0)); + pos.Set ("Y", DoubleValue (0.0)); + pos.Set ("rho", DoubleValue (100)); + Ptr positionAlloc = pos.Create ()->GetObject (); + + // *********************************************************************** + // Define and install random mobility. Here we are using the circle set up above + // as the position allocator for mobility (i.e., the area they can move in) + // *********************************************************************** + MobilityHelper mobility; + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (myNodes); + + // print starting positions + for (it = n.Begin (); it != n.End (); ++it) + { + // get node ptr, position and node id + Ptr node = *it; + Ptr mob = node->GetObject (); + int id = node->GetId(); + + // set up source node + if (id == 0) + { + // placed at the center and is the source node! + mob->SetPosition (Vector (0.0,0.0,0.0)); + } + Vector pos = mob->GetPosition (); + double distance = sqrt(pos.x*pos.x + pos.y*pos.y); + std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: "<< distance << std::endl; + } + + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (myNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId(); + + if (id == 0) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (myNodes.Get (0)); + std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + } + else + { + // on all other nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); + ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); + apps_sink.Start (Seconds (0.0)); + //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; + pkts_rcvd_by_node[id] = 0; + } + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds(simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // For OLSR we need to get some stats + // *********************************************************************** + std::cout << "App Sent Count: " << count_sent << "\nApp Receive Count: " << count_recv << std::endl; + std::cout << "Control Sent Count: " << pkts_sent_cntl << "\nData Sent Count: " << pkts_sent_data << std::endl; + for (int i = 1; i < NUM_NODES; i++) + { + std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; + } + + + NS_LOG_INFO ("Run Completed Successfully"); + + return 0; +} diff --git a/examples/fixed_contention_test.cc b/examples/fixed_contention_test.cc index 0a60ed9..38275ad 100644 --- a/examples/fixed_contention_test.cc +++ b/examples/fixed_contention_test.cc @@ -1,400 +1,400 @@ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * All rights reserved. - * - * 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 -*/ - -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - -#include -#include -#include -#include -#include -#include "ns3/core-module.h" -#include "ns3/network-module.h" -#include "ns3/olsr-module.h" -#include "ns3/mobility-module.h" -#include "ns3/applications-module.h" -#include "ns3/internet-module.h" -#include "ns3/simple-wireless-module.h" - - -// This file is used to test the fixed contention option. -// When this feature is enabled, all nodes within a certain -// range (user specified, defaults to the tx range) act -// like contention and are used to reduce the datarate to -// data rate/ # neighbors -// -// The scenario has the following: -// - 20 nodes -// - node 0 is at the center of a circle -// - nodes 1-19 are randomly placed on a circle of radius 100 -// - random mobility within the circle -// - simple wireless model has: -// + constant error rate of 0 -// + tx range of 50 -// + No queue -// + fixed contention enabled -// + fixed contention range is defaulted to 50 but is user configurable -// - OLSR used for routing -// - On/Off application used for node 0 to send 1Mb/s to all 19 neighbor nodes - -// By changing the contention range, the effective data rate will decrease. - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE ("fixed_contention_test"); - -uint32_t app_count_sent = 0; -uint32_t app_count_recv = 0; -uint32_t pkts_sent_data = 0; -uint32_t pkts_rcvd_data = 0; -uint32_t pkts_sent_cntl = 0; - -// variables for queue latency: overall, data and control -double_t avg_queue_latency = 0.0; -uint32_t queue_pkt_count = 0; -double_t avg_queue_latency_data = 0.0; -uint32_t queue_pkt_count_data = 0; -double_t avg_queue_latency_cntl = 0.0; -uint32_t queue_pkt_count_cntl = 0; - -#define APP_PKT_SIZE 1000 -std::string PktSize = "1000"; - -#define NUM_NODES 101 // node 0 is source + N neighbors -uint32_t pkts_rcvd_by_node[NUM_NODES]; - -uint32_t nodePlacementRadius = 100; - -// ****************************************************************** -// This function supports OLSR when running on Simple Wireless -// ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) -{ - // Figure out if this is OLSR or data - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_sent_data++; - } - else - { - pkts_sent_cntl++; - } -} - - -static void MacRxSuccess (std::string context, Ptr p) -{ - int id = atoi(context.c_str()); - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_by_node[id]++; - pkts_rcvd_data++; - } -} - -// ****************************************************************** -// This function supports Simple Wireless -// ****************************************************************** -static void QueueLatencyStats (Ptr p, Time latency) -{ - double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; - - queue_pkt_count++; - avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; - - // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. - // Packet passed in this trace still has the Ethernet header - if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) - { - queue_pkt_count_data++; - avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; - //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } - else - { - queue_pkt_count_cntl++; - avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; - //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } - -} - - -// ****************************************************************** -// These functions support OLSR and are related to the Applications -// ****************************************************************** - -static void SinkReceivedBytes (Ptr p, const Address & from) -{ - app_count_recv++; - //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; -} - -static void AppSendBytes (Ptr p) -{ - app_count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; -} - - -// ****************************************************************** -// MAIN -// ****************************************************************** - -int -main (int argc, char *argv[]) -{ - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 65; - bool collectPcap = false; - double dataRate = 10000000.0; - double contentionRange = 50.0; - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.AddValue ("contentionRange", "Distance to use for simple wireless contention range", contentionRange); - cmd.Parse (argc,argv); - - std::cout << "Running scenario for " << simtime << " seconds with contention range "<< contentionRange << std::endl; - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer myNodes; - myNodes.Create (NUM_NODES); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - phy->setErrorRate(0.0); - phy->setErrorModelType(CONSTANT); - phy->EnableFixedContention(); - phy->SetFixedContentionRange(contentionRange); - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "CONTENTION_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // Define positions. - ObjectFactory pos; - pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); - pos.Set ("X", DoubleValue (0.0)); - pos.Set ("Y", DoubleValue (0.0)); - pos.Set ("rho", DoubleValue (nodePlacementRadius)); - Ptr positionAlloc = pos.Create ()->GetObject (); - - // *********************************************************************** - // Define and install random mobility. Here we are using the circle set up above - // as the position allocator for mobility (i.e., the area they can move in) - // *********************************************************************** - MobilityHelper mobility; - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (myNodes); - - // print starting positions - for (it = n.Begin (); it != n.End (); ++it) - { - // get node ptr, position and node id - Ptr node = *it; - Ptr mob = node->GetObject (); - int id = node->GetId(); - - // set up source node - if (id == 0) - { - // placed at the center and is the source node! - mob->SetPosition (Vector (0.0,0.0,0.0)); - } - Vector pos = mob->GetPosition (); - double distance = sqrt(pos.x*pos.x + pos.y*pos.y); - std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: "<< distance << std::endl; - } - - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (myNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (myNodes.Get (0)); - std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - } - else - { - // on all other nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); - ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); - apps_sink.Start (Seconds (0.0)); - //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; - pkts_rcvd_by_node[id] = 0; - } - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // stats - // *********************************************************************** - double rcvPercentData = 0.0; - uint32_t dataDropped = app_count_sent*(NUM_NODES -1) - app_count_recv; - if (app_count_sent) - rcvPercentData = ((double)app_count_recv/((double)app_count_sent*(NUM_NODES -1)))*100.0; - - std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv - << "\nControl Packets Sent: " << pkts_sent_cntl - << "\nData Packets Sent: " << pkts_sent_data - << "\nData Packets Received: " << pkts_rcvd_data - << "\nData Packets Dropped: " << dataDropped - << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0)< dev = devices.Get(0); - PointerValue val; - dev->GetAttribute("TxQueue", val); - Ptr queue = val.Get(); - Ptr dropHead = DynamicCast(queue); - std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets() << std::endl; - - for (int i = 1; i < NUM_NODES; i++) - { - //std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; - } - - - NS_LOG_INFO ("Run Completed Successfully"); - - return 0; -} +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * All rights reserved. + * + * 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 +*/ + +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include +#include +#include +#include +#include +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/olsr-module.h" +#include "ns3/mobility-module.h" +#include "ns3/applications-module.h" +#include "ns3/internet-module.h" +#include "ns3/simple-wireless-module.h" + + +// This file is used to test the fixed contention option. +// When this feature is enabled, all nodes within a certain +// range (user specified, defaults to the tx range) act +// like contention and are used to reduce the datarate to +// data rate/ # neighbors +// +// The scenario has the following: +// - 20 nodes +// - node 0 is at the center of a circle +// - nodes 1-19 are randomly placed on a circle of radius 100 +// - random mobility within the circle +// - simple wireless model has: +// + constant error rate of 0 +// + tx range of 50 +// + No queue +// + fixed contention enabled +// + fixed contention range is defaulted to 50 but is user configurable +// - OLSR used for routing +// - On/Off application used for node 0 to send 1Mb/s to all 19 neighbor nodes + +// By changing the contention range, the effective data rate will decrease. + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("fixed_contention_test"); + +uint32_t app_count_sent = 0; +uint32_t app_count_recv = 0; +uint32_t pkts_sent_data = 0; +uint32_t pkts_rcvd_data = 0; +uint32_t pkts_sent_cntl = 0; + +// variables for queue latency: overall, data and control +double_t avg_queue_latency = 0.0; +uint32_t queue_pkt_count = 0; +double_t avg_queue_latency_data = 0.0; +uint32_t queue_pkt_count_data = 0; +double_t avg_queue_latency_cntl = 0.0; +uint32_t queue_pkt_count_cntl = 0; + +#define APP_PKT_SIZE 1000 +std::string PktSize = "1000"; + +#define NUM_NODES 101 // node 0 is source + N neighbors +uint32_t pkts_rcvd_by_node[NUM_NODES]; + +uint32_t nodePlacementRadius = 100; + +// ****************************************************************** +// This function supports OLSR when running on Simple Wireless +// ****************************************************************** +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +{ + // Figure out if this is OLSR or data + if (p->GetSize() == (APP_PKT_SIZE + 28)) + { + pkts_sent_data++; + } + else + { + pkts_sent_cntl++; + } +} + + +static void MacRxSuccess (std::string context, Ptr p) +{ + int id = atoi(context.c_str()); + if (p->GetSize() == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_by_node[id]++; + pkts_rcvd_data++; + } +} + +// ****************************************************************** +// This function supports Simple Wireless +// ****************************************************************** +static void QueueLatencyStats (Ptr p, Time latency) +{ + double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; + + queue_pkt_count++; + avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; + + // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. + // Packet passed in this trace still has the Ethernet header + if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) + { + queue_pkt_count_data++; + avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; + //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } + else + { + queue_pkt_count_cntl++; + avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; + //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } + +} + + +// ****************************************************************** +// These functions support OLSR and are related to the Applications +// ****************************************************************** + +static void SinkReceivedBytes (Ptr p, const Address & from) +{ + app_count_recv++; + //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; +} + +static void AppSendBytes (Ptr p) +{ + app_count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; +} + + +// ****************************************************************** +// MAIN +// ****************************************************************** + +int +main (int argc, char *argv[]) +{ + NodeContainer::Iterator it; + NodeContainer::Iterator it2; + std::list destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 65; + bool collectPcap = false; + double dataRate = 10000000.0; + double contentionRange = 50.0; + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.AddValue ("contentionRange", "Distance to use for simple wireless contention range", contentionRange); + cmd.Parse (argc,argv); + + std::cout << "Running scenario for " << simtime << " seconds with contention range "<< contentionRange << std::endl; + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer myNodes; + myNodes.Create (NUM_NODES); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); + + // create channel + Ptr phy = CreateObject (); + phy->setErrorRate(0.0); + phy->setErrorModelType(CONSTANT); + phy->EnableFixedContention(); + phy->SetFixedContentionRange(contentionRange); + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel(phy); + simpleWireless->SetNode(node); + simpleWireless->SetAddress(Mac48Address::Allocate ()); + simpleWireless->SetDataRate((DataRate (dataRate))); + + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue(queue); + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId(); + simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "CONTENTION_node_" << node->GetId() << ".pcap"; + fileStr = stringStream.str(); + simpleWireless->EnablePcapAll(fileStr); + } + } + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // Define positions. + ObjectFactory pos; + pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); + pos.Set ("X", DoubleValue (0.0)); + pos.Set ("Y", DoubleValue (0.0)); + pos.Set ("rho", DoubleValue (nodePlacementRadius)); + Ptr positionAlloc = pos.Create ()->GetObject (); + + // *********************************************************************** + // Define and install random mobility. Here we are using the circle set up above + // as the position allocator for mobility (i.e., the area they can move in) + // *********************************************************************** + MobilityHelper mobility; + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (myNodes); + + // print starting positions + for (it = n.Begin (); it != n.End (); ++it) + { + // get node ptr, position and node id + Ptr node = *it; + Ptr mob = node->GetObject (); + int id = node->GetId(); + + // set up source node + if (id == 0) + { + // placed at the center and is the source node! + mob->SetPosition (Vector (0.0,0.0,0.0)); + } + Vector pos = mob->GetPosition (); + double distance = sqrt(pos.x*pos.x + pos.y*pos.y); + std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: "<< distance << std::endl; + } + + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (myNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId(); + + if (id == 0) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (myNodes.Get (0)); + std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + } + else + { + // on all other nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); + ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); + apps_sink.Start (Seconds (0.0)); + //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; + pkts_rcvd_by_node[id] = 0; + } + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds(simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // stats + // *********************************************************************** + double rcvPercentData = 0.0; + uint32_t dataDropped = app_count_sent*(NUM_NODES -1) - app_count_recv; + if (app_count_sent) + rcvPercentData = ((double)app_count_recv/((double)app_count_sent*(NUM_NODES -1)))*100.0; + + std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv + << "\nControl Packets Sent: " << pkts_sent_cntl + << "\nData Packets Sent: " << pkts_sent_data + << "\nData Packets Received: " << pkts_rcvd_data + << "\nData Packets Dropped: " << dataDropped + << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0)< dev = devices.Get(0); + PointerValue val; + dev->GetAttribute("TxQueue", val); + Ptr queue = val.Get(); + Ptr dropHead = DynamicCast(queue); + std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets() << std::endl; + + for (int i = 1; i < NUM_NODES; i++) + { + //std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; + } + + + NS_LOG_INFO ("Run Completed Successfully"); + + return 0; +} diff --git a/examples/mixed_directional_network.cc b/examples/mixed_directional_network.cc index 1e8d96d..8de4f79 100644 --- a/examples/mixed_directional_network.cc +++ b/examples/mixed_directional_network.cc @@ -1,321 +1,321 @@ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * All rights reserved. - * - * 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 -*/ - -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - -// This uses global routing -// -// Network topology -// -// 1 -// || -// || -// 7--- || ---5 -// |---4======0======2-| -// 8--- || ---6 -// || -// || -// 3 - -// Node 0 is placed at the origin (0,0) -// Nodes 1, 2, 3, 4 are 50m away from Node 0 -// Nodes 5, 6 are placed 10m away from Node 2 -// Nodes 7, 8 are placed 10m away from Node 4 - - -// two wireless networks: -// - one network has all nodes and has a range of 40m -// - second network has node 0, 1, 2, 3, 4 and has a range of 100m -// + node 0 uses a directional network with node 1 and 4 as neighbors -// + node 2 uses a directional network but has no neighbors -// Note that nodes 0, 1, 2, 3, 4 each have two interfaces - -// Traffic: -// - Node 0 sends broadcast traffic. Received at nodes 1 & 4 -// - Node 2 sends broadcast traffic. Received at nodes 5 & 6 - - -#include -#include -#include -#include -#include - -#include "ns3/core-module.h" -#include "ns3/network-module.h" -#include "ns3/mobility-module.h" -#include "ns3/applications-module.h" -#include "ns3/internet-module.h" -#include "ns3/simple-wireless-module.h" - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE ("MixedDirectionalNetworkExample"); - -uint32_t count_sent = 0; -uint32_t count_recv = 0; - - -// ****************************************************************** -// These functions support the Applications -// ****************************************************************** -static void SinkReceivedBytes (Ptr p, const Address & from) -{ - count_recv++; - //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; -} - -static void AppSendBytes (Ptr p) -{ - count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; -} - -int -main (int argc, char *argv[]) -{ - NodeContainer::Iterator it; - double simtime = 60; - double dataRate = 10000000.0; - - NodeContainer n; - n.Create (9); - // create node container for the second network - NodeContainer n01234 = NodeContainer (n.Get (0), n.Get (1), n.Get (2), n.Get (3), n.Get (4)); - - InternetStackHelper internet; - internet.Install (n); - - - // Create container to hold devices - NetDeviceContainer dAll; - NetDeviceContainer d2; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Create error model and set as default - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // *********************************************************************** - // create first network - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (40.0)); - Ptr phy1 = CreateObject (); - phy1->setErrorRate(0.0); - phy1->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless1 = CreateObject (); - simpleWireless1->SetChannel(phy1); - simpleWireless1->SetNode(node); - simpleWireless1->SetAddress(Mac48Address::Allocate ()); - simpleWireless1->SetDataRate((DataRate (dataRate))); - - // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless1->SetQueue(queue); - - node->AddDevice (simpleWireless1); - dAll.Add (simpleWireless1); - } - - // *********************************************************************** - // create second network - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - Ptr phy2 = CreateObject (); - phy2->setErrorRate(0.0); - phy2->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - // network 2 is only on node 0, 1, 2, 3, 4 - if (id < 5) - { - // create device - Ptr simpleWireless2 = CreateObject (); - simpleWireless2->SetChannel(phy2); - simpleWireless2->SetNode(node); - simpleWireless2->SetAddress(Mac48Address::Allocate ()); - simpleWireless2->SetDataRate((DataRate (dataRate))); - - std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress() << std::endl; - - // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless2->SetQueue(queue); - - node->AddDevice (simpleWireless2); - d2.Add (simpleWireless2); - } - } - - // ------------------------------------------------------------------------ - // Set up directional network. Do this after adding all the devices because - // we need to get MAC addresses for the neighbors we want to add - // network 2 is only on node 0, 1, 2, 3, 4 - // node 0 has directional neighbors to nodes 1, 4 - // node 2 has directional networking but no neighbors - - // Get node 0, 1, 2, 4 device on the container. MUST use d2 container - // since that is the container with the SW interfaces that use directional - // network. - // In this example we get the ptr to the NetDevice using the index in the - // containter. We added them in numerical order so we know that 0 is node0, - // 1 is node 1, etc. - Ptr dev0 = d2.Get(0); - Ptr dev1 = d2.Get(1); - Ptr dev2 = d2.Get(2); - Ptr dev4 = d2.Get(4); - Ptr swDev0 = DynamicCast(dev0); - Ptr swDev1 = DynamicCast(dev1); - Ptr swDev2 = DynamicCast(dev2); - Ptr swDev4 = DynamicCast(dev4); - - // node 0 has directional neighbors to nodes 1, 4 - swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - // Here we use the function that takes map to add multiple neighbors one call - std::map nbrSet; - // Get mac addr of node 1 and add to map - Address addr = swDev1->GetAddress(); - Mac48Address macAddr = Mac48Address::ConvertFrom (addr); - nbrSet.insert(std::pair(1, macAddr)); - std::cout << "Adding node 1 with mac address " << macAddr<< std::endl; - // Get mac addr of node 4 and add to map - addr = swDev4->GetAddress(); - macAddr = Mac48Address::ConvertFrom (addr); - nbrSet.insert(std::pair(4, macAddr)); - std::cout << "Adding node 4 with mac address " << macAddr<< std::endl; - // Now add to dev on node 0 - swDev0->AddDirectionalNeighbors(nbrSet); - - // Now just set the fixed neigbor feature enabled on dev 2 but don't - // add any neighbors because it has none - swDev2->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - // ------------------------------------------------------------------------ - - - // Later, we add IP addresses. - Ipv4AddressHelper ipv4; - ipv4.SetBase ("10.1.1.0", "255.255.255.0"); - Ipv4InterfaceContainer interfaces = ipv4.Assign (dAll); - - ipv4.SetBase ("10.1.2.0", "255.255.255.0"); - ipv4.Assign (d2); - - // Create router nodes, initialize routing database and set up the routing - // tables in the nodes. - Ipv4GlobalRoutingHelper::PopulateRoutingTables (); - - // *********************************************************************** - // Define positions. - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); - positionAlloc->Add (Vector (50.0, 0.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); - positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); - positionAlloc->Add (Vector (60.0, -2.0, 0.0)); - positionAlloc->Add (Vector (60.0, 2.0, 0.0)); - positionAlloc->Add (Vector (-60.0, 2.0, 0.0)); - positionAlloc->Add (Vector (-60.0, -2.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (n); - - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("1000")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (n.Get (0)); - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 1.0)); - } - else if (id == 2) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("1000")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (n.Get (2)); - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 1.0)); - } - - // on nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); - ApplicationContainer apps_sink = sink.Install (n.Get (id)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node " << id << " installed sink " << std::endl; - - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - std::cout << "Sent: " << count_sent << "\nReceive Count: " << count_recv << std::endl; - - - NS_LOG_INFO ("Run Completed Successfully"); -} +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * All rights reserved. + * + * 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 +*/ + +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +// This uses global routing +// +// Network topology +// +// 1 +// || +// || +// 7--- || ---5 +// |---4======0======2-| +// 8--- || ---6 +// || +// || +// 3 + +// Node 0 is placed at the origin (0,0) +// Nodes 1, 2, 3, 4 are 50m away from Node 0 +// Nodes 5, 6 are placed 10m away from Node 2 +// Nodes 7, 8 are placed 10m away from Node 4 + + +// two wireless networks: +// - one network has all nodes and has a range of 40m +// - second network has node 0, 1, 2, 3, 4 and has a range of 100m +// + node 0 uses a directional network with node 1 and 4 as neighbors +// + node 2 uses a directional network but has no neighbors +// Note that nodes 0, 1, 2, 3, 4 each have two interfaces + +// Traffic: +// - Node 0 sends broadcast traffic. Received at nodes 1 & 4 +// - Node 2 sends broadcast traffic. Received at nodes 5 & 6 + + +#include +#include +#include +#include +#include + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/mobility-module.h" +#include "ns3/applications-module.h" +#include "ns3/internet-module.h" +#include "ns3/simple-wireless-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("MixedDirectionalNetworkExample"); + +uint32_t count_sent = 0; +uint32_t count_recv = 0; + + +// ****************************************************************** +// These functions support the Applications +// ****************************************************************** +static void SinkReceivedBytes (Ptr p, const Address & from) +{ + count_recv++; + //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; +} + +static void AppSendBytes (Ptr p) +{ + count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; +} + +int +main (int argc, char *argv[]) +{ + NodeContainer::Iterator it; + double simtime = 60; + double dataRate = 10000000.0; + + NodeContainer n; + n.Create (9); + // create node container for the second network + NodeContainer n01234 = NodeContainer (n.Get (0), n.Get (1), n.Get (2), n.Get (3), n.Get (4)); + + InternetStackHelper internet; + internet.Install (n); + + + // Create container to hold devices + NetDeviceContainer dAll; + NetDeviceContainer d2; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Create error model and set as default + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); + + // *********************************************************************** + // create first network + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (40.0)); + Ptr phy1 = CreateObject (); + phy1->setErrorRate(0.0); + phy1->setErrorModelType(CONSTANT); + + // create simple wireless device on each node + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless1 = CreateObject (); + simpleWireless1->SetChannel(phy1); + simpleWireless1->SetNode(node); + simpleWireless1->SetAddress(Mac48Address::Allocate ()); + simpleWireless1->SetDataRate((DataRate (dataRate))); + + // Set queue type to use + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless1->SetQueue(queue); + + node->AddDevice (simpleWireless1); + dAll.Add (simpleWireless1); + } + + // *********************************************************************** + // create second network + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + Ptr phy2 = CreateObject (); + phy2->setErrorRate(0.0); + phy2->setErrorModelType(CONSTANT); + + // create simple wireless device on each node + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId(); + + // network 2 is only on node 0, 1, 2, 3, 4 + if (id < 5) + { + // create device + Ptr simpleWireless2 = CreateObject (); + simpleWireless2->SetChannel(phy2); + simpleWireless2->SetNode(node); + simpleWireless2->SetAddress(Mac48Address::Allocate ()); + simpleWireless2->SetDataRate((DataRate (dataRate))); + + std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress() << std::endl; + + // Set queue type to use + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless2->SetQueue(queue); + + node->AddDevice (simpleWireless2); + d2.Add (simpleWireless2); + } + } + + // ------------------------------------------------------------------------ + // Set up directional network. Do this after adding all the devices because + // we need to get MAC addresses for the neighbors we want to add + // network 2 is only on node 0, 1, 2, 3, 4 + // node 0 has directional neighbors to nodes 1, 4 + // node 2 has directional networking but no neighbors + + // Get node 0, 1, 2, 4 device on the container. MUST use d2 container + // since that is the container with the SW interfaces that use directional + // network. + // In this example we get the ptr to the NetDevice using the index in the + // containter. We added them in numerical order so we know that 0 is node0, + // 1 is node 1, etc. + Ptr dev0 = d2.Get(0); + Ptr dev1 = d2.Get(1); + Ptr dev2 = d2.Get(2); + Ptr dev4 = d2.Get(4); + Ptr swDev0 = DynamicCast(dev0); + Ptr swDev1 = DynamicCast(dev1); + Ptr swDev2 = DynamicCast(dev2); + Ptr swDev4 = DynamicCast(dev4); + + // node 0 has directional neighbors to nodes 1, 4 + swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + // Here we use the function that takes map to add multiple neighbors one call + std::map nbrSet; + // Get mac addr of node 1 and add to map + Address addr = swDev1->GetAddress(); + Mac48Address macAddr = Mac48Address::ConvertFrom (addr); + nbrSet.insert(std::pair(1, macAddr)); + std::cout << "Adding node 1 with mac address " << macAddr<< std::endl; + // Get mac addr of node 4 and add to map + addr = swDev4->GetAddress(); + macAddr = Mac48Address::ConvertFrom (addr); + nbrSet.insert(std::pair(4, macAddr)); + std::cout << "Adding node 4 with mac address " << macAddr<< std::endl; + // Now add to dev on node 0 + swDev0->AddDirectionalNeighbors(nbrSet); + + // Now just set the fixed neigbor feature enabled on dev 2 but don't + // add any neighbors because it has none + swDev2->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + // ------------------------------------------------------------------------ + + + // Later, we add IP addresses. + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces = ipv4.Assign (dAll); + + ipv4.SetBase ("10.1.2.0", "255.255.255.0"); + ipv4.Assign (d2); + + // Create router nodes, initialize routing database and set up the routing + // tables in the nodes. + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + // *********************************************************************** + // Define positions. + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); + positionAlloc->Add (Vector (50.0, 0.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); + positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); + positionAlloc->Add (Vector (60.0, -2.0, 0.0)); + positionAlloc->Add (Vector (60.0, 2.0, 0.0)); + positionAlloc->Add (Vector (-60.0, 2.0, 0.0)); + positionAlloc->Add (Vector (-60.0, -2.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (n); + + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId(); + + if (id == 0) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("1000")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (n.Get (0)); + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 1.0)); + } + else if (id == 2) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("1000")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (n.Get (2)); + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 1.0)); + } + + // on nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); + ApplicationContainer apps_sink = sink.Install (n.Get (id)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node " << id << " installed sink " << std::endl; + + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds(simtime)); + Simulator::Run (); + Simulator::Destroy (); + + std::cout << "Sent: " << count_sent << "\nReceive Count: " << count_recv << std::endl; + + + NS_LOG_INFO ("Run Completed Successfully"); +} diff --git a/examples/multiple_interface_example.cc b/examples/multiple_interface_example.cc index 67cbb53..96147d2 100644 --- a/examples/multiple_interface_example.cc +++ b/examples/multiple_interface_example.cc @@ -1,290 +1,290 @@ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * All rights reserved. - * - * 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 -*/ - -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - -// Network topology -// -// 0 ------------ 1 --- simple wireless network -// ++++++++++++ +++ directional simple wireless network -// -// This network has 2 nodes and 2 interfaces per node. -// Both interfaces are simple wireless -// One interface on each node is directional -// -// Node 0 sends traffic over both interfaces. part way into the simulation, -// node 0 loses its directional neighbor and the traffic over that link stops -// being received. - - - - -#include -#include -#include -#include -#include - -#include "ns3/core-module.h" -#include "ns3/network-module.h" -#include "ns3/mobility-module.h" -#include "ns3/applications-module.h" -#include "ns3/internet-module.h" -#include "ns3/simple-wireless-module.h" - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE ("MixedDirectionalNetworkExample"); - -uint32_t count_sent_app1 = 0; -uint32_t count_recv_app1 = 0; -uint32_t count_sent_app2 = 0; -uint32_t count_recv_app2 = 0; - - -// ****************************************************************** -// These functions support the Applications -// ****************************************************************** -static void SinkReceivedBytes (Ptr p, const Address & from) -{ - if (p->GetSize() > 500) - count_recv_app1++; - else - count_recv_app2++; - - - std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes."<< std::endl; -} - -static void AppSendBytes (Ptr p) -{ - if (p->GetSize() > 500) - count_sent_app1++; - else - count_sent_app2++; - - std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. "<< std::endl; -} - - -static void removeDirectionalNbr (Ptr sw) -{ - // remove directional neigbhor 1 - sw->DeleteDirectionalNeighbor(1); -} - -int -main (int argc, char *argv[]) -{ - NodeContainer::Iterator it; - double simtime = 126; - double dataRate = 10000000.0; //10Mb/s - - // create node container for the omni network - NodeContainer n1; - n1.Create (2); - // create node container for the directional network - NodeContainer n2_dir = NodeContainer (n1.Get (0), n1.Get (1)); - - - InternetStackHelper internet; - internet.Install (n1); - - - // Create container to hold devices - NetDeviceContainer d1_omni; - NetDeviceContainer d2_dir; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Create error model and set as default - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // *********************************************************************** - // create first network - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // channel - Ptr phy1 = CreateObject (); - phy1->setErrorRate(0.0); - phy1->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n1.Begin (); it != n1.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless1 = CreateObject (); - simpleWireless1->SetChannel(phy1); - simpleWireless1->SetNode(node); - simpleWireless1->SetAddress(Mac48Address::Allocate ()); - simpleWireless1->SetDataRate((DataRate (dataRate))); - - // create queue type - Ptr queue = CreateObject (); - simpleWireless1->SetQueue(queue); - - node->AddDevice (simpleWireless1); - d1_omni.Add (simpleWireless1); - } - - // *********************************************************************** - // create second network - Ptr phy2 = CreateObject (); - phy2->setErrorRate(0.0); - phy2->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n2_dir.Begin (); it != n2_dir.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - // create device - Ptr simpleWireless2 = CreateObject (); - simpleWireless2->SetChannel(phy2); - simpleWireless2->SetNode(node); - simpleWireless2->SetAddress(Mac48Address::Allocate ()); - simpleWireless2->SetDataRate((DataRate (dataRate))); - std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress() << std::endl; - - // create queue type - Ptr queue = CreateObject (); - simpleWireless2->SetQueue(queue); - - if (id == 0) - { - // schedule function which removed node 0's directional neighbor - Simulator::Schedule (Seconds (60.0), &removeDirectionalNbr, simpleWireless2); - } - - node->AddDevice (simpleWireless2); - d2_dir.Add (simpleWireless2); - } - - - // *********************************************************************** - // Set up directional network. Do this after adding all the devices because - // we need to get MAC addresses for the neighbors we want to add - - // Get node 0, 1 device on the container. MUST use d2_dir container - // since that is the container with the SW interfaces that use directional - // network. - // In this example we get the ptr to the NetDevice using the index in the - // containter. We added them in numerical order so we know that 0 is node0, - // 1 is node 1, etc. - Ptr dev0 = d2_dir.Get(0); - Ptr dev1 = d2_dir.Get(1); - Ptr swDev0 = DynamicCast(dev0); - Ptr swDev1 = DynamicCast(dev1); - - // node 0 has directional neighbors to node 1 - swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - // Here we use the function that takes a single node to add - Address addr = swDev1->GetAddress(); - Mac48Address macAddr = Mac48Address::ConvertFrom (addr); - swDev0->AddDirectionalNeighbor(1,macAddr); - - // node 1 has directional neighbors to node 0 - swDev1->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - addr = swDev0->GetAddress(); - macAddr = Mac48Address::ConvertFrom (addr); - swDev1->AddDirectionalNeighbor(0,macAddr); - - - // *********************************************************************** - // add IP addresses. - Ipv4AddressHelper ipv4; - ipv4.SetBase ("10.1.1.0", "255.255.255.0"); - Ipv4InterfaceContainer interfaces = ipv4.Assign (d1_omni); - - ipv4.SetBase ("10.1.2.0", "255.255.255.0"); - ipv4.Assign (d2_dir); - - // Create router nodes, initialize routing database and set up the routing - // tables in the nodes. - Ipv4GlobalRoutingHelper::PopulateRoutingTables (); - - // *********************************************************************** - // Define positions. - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (n1); - - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on node 1 - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); - ApplicationContainer apps_sink = sink.Install (n1.Get (1)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node 1 installed sink " << std::endl; - - // start the OnOff app on source to destinations in the omni network - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("1000")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - ApplicationContainer apps1 = onoff.Install (n1.Get (0)); - apps1.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - apps1.Start (Seconds (5.0)); - apps1.Stop (Seconds (simtime - 1.0)); - - // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. - // start the OnOff app on source to destinations in the directional network - onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.255"), 8080)); - //onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.2"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("500")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - ApplicationContainer apps2 = onoff.Install (n2_dir.Get (0)); - apps2.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - apps2.Start (Seconds (5.0)); - apps2.Stop (Seconds (simtime - 1.0)); - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - std::cout << "App1 Sent: " << count_sent_app1 << " Received: " << count_recv_app1 << std::endl; - std::cout << "App2 Sent: " << count_sent_app2 << " Received: " << count_recv_app2 << std::endl; - - - NS_LOG_INFO ("Run Completed Successfully"); -} +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * All rights reserved. + * + * 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 +*/ + +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +// Network topology +// +// 0 ------------ 1 --- simple wireless network +// ++++++++++++ +++ directional simple wireless network +// +// This network has 2 nodes and 2 interfaces per node. +// Both interfaces are simple wireless +// One interface on each node is directional +// +// Node 0 sends traffic over both interfaces. part way into the simulation, +// node 0 loses its directional neighbor and the traffic over that link stops +// being received. + + + + +#include +#include +#include +#include +#include + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/mobility-module.h" +#include "ns3/applications-module.h" +#include "ns3/internet-module.h" +#include "ns3/simple-wireless-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("MixedDirectionalNetworkExample"); + +uint32_t count_sent_app1 = 0; +uint32_t count_recv_app1 = 0; +uint32_t count_sent_app2 = 0; +uint32_t count_recv_app2 = 0; + + +// ****************************************************************** +// These functions support the Applications +// ****************************************************************** +static void SinkReceivedBytes (Ptr p, const Address & from) +{ + if (p->GetSize() > 500) + count_recv_app1++; + else + count_recv_app2++; + + + std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes."<< std::endl; +} + +static void AppSendBytes (Ptr p) +{ + if (p->GetSize() > 500) + count_sent_app1++; + else + count_sent_app2++; + + std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. "<< std::endl; +} + + +static void removeDirectionalNbr (Ptr sw) +{ + // remove directional neigbhor 1 + sw->DeleteDirectionalNeighbor(1); +} + +int +main (int argc, char *argv[]) +{ + NodeContainer::Iterator it; + double simtime = 126; + double dataRate = 10000000.0; //10Mb/s + + // create node container for the omni network + NodeContainer n1; + n1.Create (2); + // create node container for the directional network + NodeContainer n2_dir = NodeContainer (n1.Get (0), n1.Get (1)); + + + InternetStackHelper internet; + internet.Install (n1); + + + // Create container to hold devices + NetDeviceContainer d1_omni; + NetDeviceContainer d2_dir; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Create error model and set as default + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); + + // *********************************************************************** + // create first network + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // channel + Ptr phy1 = CreateObject (); + phy1->setErrorRate(0.0); + phy1->setErrorModelType(CONSTANT); + + // create simple wireless device on each node + for (it = n1.Begin (); it != n1.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless1 = CreateObject (); + simpleWireless1->SetChannel(phy1); + simpleWireless1->SetNode(node); + simpleWireless1->SetAddress(Mac48Address::Allocate ()); + simpleWireless1->SetDataRate((DataRate (dataRate))); + + // create queue type + Ptr queue = CreateObject (); + simpleWireless1->SetQueue(queue); + + node->AddDevice (simpleWireless1); + d1_omni.Add (simpleWireless1); + } + + // *********************************************************************** + // create second network + Ptr phy2 = CreateObject (); + phy2->setErrorRate(0.0); + phy2->setErrorModelType(CONSTANT); + + // create simple wireless device on each node + for (it = n2_dir.Begin (); it != n2_dir.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId(); + + // create device + Ptr simpleWireless2 = CreateObject (); + simpleWireless2->SetChannel(phy2); + simpleWireless2->SetNode(node); + simpleWireless2->SetAddress(Mac48Address::Allocate ()); + simpleWireless2->SetDataRate((DataRate (dataRate))); + std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress() << std::endl; + + // create queue type + Ptr queue = CreateObject (); + simpleWireless2->SetQueue(queue); + + if (id == 0) + { + // schedule function which removed node 0's directional neighbor + Simulator::Schedule (Seconds (60.0), &removeDirectionalNbr, simpleWireless2); + } + + node->AddDevice (simpleWireless2); + d2_dir.Add (simpleWireless2); + } + + + // *********************************************************************** + // Set up directional network. Do this after adding all the devices because + // we need to get MAC addresses for the neighbors we want to add + + // Get node 0, 1 device on the container. MUST use d2_dir container + // since that is the container with the SW interfaces that use directional + // network. + // In this example we get the ptr to the NetDevice using the index in the + // containter. We added them in numerical order so we know that 0 is node0, + // 1 is node 1, etc. + Ptr dev0 = d2_dir.Get(0); + Ptr dev1 = d2_dir.Get(1); + Ptr swDev0 = DynamicCast(dev0); + Ptr swDev1 = DynamicCast(dev1); + + // node 0 has directional neighbors to node 1 + swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + // Here we use the function that takes a single node to add + Address addr = swDev1->GetAddress(); + Mac48Address macAddr = Mac48Address::ConvertFrom (addr); + swDev0->AddDirectionalNeighbor(1,macAddr); + + // node 1 has directional neighbors to node 0 + swDev1->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + addr = swDev0->GetAddress(); + macAddr = Mac48Address::ConvertFrom (addr); + swDev1->AddDirectionalNeighbor(0,macAddr); + + + // *********************************************************************** + // add IP addresses. + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces = ipv4.Assign (d1_omni); + + ipv4.SetBase ("10.1.2.0", "255.255.255.0"); + ipv4.Assign (d2_dir); + + // Create router nodes, initialize routing database and set up the routing + // tables in the nodes. + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + // *********************************************************************** + // Define positions. + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (n1); + + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on node 1 + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); + ApplicationContainer apps_sink = sink.Install (n1.Get (1)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node 1 installed sink " << std::endl; + + // start the OnOff app on source to destinations in the omni network + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("1000")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + ApplicationContainer apps1 = onoff.Install (n1.Get (0)); + apps1.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + apps1.Start (Seconds (5.0)); + apps1.Stop (Seconds (simtime - 1.0)); + + // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. + // start the OnOff app on source to destinations in the directional network + onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.255"), 8080)); + //onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.2"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("500")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + ApplicationContainer apps2 = onoff.Install (n2_dir.Get (0)); + apps2.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + apps2.Start (Seconds (5.0)); + apps2.Stop (Seconds (simtime - 1.0)); + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds(simtime)); + Simulator::Run (); + Simulator::Destroy (); + + std::cout << "App1 Sent: " << count_sent_app1 << " Received: " << count_recv_app1 << std::endl; + std::cout << "App2 Sent: " << count_sent_app2 << " Received: " << count_recv_app2 << std::endl; + + + NS_LOG_INFO ("Run Completed Successfully"); +} diff --git a/examples/queue_test.cc b/examples/queue_test.cc index 9948629..57a96fc 100644 --- a/examples/queue_test.cc +++ b/examples/queue_test.cc @@ -1,412 +1,412 @@ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * All rights reserved. - * - * 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 -*/ - -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - -#include -#include -#include -#include -#include -#include "ns3/core-module.h" -#include "ns3/network-module.h" -#include "ns3/olsr-module.h" -#include "ns3/mobility-module.h" -#include "ns3/applications-module.h" -#include "ns3/internet-module.h" -#include "ns3/simple-wireless-module.h" - - -// This file is used to test the queue options available: -// - no queues -// - drop queue tail (provided with ns3) -// - drop queue head (new; provided with the MIT LL simple wireless model) -// - priority queue (new; provided with the MIT LL simple wireless model) -// -// All queues are FIFO -// -// Drop Queue Tail - when queues are full, drop at the tail of the queue. That is, the -// newly received packet is dropped -// Drop Queue Head - when queues are full, drop at the head of the queue. That is, the -// oldest packet is dropped and newly received packet is inserted -// into the queue -// Priority Queue - defines two queues: control and data. Each queue is configured -// independently to be either drop head or drop tail. Differentiation -// of control and data is based on a user specified pcap filter string -// -// The scenario has the following: -// - 2 nodes placed 50 units apart with no mobility -// - simple wireless model with user configurable data rate -// - OLSR used for routing -// - On/Off application used to send 1Mb/s -// - capability to enable pcap capture -// -// Queue capabilities can be tested by changing the data rate of the simple wireless model - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE ("queue_test"); - -uint32_t app_count_sent = 0; -uint32_t app_count_recv = 0; -uint32_t pkts_sent_data = 0; -uint32_t bytes_sent_data = 0; -uint32_t pkts_sent_cntl = 0; -uint32_t bytes_sent_cntl = 0; -uint32_t pkts_rcvd_data = 0; -uint32_t pkts_rcvd_cntl = 0; - -// variables for queue latency: overall, data and control -double_t avg_queue_latency = 0.0; -uint32_t queue_pkt_count = 0; -double_t avg_queue_latency_data = 0.0; -uint32_t queue_pkt_count_data = 0; -double_t avg_queue_latency_cntl = 0.0; -uint32_t queue_pkt_count_cntl = 0; - -#define APP_PKT_SIZE 1000 -std::string PktSize = "1000"; - - -// ****************************************************************** -// This function supports OLSR when running on Simple Wireless -// ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) -{ - // Figure out if this is OLSR or data - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_sent_data++; - bytes_sent_data += p->GetSize(); - } - else - { - pkts_sent_cntl++; - bytes_sent_cntl += p->GetSize(); - } -} - - -static void MacRxSuccess (std::string context, Ptr p) -{ - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_data++; - } - else - { - pkts_rcvd_cntl++; - } - - -} - -// ****************************************************************** -// This function supports Simple Wireless -// ****************************************************************** -static void QueueLatencyStats (Ptr p, Time latency) -{ - double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; - - queue_pkt_count++; - avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; - - // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. - // Packet passed in this trace still has the Ethernet header - if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) - { - queue_pkt_count_data++; - avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; - //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } - else - { - queue_pkt_count_cntl++; - avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; - //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } - -} - - -// ****************************************************************** -// These functions support OLSR and are related to the Applications -// ****************************************************************** - -static void SinkReceivedBytes (Ptr p, const Address & from) -{ - app_count_recv++; - //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; -} - -static void AppSendBytes (Ptr p) -{ - app_count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; -} - - -// ****************************************************************** -// MAIN -// ****************************************************************** - -int -main (int argc, char *argv[]) -{ - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 120; - bool collectPcap = false; - double dataRate = 10000000.0; - std::string queueType = "DropTail"; - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.AddValue ("datarate", "Data Rate of wireless link in bits per second", dataRate); - cmd.AddValue ("queueType", "Set Queue type to NoQueue, DropHead, DropTail or PriorityHead or PriorityTail", queueType); - cmd.Parse (argc,argv); - - std::cout << "Running scenario for " << simtime << " seconds with queue type: "<< queueType <<" and data rate: " << std::fixed << std::setprecision(1) << dataRate <<"bps"<< std::endl; - - if ((queueType != "NoQueue") && (queueType != "DropHead") && (queueType != "DropTail") && (queueType != "PriorityHead") && (queueType != "PriorityTail")) - { - NS_ABORT_MSG ("Invalid queue type: Use --queueType=DropHead or --queueType=DropTail or --queueType=PriorityHead or --queueType=PriorityTail"); - } - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer NpNodes; - NpNodes.Create (2); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - phy->setErrorRate(0.0); - phy->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - - // Set queue type to use. Set nothing if NoQueue - if (queueType == "DropHead") - { - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - } - else if (queueType == "DropTail") - { - Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - } - else if (queueType == "PriorityHead") - { - Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr controlQueue = CreateObject (); - Ptr dataQueue = CreateObject (); - Ptr queue = CreateObject (); - queue->Initialize(); - queue->SetControlQueue(controlQueue); - queue->SetDataQueue(dataQueue); - simpleWireless->SetQueue(queue); - } - else if (queueType == "PriorityTail") - { - Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); - Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); - Ptr controlQueue = CreateObject (); - Ptr dataQueue = CreateObject (); - Ptr queue = CreateObject (); - queue->Initialize(); - queue->SetControlQueue(controlQueue); - queue->SetDataQueue(dataQueue); - simpleWireless->SetQueue(queue); - } - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "QUEUE_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - - // *********************************************************************** - // Define positions. Nodes are 50 apart - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector (0.0, 0.0, 0.0)); - positionAlloc->Add (Vector (50.0, 0.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (NpNodes); - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // print the olsr routing table to a file every 10 seconds - //Ptr routingStream = Create ("400node_OLSR.routes", std::ios::out); - //olsr.PrintRoutingTableAllEvery (Seconds (10), routingStream); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (NpNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on destination node - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); - ApplicationContainer apps_sink = sink.Install (NpNodes.Get (1)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node 1 installed sink to receive on " << interfaces.GetAddress (1) << std::endl; - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // Now start the OnOff app on source to destinations - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (NpNodes.Get (0)); - std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // For OLSR we need to get some stats - // *********************************************************************** - double rcvPercentData = 0.0; - uint32_t dataDropped = app_count_sent - app_count_recv; - if (app_count_sent) - rcvPercentData = ((double)app_count_recv/(double)app_count_sent)*100.0; - - double rcvPercentCntrl = 0.0; - uint32_t cntlDropped = pkts_sent_cntl - pkts_rcvd_cntl; - if (pkts_sent_cntl) - rcvPercentCntrl = ((double)pkts_rcvd_cntl/(double)pkts_sent_cntl)*100.0; - - std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv - << "\nControl Packets Sent: " << pkts_sent_cntl << "\nControl Bytes Sent: " << bytes_sent_cntl - << "\nData Packets Sent: " << pkts_sent_data << "\nData Bytes Sent: " << bytes_sent_data - << "\nControl Packets Received: " << pkts_rcvd_cntl << "\nData Packets Received: " << pkts_rcvd_data - << "\nData Packets Dropped: " << dataDropped << "\nControl Packets Dropped: " << cntlDropped - << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0) - << "\n% Control Received: " << std::fixed << std::setprecision(1) << rcvPercentCntrl << std::noshowpoint << std::setprecision(0) < +#include +#include +#include +#include +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/olsr-module.h" +#include "ns3/mobility-module.h" +#include "ns3/applications-module.h" +#include "ns3/internet-module.h" +#include "ns3/simple-wireless-module.h" + + +// This file is used to test the queue options available: +// - no queues +// - drop queue tail (provided with ns3) +// - drop queue head (new; provided with the MIT LL simple wireless model) +// - priority queue (new; provided with the MIT LL simple wireless model) +// +// All queues are FIFO +// +// Drop Queue Tail - when queues are full, drop at the tail of the queue. That is, the +// newly received packet is dropped +// Drop Queue Head - when queues are full, drop at the head of the queue. That is, the +// oldest packet is dropped and newly received packet is inserted +// into the queue +// Priority Queue - defines two queues: control and data. Each queue is configured +// independently to be either drop head or drop tail. Differentiation +// of control and data is based on a user specified pcap filter string +// +// The scenario has the following: +// - 2 nodes placed 50 units apart with no mobility +// - simple wireless model with user configurable data rate +// - OLSR used for routing +// - On/Off application used to send 1Mb/s +// - capability to enable pcap capture +// +// Queue capabilities can be tested by changing the data rate of the simple wireless model + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("queue_test"); + +uint32_t app_count_sent = 0; +uint32_t app_count_recv = 0; +uint32_t pkts_sent_data = 0; +uint32_t bytes_sent_data = 0; +uint32_t pkts_sent_cntl = 0; +uint32_t bytes_sent_cntl = 0; +uint32_t pkts_rcvd_data = 0; +uint32_t pkts_rcvd_cntl = 0; + +// variables for queue latency: overall, data and control +double_t avg_queue_latency = 0.0; +uint32_t queue_pkt_count = 0; +double_t avg_queue_latency_data = 0.0; +uint32_t queue_pkt_count_data = 0; +double_t avg_queue_latency_cntl = 0.0; +uint32_t queue_pkt_count_cntl = 0; + +#define APP_PKT_SIZE 1000 +std::string PktSize = "1000"; + + +// ****************************************************************** +// This function supports OLSR when running on Simple Wireless +// ****************************************************************** +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +{ + // Figure out if this is OLSR or data + if (p->GetSize() == (APP_PKT_SIZE + 28)) + { + pkts_sent_data++; + bytes_sent_data += p->GetSize(); + } + else + { + pkts_sent_cntl++; + bytes_sent_cntl += p->GetSize(); + } +} + + +static void MacRxSuccess (std::string context, Ptr p) +{ + if (p->GetSize() == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_data++; + } + else + { + pkts_rcvd_cntl++; + } + + +} + +// ****************************************************************** +// This function supports Simple Wireless +// ****************************************************************** +static void QueueLatencyStats (Ptr p, Time latency) +{ + double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; + + queue_pkt_count++; + avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; + + // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. + // Packet passed in this trace still has the Ethernet header + if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) + { + queue_pkt_count_data++; + avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; + //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } + else + { + queue_pkt_count_cntl++; + avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; + //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } + +} + + +// ****************************************************************** +// These functions support OLSR and are related to the Applications +// ****************************************************************** + +static void SinkReceivedBytes (Ptr p, const Address & from) +{ + app_count_recv++; + //std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes. count_recv is "<< count_recv << std::endl; +} + +static void AppSendBytes (Ptr p) +{ + app_count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; +} + + +// ****************************************************************** +// MAIN +// ****************************************************************** + +int +main (int argc, char *argv[]) +{ + NodeContainer::Iterator it; + NodeContainer::Iterator it2; + std::list destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 120; + bool collectPcap = false; + double dataRate = 10000000.0; + std::string queueType = "DropTail"; + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.AddValue ("datarate", "Data Rate of wireless link in bits per second", dataRate); + cmd.AddValue ("queueType", "Set Queue type to NoQueue, DropHead, DropTail or PriorityHead or PriorityTail", queueType); + cmd.Parse (argc,argv); + + std::cout << "Running scenario for " << simtime << " seconds with queue type: "<< queueType <<" and data rate: " << std::fixed << std::setprecision(1) << dataRate <<"bps"<< std::endl; + + if ((queueType != "NoQueue") && (queueType != "DropHead") && (queueType != "DropTail") && (queueType != "PriorityHead") && (queueType != "PriorityTail")) + { + NS_ABORT_MSG ("Invalid queue type: Use --queueType=DropHead or --queueType=DropTail or --queueType=PriorityHead or --queueType=PriorityTail"); + } + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer NpNodes; + NpNodes.Create (2); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); + + // create channel + Ptr phy = CreateObject (); + phy->setErrorRate(0.0); + phy->setErrorModelType(CONSTANT); + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel(phy); + simpleWireless->SetNode(node); + simpleWireless->SetAddress(Mac48Address::Allocate ()); + simpleWireless->SetDataRate((DataRate (dataRate))); + + // Set queue type to use. Set nothing if NoQueue + if (queueType == "DropHead") + { + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue(queue); + } + else if (queueType == "DropTail") + { + Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue(queue); + } + else if (queueType == "PriorityHead") + { + Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr controlQueue = CreateObject (); + Ptr dataQueue = CreateObject (); + Ptr queue = CreateObject (); + queue->Initialize(); + queue->SetControlQueue(controlQueue); + queue->SetDataQueue(dataQueue); + simpleWireless->SetQueue(queue); + } + else if (queueType == "PriorityTail") + { + Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); + Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); + Ptr controlQueue = CreateObject (); + Ptr dataQueue = CreateObject (); + Ptr queue = CreateObject (); + queue->Initialize(); + queue->SetControlQueue(controlQueue); + queue->SetDataQueue(dataQueue); + simpleWireless->SetQueue(queue); + } + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId(); + simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "QUEUE_node_" << node->GetId() << ".pcap"; + fileStr = stringStream.str(); + simpleWireless->EnablePcapAll(fileStr); + } + } + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + + // *********************************************************************** + // Define positions. Nodes are 50 apart + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (50.0, 0.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (NpNodes); + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // print the olsr routing table to a file every 10 seconds + //Ptr routingStream = Create ("400node_OLSR.routes", std::ios::out); + //olsr.PrintRoutingTableAllEvery (Seconds (10), routingStream); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (NpNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on destination node + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); + ApplicationContainer apps_sink = sink.Install (NpNodes.Get (1)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node 1 installed sink to receive on " << interfaces.GetAddress (1) << std::endl; + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // Now start the OnOff app on source to destinations + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (NpNodes.Get (0)); + std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds(simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // For OLSR we need to get some stats + // *********************************************************************** + double rcvPercentData = 0.0; + uint32_t dataDropped = app_count_sent - app_count_recv; + if (app_count_sent) + rcvPercentData = ((double)app_count_recv/(double)app_count_sent)*100.0; + + double rcvPercentCntrl = 0.0; + uint32_t cntlDropped = pkts_sent_cntl - pkts_rcvd_cntl; + if (pkts_sent_cntl) + rcvPercentCntrl = ((double)pkts_rcvd_cntl/(double)pkts_sent_cntl)*100.0; + + std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv + << "\nControl Packets Sent: " << pkts_sent_cntl << "\nControl Bytes Sent: " << bytes_sent_cntl + << "\nData Packets Sent: " << pkts_sent_data << "\nData Bytes Sent: " << bytes_sent_data + << "\nControl Packets Received: " << pkts_rcvd_cntl << "\nData Packets Received: " << pkts_rcvd_data + << "\nData Packets Dropped: " << dataDropped << "\nControl Packets Dropped: " << cntlDropped + << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0) + << "\n% Control Received: " << std::fixed << std::setprecision(1) << rcvPercentCntrl << std::noshowpoint << std::setprecision(0) < () - .AddConstructor () - .AddAttribute ("Mode", - "Whether to use bytes (see MaxBytes) or packets (see MaxPackets) as the maximum queue size metric.", - EnumValue (QUEUE_MODE_PACKETS), - MakeEnumAccessor (&DropHeadQueue::SetMode), - MakeEnumChecker (QUEUE_MODE_BYTES, "QUEUE_MODE_BYTES", - QUEUE_MODE_PACKETS, "QUEUE_MODE_PACKETS")) - .AddAttribute ("MaxPackets", - "The maximum number of packets accepted by this DropHeadQueue.", - UintegerValue (100), - MakeUintegerAccessor (&DropHeadQueue::m_maxPackets), - MakeUintegerChecker ()) - .AddAttribute ("MaxBytes", - "The maximum number of bytes accepted by this DropHeadQueue.", - UintegerValue (100 * 65535), - MakeUintegerAccessor (&DropHeadQueue::m_maxBytes), - MakeUintegerChecker ()) - ; - - return tid; -} - -DropHeadQueue::DropHeadQueue () : - Queue (), - m_packets (), - m_bytesInQueue (0) -{ - NS_LOG_FUNCTION (this); -} - -DropHeadQueue::~DropHeadQueue () -{ - NS_LOG_FUNCTION (this); -} - -void -DropHeadQueue::SetMode (DropHeadQueue::QueueMode mode) -{ - NS_LOG_FUNCTION (this << mode); - m_mode = mode; -} - -DropHeadQueue::QueueMode -DropHeadQueue::GetMode (void) -{ - NS_LOG_FUNCTION (this); - return m_mode; -} - -bool -DropHeadQueue::DoEnqueue (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - - if (m_mode == QUEUE_MODE_PACKETS && (m_packets.size () >= m_maxPackets)) - { - NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt"); - Ptr head_packet = Dequeue(); - Drop (head_packet); - } - - if (m_mode == QUEUE_MODE_BYTES) - { - // Drop packets from head of queue until enough bytes is available - while (m_bytesInQueue + p->GetSize () >= m_maxBytes) - { - NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- droppping pkt"); - Ptr head_packet = Dequeue(); - Drop (head_packet); - } - } - - m_bytesInQueue += p->GetSize (); - m_packets.push (p); - - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - - return true; -} - -Ptr -DropHeadQueue::DoDequeue (void) -{ - NS_LOG_FUNCTION (this); - - if (m_packets.empty ()) - { - NS_LOG_LOGIC ("Queue empty"); - return 0; - } - - Ptr p = m_packets.front (); - m_packets.pop (); - m_bytesInQueue -= p->GetSize (); - - NS_LOG_LOGIC ("Popped " << p); - - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - - return p; -} - -Ptr -DropHeadQueue::DoPeek (void) const -{ - NS_LOG_FUNCTION (this); - - if (m_packets.empty ()) - { - NS_LOG_LOGIC ("Queue empty"); - return 0; - } - - Ptr p = m_packets.front (); - - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - - return p; -} - -} // namespace ns3 - +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2007 University of Washington + * + * 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 + */ + +#include "ns3/log.h" +#include "ns3/enum.h" +#include "ns3/uinteger.h" +#include "drop-head-queue.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("DropHeadQueue"); + +NS_OBJECT_ENSURE_REGISTERED (DropHeadQueue); + +TypeId DropHeadQueue::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::DropHeadQueue") + .SetParent () + .AddConstructor () + .AddAttribute ("Mode", + "Whether to use bytes (see MaxBytes) or packets (see MaxPackets) as the maximum queue size metric.", + EnumValue (QUEUE_MODE_PACKETS), + MakeEnumAccessor (&DropHeadQueue::SetMode), + MakeEnumChecker (QUEUE_MODE_BYTES, "QUEUE_MODE_BYTES", + QUEUE_MODE_PACKETS, "QUEUE_MODE_PACKETS")) + .AddAttribute ("MaxPackets", + "The maximum number of packets accepted by this DropHeadQueue.", + UintegerValue (100), + MakeUintegerAccessor (&DropHeadQueue::m_maxPackets), + MakeUintegerChecker ()) + .AddAttribute ("MaxBytes", + "The maximum number of bytes accepted by this DropHeadQueue.", + UintegerValue (100 * 65535), + MakeUintegerAccessor (&DropHeadQueue::m_maxBytes), + MakeUintegerChecker ()) + ; + + return tid; +} + +DropHeadQueue::DropHeadQueue () : + Queue (), + m_packets (), + m_bytesInQueue (0) +{ + NS_LOG_FUNCTION (this); +} + +DropHeadQueue::~DropHeadQueue () +{ + NS_LOG_FUNCTION (this); +} + +void +DropHeadQueue::SetMode (DropHeadQueue::QueueMode mode) +{ + NS_LOG_FUNCTION (this << mode); + m_mode = mode; +} + +DropHeadQueue::QueueMode +DropHeadQueue::GetMode (void) +{ + NS_LOG_FUNCTION (this); + return m_mode; +} + +bool +DropHeadQueue::DoEnqueue (Ptr p) +{ + NS_LOG_FUNCTION (this << p); + + if (m_mode == QUEUE_MODE_PACKETS && (m_packets.size () >= m_maxPackets)) + { + NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt"); + Ptr head_packet = Dequeue(); + Drop (head_packet); + } + + if (m_mode == QUEUE_MODE_BYTES) + { + // Drop packets from head of queue until enough bytes is available + while (m_bytesInQueue + p->GetSize () >= m_maxBytes) + { + NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- droppping pkt"); + Ptr head_packet = Dequeue(); + Drop (head_packet); + } + } + + m_bytesInQueue += p->GetSize (); + m_packets.push (p); + + NS_LOG_LOGIC ("Number packets " << m_packets.size ()); + NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); + + return true; +} + +Ptr +DropHeadQueue::DoDequeue (void) +{ + NS_LOG_FUNCTION (this); + + if (m_packets.empty ()) + { + NS_LOG_LOGIC ("Queue empty"); + return 0; + } + + Ptr p = m_packets.front (); + m_packets.pop (); + m_bytesInQueue -= p->GetSize (); + + NS_LOG_LOGIC ("Popped " << p); + + NS_LOG_LOGIC ("Number packets " << m_packets.size ()); + NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); + + return p; +} + +Ptr +DropHeadQueue::DoPeek (void) const +{ + NS_LOG_FUNCTION (this); + + if (m_packets.empty ()) + { + NS_LOG_LOGIC ("Queue empty"); + return 0; + } + + Ptr p = m_packets.front (); + + NS_LOG_LOGIC ("Number packets " << m_packets.size ()); + NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); + + return p; +} + +} // namespace ns3 + diff --git a/model/drop-head-queue.h b/model/drop-head-queue.h index 3058ccd..59ff30b 100644 --- a/model/drop-head-queue.h +++ b/model/drop-head-queue.h @@ -1,81 +1,81 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * Copyright (c) 2007 University of Washington - * - * 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 - */ - -#ifndef DROPHEAD_H -#define DROPHEAD_H - -#include -#include "ns3/packet.h" -#include "ns3/queue.h" - -namespace ns3 { - -class TraceContainer; - -/** - * \ingroup queue - * - * \brief A FIFO packet queue that drops head-end packets on overflow - */ -class DropHeadQueue : public Queue { -public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId (void); - /** - * \brief DropHeadQueue Constructor - * - * Creates a drophead queue with a maximum size of 100 packets by default - */ - DropHeadQueue (); - - virtual ~DropHeadQueue(); - - /** - * Set the operating mode of this device. - * - * \param mode The operating mode of this device. - * - */ - void SetMode (DropHeadQueue::QueueMode mode); - - /** - * Get the encapsulation mode of this device. - * - * \returns The encapsulation mode of this device. - */ - DropHeadQueue::QueueMode GetMode (void); - -private: - virtual bool DoEnqueue (Ptr p); - virtual Ptr DoDequeue (void); - virtual Ptr DoPeek (void) const; - - std::queue > m_packets; //!< the packets in the queue - uint32_t m_maxPackets; //!< max packets in the queue - uint32_t m_maxBytes; //!< max bytes in the queue - uint32_t m_bytesInQueue; //!< actual bytes in the queue - QueueMode m_mode; //!< queue mode (packets or bytes limited) -}; - -} // namespace ns3 - -#endif /* DROPHEAD_H */ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2007 University of Washington + * + * 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 + */ + +#ifndef DROPHEAD_H +#define DROPHEAD_H + +#include +#include "ns3/packet.h" +#include "ns3/queue.h" + +namespace ns3 { + +class TraceContainer; + +/** + * \ingroup queue + * + * \brief A FIFO packet queue that drops head-end packets on overflow + */ +class DropHeadQueue : public Queue { +public: + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + /** + * \brief DropHeadQueue Constructor + * + * Creates a drophead queue with a maximum size of 100 packets by default + */ + DropHeadQueue (); + + virtual ~DropHeadQueue(); + + /** + * Set the operating mode of this device. + * + * \param mode The operating mode of this device. + * + */ + void SetMode (DropHeadQueue::QueueMode mode); + + /** + * Get the encapsulation mode of this device. + * + * \returns The encapsulation mode of this device. + */ + DropHeadQueue::QueueMode GetMode (void); + +private: + virtual bool DoEnqueue (Ptr p); + virtual Ptr DoDequeue (void); + virtual Ptr DoPeek (void) const; + + std::queue > m_packets; //!< the packets in the queue + uint32_t m_maxPackets; //!< max packets in the queue + uint32_t m_maxBytes; //!< max bytes in the queue + uint32_t m_bytesInQueue; //!< actual bytes in the queue + QueueMode m_mode; //!< queue mode (packets or bytes limited) +}; + +} // namespace ns3 + +#endif /* DROPHEAD_H */ diff --git a/model/priority-queue.cc b/model/priority-queue.cc index 1f8e88b..e4fa67d 100644 --- a/model/priority-queue.cc +++ b/model/priority-queue.cc @@ -1,193 +1,193 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * Copyright (c) 2007 University of Washington - * - * 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 - */ - -#include "ns3/log.h" -#include "ns3/enum.h" -#include "ns3/string.h" -#include "ns3/pointer.h" -#include "ns3/uinteger.h" -#include "priority-queue.h" - -namespace ns3 { - -NS_LOG_COMPONENT_DEFINE ("PriorityQueue"); - -NS_OBJECT_ENSURE_REGISTERED (PriorityQueue); - -TypeId PriorityQueue::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::PriorityQueue") - .SetParent () - .AddConstructor () - - .AddAttribute ("ControlQueue", - "A queue to use as the transmit queue in the device.", - PointerValue (), - MakePointerAccessor (&PriorityQueue::m_controlQueue), - MakePointerChecker ()) - .AddAttribute ("DataQueue", - "A queue to use as the transmit queue in the device.", - PointerValue (), - MakePointerAccessor (&PriorityQueue::m_dataQueue), - MakePointerChecker ()) - .AddAttribute ("ControlPacketClassifier", - "Pcap style filter to classify control packets", - StringValue (), - MakeStringAccessor (&PriorityQueue::m_classifier), - MakeStringChecker ()) - ; - - return tid; -} - -PriorityQueue::PriorityQueue () : - Queue () -{ - NS_LOG_FUNCTION (this); - - m_pcapHandle = pcap_open_dead (DLT_EN10MB, 1500); - NS_ASSERT_MSG (m_pcapHandle, "failed to open pcap handle"); -} - -PriorityQueue::~PriorityQueue () -{ - NS_LOG_FUNCTION (this); - - m_controlQueue = 0; - m_dataQueue = 0; - - pcap_close (m_pcapHandle); -} - -void -PriorityQueue::Initialize () -{ - NS_LOG_FUNCTION (this); - - int ret = pcap_compile (m_pcapHandle, &m_bpf, - m_classifier.c_str (), 1, PCAP_NETMASK_UNKNOWN); - NS_ASSERT_MSG (ret == 0, "failed to compile control packet classifer"); -} - -void -PriorityQueue::SetControlQueue (Ptr q) -{ - NS_LOG_FUNCTION (this << q); - m_controlQueue = q; -} - -void -PriorityQueue::SetDataQueue (Ptr q) -{ - NS_LOG_FUNCTION (this << q); - m_dataQueue = q; -} - -Ptr -PriorityQueue::GetControlQueue (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_controlQueue; -} - -Ptr -PriorityQueue::GetDataQueue (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_dataQueue; -} - -PriorityQueue::PacketClass -PriorityQueue::Classify (Ptr p) -{ - pcap_pkthdr pcapPkthdr; - pcapPkthdr.caplen = p->GetSize (); - pcapPkthdr.len = p->GetSize (); - uint8_t *data = new uint8_t[p->GetSize ()]; - p->CopyData (data, p->GetSize ()); - int ret = pcap_offline_filter (&m_bpf, &pcapPkthdr, data); - delete [] data; - - if (ret == 0) - { - NS_LOG_DEBUG ("Packet is data packet"); - return PACKET_CLASS_DATA; - } - else - { - NS_LOG_DEBUG ("Packet is control packet"); - return PACKET_CLASS_CONTROL; - } -} - -bool -PriorityQueue::DoEnqueue (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - - PacketClass packetClass = Classify (p); - - if (packetClass == PACKET_CLASS_CONTROL) - { - return m_controlQueue->Enqueue (p); - } - else - { - return m_dataQueue->Enqueue (p); - } -} - -Ptr -PriorityQueue::DoDequeue (void) -{ - NS_LOG_FUNCTION (this); - - Ptr p = 0; - if (!m_controlQueue->IsEmpty ()) - { - p = m_controlQueue->Dequeue (); - } - else - { - p = m_dataQueue->Dequeue (); - } - - return p; -} - -Ptr -PriorityQueue::DoPeek (void) const -{ - NS_LOG_FUNCTION (this); - - Ptr p = 0; - if (!m_controlQueue->IsEmpty ()) - { - p = m_controlQueue->Peek (); - } - else - { - p = m_dataQueue->Peek (); - } - - return p; -} - -} // namespace ns3 - +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2007 University of Washington + * + * 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 + */ + +#include "ns3/log.h" +#include "ns3/enum.h" +#include "ns3/string.h" +#include "ns3/pointer.h" +#include "ns3/uinteger.h" +#include "priority-queue.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("PriorityQueue"); + +NS_OBJECT_ENSURE_REGISTERED (PriorityQueue); + +TypeId PriorityQueue::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::PriorityQueue") + .SetParent () + .AddConstructor () + + .AddAttribute ("ControlQueue", + "A queue to use as the transmit queue in the device.", + PointerValue (), + MakePointerAccessor (&PriorityQueue::m_controlQueue), + MakePointerChecker ()) + .AddAttribute ("DataQueue", + "A queue to use as the transmit queue in the device.", + PointerValue (), + MakePointerAccessor (&PriorityQueue::m_dataQueue), + MakePointerChecker ()) + .AddAttribute ("ControlPacketClassifier", + "Pcap style filter to classify control packets", + StringValue (), + MakeStringAccessor (&PriorityQueue::m_classifier), + MakeStringChecker ()) + ; + + return tid; +} + +PriorityQueue::PriorityQueue () : + Queue () +{ + NS_LOG_FUNCTION (this); + + m_pcapHandle = pcap_open_dead (DLT_EN10MB, 1500); + NS_ASSERT_MSG (m_pcapHandle, "failed to open pcap handle"); +} + +PriorityQueue::~PriorityQueue () +{ + NS_LOG_FUNCTION (this); + + m_controlQueue = 0; + m_dataQueue = 0; + + pcap_close (m_pcapHandle); +} + +void +PriorityQueue::Initialize () +{ + NS_LOG_FUNCTION (this); + + int ret = pcap_compile (m_pcapHandle, &m_bpf, + m_classifier.c_str (), 1, PCAP_NETMASK_UNKNOWN); + NS_ASSERT_MSG (ret == 0, "failed to compile control packet classifer"); +} + +void +PriorityQueue::SetControlQueue (Ptr q) +{ + NS_LOG_FUNCTION (this << q); + m_controlQueue = q; +} + +void +PriorityQueue::SetDataQueue (Ptr q) +{ + NS_LOG_FUNCTION (this << q); + m_dataQueue = q; +} + +Ptr +PriorityQueue::GetControlQueue (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_controlQueue; +} + +Ptr +PriorityQueue::GetDataQueue (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_dataQueue; +} + +PriorityQueue::PacketClass +PriorityQueue::Classify (Ptr p) +{ + pcap_pkthdr pcapPkthdr; + pcapPkthdr.caplen = p->GetSize (); + pcapPkthdr.len = p->GetSize (); + uint8_t *data = new uint8_t[p->GetSize ()]; + p->CopyData (data, p->GetSize ()); + int ret = pcap_offline_filter (&m_bpf, &pcapPkthdr, data); + delete [] data; + + if (ret == 0) + { + NS_LOG_DEBUG ("Packet is data packet"); + return PACKET_CLASS_DATA; + } + else + { + NS_LOG_DEBUG ("Packet is control packet"); + return PACKET_CLASS_CONTROL; + } +} + +bool +PriorityQueue::DoEnqueue (Ptr p) +{ + NS_LOG_FUNCTION (this << p); + + PacketClass packetClass = Classify (p); + + if (packetClass == PACKET_CLASS_CONTROL) + { + return m_controlQueue->Enqueue (p); + } + else + { + return m_dataQueue->Enqueue (p); + } +} + +Ptr +PriorityQueue::DoDequeue (void) +{ + NS_LOG_FUNCTION (this); + + Ptr p = 0; + if (!m_controlQueue->IsEmpty ()) + { + p = m_controlQueue->Dequeue (); + } + else + { + p = m_dataQueue->Dequeue (); + } + + return p; +} + +Ptr +PriorityQueue::DoPeek (void) const +{ + NS_LOG_FUNCTION (this); + + Ptr p = 0; + if (!m_controlQueue->IsEmpty ()) + { + p = m_controlQueue->Peek (); + } + else + { + p = m_dataQueue->Peek (); + } + + return p; +} + +} // namespace ns3 + diff --git a/model/priority-queue.h b/model/priority-queue.h index 9612b8b..5a5cff7 100644 --- a/model/priority-queue.h +++ b/model/priority-queue.h @@ -1,121 +1,121 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * Copyright (c) 2007 University of Washington - * - * 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 - */ - -#ifndef PRIORITY_H -#define PRIORITY_H - -#include "ns3/packet.h" -#include "ns3/queue.h" - -#include -#undef DLT_IEEE802_11_RADIO // Avoid namespace collision with ns3::YansWifiPhyHelper::DLT_IEEE802_11_RADIO - -namespace ns3 { - -class TraceContainer; - -/** - * \ingroup queue - * - * \brief A strict priority queue with two subqueues, one for control packets and one for data - */ -class PriorityQueue : public Queue { -public: - /** - * \brief Get the type ID. - * \return the object TypeId - */ - static TypeId GetTypeId (void); - /** - * \brief PriorityQueue Constructor - * - * Creates a priority queue with a maximum size of 100 packets by default - */ - PriorityQueue (); - - virtual ~PriorityQueue(); - - /** - * \brief PriorityQueue Constructor - * - * Initializes priority queue - */ - void Initialize (); - - /** - * Attach a queue to hold data packets to the PriorityQueue. - * - * The PriorityQueue "owns" a sub queue that implements a queueing - * method such as DropTailQueue, DropHeadQueue or RedQueue - * - * \param queue Ptr to the new queue. - */ - void SetDataQueue (Ptr q); - - /** - * Attach a queue to hold control packets to the PriorityQueue. - * - * The PriorityQueue "owns" a sub queue that implements a queueing - * method such as DropTailQueue, DropHeadQueue or RedQueue - * - * \param queue Ptr to the new queue. - */ - void SetControlQueue (Ptr q); - - /** - * Get a copy of the attached Queue that holds control packets. - * - * \returns Ptr to the queue. - */ - Ptr GetControlQueue (void) const; - - /** - * Get a copy of the attached Queue that holds data packets. - * - * \returns Ptr to the queue. - */ - Ptr GetDataQueue (void) const; - - /** - * \brief Enumeration of the modes supported in the class. - * - */ - enum PacketClass - { - PACKET_CLASS_CONTROL, /**< Packet classifier matched packet to control type */ - PACKET_CLASS_DATA, /**< Packet classifier matched packet to control type */ - }; - -private: - virtual bool DoEnqueue (Ptr p); - virtual Ptr DoDequeue (void); - virtual Ptr DoPeek (void) const; - PacketClass Classify (Ptr p); - - Ptr m_controlQueue; //!< queue for control traffic - Ptr m_dataQueue; //!< queue for data traffic - - std::string m_classifier; //!< classfier for control packets - pcap_t * m_pcapHandle; //!< handle for libpcap - struct bpf_program m_bpf; //!< compiled classifier for control packets -}; - -} // namespace ns3 - -#endif /* PRIORITY_H */ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2007 University of Washington + * + * 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 + */ + +#ifndef PRIORITY_H +#define PRIORITY_H + +#include "ns3/packet.h" +#include "ns3/queue.h" + +#include +#undef DLT_IEEE802_11_RADIO // Avoid namespace collision with ns3::YansWifiPhyHelper::DLT_IEEE802_11_RADIO + +namespace ns3 { + +class TraceContainer; + +/** + * \ingroup queue + * + * \brief A strict priority queue with two subqueues, one for control packets and one for data + */ +class PriorityQueue : public Queue { +public: + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + /** + * \brief PriorityQueue Constructor + * + * Creates a priority queue with a maximum size of 100 packets by default + */ + PriorityQueue (); + + virtual ~PriorityQueue(); + + /** + * \brief PriorityQueue Constructor + * + * Initializes priority queue + */ + void Initialize (); + + /** + * Attach a queue to hold data packets to the PriorityQueue. + * + * The PriorityQueue "owns" a sub queue that implements a queueing + * method such as DropTailQueue, DropHeadQueue or RedQueue + * + * \param queue Ptr to the new queue. + */ + void SetDataQueue (Ptr q); + + /** + * Attach a queue to hold control packets to the PriorityQueue. + * + * The PriorityQueue "owns" a sub queue that implements a queueing + * method such as DropTailQueue, DropHeadQueue or RedQueue + * + * \param queue Ptr to the new queue. + */ + void SetControlQueue (Ptr q); + + /** + * Get a copy of the attached Queue that holds control packets. + * + * \returns Ptr to the queue. + */ + Ptr GetControlQueue (void) const; + + /** + * Get a copy of the attached Queue that holds data packets. + * + * \returns Ptr to the queue. + */ + Ptr GetDataQueue (void) const; + + /** + * \brief Enumeration of the modes supported in the class. + * + */ + enum PacketClass + { + PACKET_CLASS_CONTROL, /**< Packet classifier matched packet to control type */ + PACKET_CLASS_DATA, /**< Packet classifier matched packet to control type */ + }; + +private: + virtual bool DoEnqueue (Ptr p); + virtual Ptr DoDequeue (void); + virtual Ptr DoPeek (void) const; + PacketClass Classify (Ptr p); + + Ptr m_controlQueue; //!< queue for control traffic + Ptr m_dataQueue; //!< queue for data traffic + + std::string m_classifier; //!< classfier for control packets + pcap_t * m_pcapHandle; //!< handle for libpcap + struct bpf_program m_bpf; //!< compiled classifier for control packets +}; + +} // namespace ns3 + +#endif /* PRIORITY_H */ diff --git a/model/simple-wireless-channel.cc b/model/simple-wireless-channel.cc index ce4e27f..1580cf0 100644 --- a/model/simple-wireless-channel.cc +++ b/model/simple-wireless-channel.cc @@ -1,448 +1,448 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * Copyright (c) 2010 University of Washington - * - * 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 - * - */ -#include "ns3/simulator.h" -#include "ns3/packet.h" -#include "ns3/node.h" -#include "ns3/log.h" -#include "ns3/double.h" -#include "ns3/uinteger.h" -#include "ns3/ptr.h" -#include "ns3/mobility-model.h" -#include "simple-wireless-channel.h" -#include "simple-wireless-net-device.h" -#include - -NS_LOG_COMPONENT_DEFINE ("SimpleWirelessChannel"); - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (SimpleWirelessChannel); - -TypeId -SimpleWirelessChannel::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::SimpleWirelessChannel") - .SetParent () - .AddConstructor () - .AddAttribute ("MaxRange", - "Maximum Transmission Range (meters)", - DoubleValue (250), - MakeDoubleAccessor (&SimpleWirelessChannel::m_range), - MakeDoubleChecker ()) - .AddAttribute ("RangeErrorModel", - "Type or range based error model", - EnumValue (CONSTANT), - MakeEnumAccessor (&SimpleWirelessChannel::m_ErrorModel), - MakeEnumChecker (CONSTANT, "Constant", - PER_CURVE, "PER_CURVE", - STOCHASTIC, "STOCHASTIC")) - .AddAttribute ("RangeErrorRate", - "Error rate when using constant Range Error Model", - StringValue("0.0"), - MakeDoubleAccessor (&SimpleWirelessChannel::m_errorRate), - MakeDoubleChecker ()) - .AddAttribute ("EnableFixedContention", - "Enabled or Disabled", - BooleanValue (false), - MakeBooleanAccessor (&SimpleWirelessChannel::m_fixedContentionEnabled), - MakeBooleanChecker ()) - .AddAttribute ("FixedContentionRange", - "Maximum Range (meters) for Fixed Contention", - DoubleValue (0), // default to 0 so we can use the tx range as default if the user does not set this - MakeDoubleAccessor (&SimpleWirelessChannel::m_fixedContentionRange), - MakeDoubleChecker ()) - .AddAttribute ("AvgLinkUpDuration", - "Average time that the link to a neighbor is up for Stochastic Error Model", - TimeValue (MicroSeconds (10000.0)), - MakeTimeAccessor (&SimpleWirelessChannel::m_upDuration), - MakeTimeChecker ()) - .AddAttribute ("AvgLinkDownDuration", - "Average time that the link to a neighbor is down for Stochastic Error Model", - TimeValue (MicroSeconds (100.0)), - MakeTimeAccessor (&SimpleWirelessChannel::m_downDuration), - MakeTimeChecker ()) - ; - return tid; -} - -SimpleWirelessChannel::SimpleWirelessChannel () -{ - // Default to a constant error model with 0 errors - m_random = CreateObject (); - m_ErrorModel = CONSTANT; - m_errorRate = 0.0; - m_fixedContentionEnabled = false; - m_fixedContentionRange = 0; -} - -void -SimpleWirelessChannel::Send (Ptr p, uint16_t protocol, - Mac48Address to, Mac48Address from, - Ptr sender, Time txTime, uint32_t destId) -{ - NS_LOG_FUNCTION (p << protocol << to << from << sender); - - uint32_t senderNodeId = sender->GetNode()->GetId(); - - if (m_fixedContentionEnabled) - { - sender->ClearNbrCount(); - - // if the range has not been set, use the tx range. - // We do this here because we want the value for range that the user selected value. - // If we set the contention range to m_range in other places (like the call to - // EnableFixedContention), at that point the range could still be the default - // value and not the value the user has set. - if (m_fixedContentionRange == 0) - m_fixedContentionRange = m_range; - } - - for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) - { - Ptr tmp = *i; - uint32_t destNodeId = tmp->GetNode()->GetId(); - - // don't send to ourselves - if (tmp == sender) - { - NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Node is self"); - continue; - } - - // See if we have directional networking enabled and if so if this is destination node - if ( (destId != NO_DIRECTIONAL_NBR) && (destNodeId != destId) ) - { - NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Directional networking enabled and node is not destination " << destId); - continue; - } - - // See if we are using stochastic. If so see if the sender's link - // to the destination is up or down - if (CheckStochasticError (senderNodeId, destNodeId)) - { - NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Stochastic error enabled and link to node is in OFF state"); - continue; - } - - Ptr a = sender->GetNode ()->GetObject (); - Ptr b = tmp->GetNode ()->GetObject (); - NS_ASSERT_MSG (a && b, "Error: nodes must have mobility models"); - - // Get distance and determine error rate based on that - // and the error model - double distance = a->GetDistanceFrom (b); - - - // if fixed contention is enabled then we need to peg the neighbor count - if ( (m_fixedContentionEnabled) && (distance < m_fixedContentionRange) ) - { - sender->IncrementNbrCount(); - NS_LOG_INFO ("Node " << senderNodeId << " pegging nbr count for contention. distane is " << distance << ". count is now " << sender->GetNbrCount()); - } - - // Is this packet beyond the transmission range? - if (distance > m_range) - { - NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". distance of " << distance << " is out of range"); - continue; - } - - // Is this packet in error or can we send it based on the distance? - if (packetInError(distance)) - { - continue; - } - - // propagation delay. speed of light is 3.3 ns/meter - double propDelay = 3.3 * distance; - NS_LOG_INFO ("Node " << senderNodeId << " sending to node " << destNodeId - << " at distance " << distance << " meters; time (ns): "<< Simulator::Now().GetNanoSeconds () - << " txDelay: " << txTime << " propDelay: " << propDelay); - - Simulator::ScheduleWithContext (destNodeId, NanoSeconds (txTime + propDelay), - &SimpleWirelessNetDevice::Receive, tmp, p->Copy (), protocol, to, from); - - } -} - -void -SimpleWirelessChannel::Add (Ptr device) -{ - m_devices.push_back (device); -} - -uint32_t -SimpleWirelessChannel::GetNDevices (void) const -{ - return m_devices.size (); -} - -Ptr -SimpleWirelessChannel::GetDevice (uint32_t i) const -{ - return m_devices[i]; -} - - -//******************************************************************** -// contention functions -void SimpleWirelessChannel::EnableFixedContention(void) -{ - m_fixedContentionEnabled = true; - - // Set up all the devices to support contention. - // IMPORTANT NOTE: There may not be any devices at this point on the channel. - // If there are not any, then the first packet sent by the device will use the - // full data rate and will not use contention. That is, the device will be notified - // by the channel when the channel gets the first packet from the device and that is - // after the data rate has been used to set the tx time. All subsequent packets sent - // by the device will use contention just not the first one. - for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) - { - Ptr tmp = *i; - tmp->ClearNbrCount(); - } -} - -void SimpleWirelessChannel::SetFixedContentionRange(double range) -{ - m_fixedContentionRange = range; -} - -//******************************************************************** -// Error Model functions -void SimpleWirelessChannel::setErrorModelType(ErrorModelType type) -{ - m_ErrorModel = type; - - // reset range to 0 if error model is PER CURVE so that - // we can compare to distances added to the curve to - // get the max range - if (m_ErrorModel == PER_CURVE) - { - m_range = 0; - } -} - -void SimpleWirelessChannel::setErrorRate(double error) -{ - m_errorRate = error; -} - -void SimpleWirelessChannel::addToPERmodel(double distance, double error) -{ - // NOTE: distance is in meters - mPERmap.insert(std::pair(distance, error)); - - if (distance > m_range) - { - m_range = distance; - } -} - - -//******************************************************************** -// Stochastic error functions - -void SimpleWirelessChannel::InitStochasticModel() -{ - // Build the map of neighbor links, setting all links to - // ON state and pick a duration for that state. - if (m_ErrorModel == STOCHASTIC) - { - if (m_devices.size() == 0) - { - NS_LOG_ERROR ("InitStochasticModel called but there are no devices on the channel. Be sure to call InitStochasticModel AFTER devices have been added."); - } - - m_randomUp = CreateObject (); - m_randomDown = CreateObject (); - - m_randomUp->SetAttribute ("Mean", DoubleValue (m_upDuration.GetMicroSeconds())); - m_randomDown->SetAttribute ("Mean", DoubleValue (m_downDuration.GetMicroSeconds())); - - Time currTime = Simulator::Now(); - - for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) - { - for (std::vector >::const_iterator j = m_devices.begin (); j != m_devices.end (); ++j) - { - int src = (*i)->GetNode()->GetId(); - int dst = (*j)->GetNode()->GetId(); - - if (src == dst) - continue; - - StochasticLink tempLink; - tempLink.linkState = true; - tempLink.stateExpireTime = currTime + MicroSeconds(m_randomUp->GetValue()); - //tempLink.stateExpireTime = Simulator::Now() + Seconds(1.0); - - m_StochasticLinks.insert(std::pair(StochasticKey(src,dst), tempLink)); - NS_LOG_DEBUG("Add link to stochastic map. src: " << src << " dst: " << dst << " expireTime: " - << std::setprecision (9) << tempLink.stateExpireTime.GetSeconds() << " state: " << tempLink.linkState); - } - } - } -} - - -// This returns true if we should NOT send the packet. -// That is, return true == packet fails to send - -bool SimpleWirelessChannel::CheckStochasticError(uint32_t srcId, uint32_t dstId) -{ - if (m_ErrorModel == STOCHASTIC) - { - // get entry from map for this src/dst pair - StochasIt iter = m_StochasticLinks.find(StochasticKey(srcId, dstId)); - NS_ASSERT( iter != m_StochasticLinks.end()); - - Time currTime = Simulator::Now(); - - //std::cout << std::setprecision (9) << currTime.GetSeconds() << " Checking state for link src: " << srcId << " dst: " << dstId << " expireTime: " << iter->second.stateExpireTime << std::endl; - - if (currTime >= iter->second.stateExpireTime) - { - // the time at which the previous state was set to end has already passed. - Time endTime = iter->second.stateExpireTime; - bool tempState = iter->second.linkState; - Time newDuration; - // Pick the new states until we get to one that is at or greater - // than the current time. - while (endTime < currTime) - { - // Now pick duration for the new state - if (!tempState) - { - newDuration = MicroSeconds(m_randomUp->GetValue()); - } - else - { - newDuration = MicroSeconds(m_randomDown->GetValue()); - } - endTime += newDuration; - tempState = !tempState; - - NS_LOG_DEBUG("---> " << std::setprecision (9) << currTime.GetSeconds() << " next state: " << tempState << " for link src: " << srcId << " dst: " << dstId - << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds() - << " expireTime: " << std::setprecision (9) << endTime.GetSeconds()); - } - - // When we get here, the new state and time are selected - iter->second.linkState = tempState; - iter->second.stateExpireTime = endTime; - - NS_LOG_DEBUG(std::setprecision (9) << currTime.GetSeconds() << " New state " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId - << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds() - << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds()); - - } - else - { - NS_LOG_DEBUG(std::setprecision (9) << currTime.GetSeconds() << " State " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId - << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds()); - } - - // now return true or false depending on state - // true = packet is in "error" and failes - // false = packet not in error and sends - if (iter->second.linkState) - { - return false; - } - else - { - return true; - } - } - else - { - return false; - } -} - -//******************************************************************** - -bool SimpleWirelessChannel::packetInError(double distance) -{ - std::map::iterator it; - std::map::iterator up_iter; - std::map::iterator low_iter; - - if (m_ErrorModel == CONSTANT) - { - if ( m_random->GetValue () < m_errorRate ) - { - NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); - return true; - } - } - else if (m_ErrorModel == PER_CURVE) - { - it = mPERmap.find(distance); - if (it != mPERmap.end()) - { - // we found an exact match in the map for this distance - if (m_random->GetValue() < it->second) - { - NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); - return true; - } - } - else - { - // we did not find an exact match in the map. That's OK - // since it could actually be unlikely to find one. - // Now we just extrapolate between the two entries in the map - - // first get iterator to upper bound - up_iter = mPERmap.upper_bound(distance); - if (up_iter == mPERmap.end()) - { - // We shouldn't hit this situation because we already checked the distance - // relative to the range but go ahead and leave this here - // this distance is beyond the upper bound so error is 100% - NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); - return true; - } - - // Set low iter to upper then decrement it - low_iter = up_iter; - --low_iter; - - double errorRate = low_iter->second + ( ((distance - low_iter->first)/(up_iter->first - low_iter->first)) * (up_iter->second - low_iter->second)); - NS_LOG_INFO("Error Model: " << m_ErrorModel << " distance: " << distance << " calculated error rate: " << errorRate << " low distance: " << low_iter->first << " low error: " << low_iter->second - << " high distance: " << up_iter->first << " high error: " << up_iter->second); - - if (m_random->GetValue() < errorRate) - { - return true; - } - } - } - - - // if we get here then there were no errors - return false; -} - - -} // namespace ns3 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2010 University of Washington + * + * 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 + * + */ +#include "ns3/simulator.h" +#include "ns3/packet.h" +#include "ns3/node.h" +#include "ns3/log.h" +#include "ns3/double.h" +#include "ns3/uinteger.h" +#include "ns3/ptr.h" +#include "ns3/mobility-model.h" +#include "simple-wireless-channel.h" +#include "simple-wireless-net-device.h" +#include + +NS_LOG_COMPONENT_DEFINE ("SimpleWirelessChannel"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (SimpleWirelessChannel); + +TypeId +SimpleWirelessChannel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::SimpleWirelessChannel") + .SetParent () + .AddConstructor () + .AddAttribute ("MaxRange", + "Maximum Transmission Range (meters)", + DoubleValue (250), + MakeDoubleAccessor (&SimpleWirelessChannel::m_range), + MakeDoubleChecker ()) + .AddAttribute ("RangeErrorModel", + "Type or range based error model", + EnumValue (CONSTANT), + MakeEnumAccessor (&SimpleWirelessChannel::m_ErrorModel), + MakeEnumChecker (CONSTANT, "Constant", + PER_CURVE, "PER_CURVE", + STOCHASTIC, "STOCHASTIC")) + .AddAttribute ("RangeErrorRate", + "Error rate when using constant Range Error Model", + StringValue("0.0"), + MakeDoubleAccessor (&SimpleWirelessChannel::m_errorRate), + MakeDoubleChecker ()) + .AddAttribute ("EnableFixedContention", + "Enabled or Disabled", + BooleanValue (false), + MakeBooleanAccessor (&SimpleWirelessChannel::m_fixedContentionEnabled), + MakeBooleanChecker ()) + .AddAttribute ("FixedContentionRange", + "Maximum Range (meters) for Fixed Contention", + DoubleValue (0), // default to 0 so we can use the tx range as default if the user does not set this + MakeDoubleAccessor (&SimpleWirelessChannel::m_fixedContentionRange), + MakeDoubleChecker ()) + .AddAttribute ("AvgLinkUpDuration", + "Average time that the link to a neighbor is up for Stochastic Error Model", + TimeValue (MicroSeconds (10000.0)), + MakeTimeAccessor (&SimpleWirelessChannel::m_upDuration), + MakeTimeChecker ()) + .AddAttribute ("AvgLinkDownDuration", + "Average time that the link to a neighbor is down for Stochastic Error Model", + TimeValue (MicroSeconds (100.0)), + MakeTimeAccessor (&SimpleWirelessChannel::m_downDuration), + MakeTimeChecker ()) + ; + return tid; +} + +SimpleWirelessChannel::SimpleWirelessChannel () +{ + // Default to a constant error model with 0 errors + m_random = CreateObject (); + m_ErrorModel = CONSTANT; + m_errorRate = 0.0; + m_fixedContentionEnabled = false; + m_fixedContentionRange = 0; +} + +void +SimpleWirelessChannel::Send (Ptr p, uint16_t protocol, + Mac48Address to, Mac48Address from, + Ptr sender, Time txTime, uint32_t destId) +{ + NS_LOG_FUNCTION (p << protocol << to << from << sender); + + uint32_t senderNodeId = sender->GetNode()->GetId(); + + if (m_fixedContentionEnabled) + { + sender->ClearNbrCount(); + + // if the range has not been set, use the tx range. + // We do this here because we want the value for range that the user selected value. + // If we set the contention range to m_range in other places (like the call to + // EnableFixedContention), at that point the range could still be the default + // value and not the value the user has set. + if (m_fixedContentionRange == 0) + m_fixedContentionRange = m_range; + } + + for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) + { + Ptr tmp = *i; + uint32_t destNodeId = tmp->GetNode()->GetId(); + + // don't send to ourselves + if (tmp == sender) + { + NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Node is self"); + continue; + } + + // See if we have directional networking enabled and if so if this is destination node + if ( (destId != NO_DIRECTIONAL_NBR) && (destNodeId != destId) ) + { + NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Directional networking enabled and node is not destination " << destId); + continue; + } + + // See if we are using stochastic. If so see if the sender's link + // to the destination is up or down + if (CheckStochasticError (senderNodeId, destNodeId)) + { + NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Stochastic error enabled and link to node is in OFF state"); + continue; + } + + Ptr a = sender->GetNode ()->GetObject (); + Ptr b = tmp->GetNode ()->GetObject (); + NS_ASSERT_MSG (a && b, "Error: nodes must have mobility models"); + + // Get distance and determine error rate based on that + // and the error model + double distance = a->GetDistanceFrom (b); + + + // if fixed contention is enabled then we need to peg the neighbor count + if ( (m_fixedContentionEnabled) && (distance < m_fixedContentionRange) ) + { + sender->IncrementNbrCount(); + NS_LOG_INFO ("Node " << senderNodeId << " pegging nbr count for contention. distane is " << distance << ". count is now " << sender->GetNbrCount()); + } + + // Is this packet beyond the transmission range? + if (distance > m_range) + { + NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". distance of " << distance << " is out of range"); + continue; + } + + // Is this packet in error or can we send it based on the distance? + if (packetInError(distance)) + { + continue; + } + + // propagation delay. speed of light is 3.3 ns/meter + double propDelay = 3.3 * distance; + NS_LOG_INFO ("Node " << senderNodeId << " sending to node " << destNodeId + << " at distance " << distance << " meters; time (ns): "<< Simulator::Now().GetNanoSeconds () + << " txDelay: " << txTime << " propDelay: " << propDelay); + + Simulator::ScheduleWithContext (destNodeId, NanoSeconds (txTime + propDelay), + &SimpleWirelessNetDevice::Receive, tmp, p->Copy (), protocol, to, from); + + } +} + +void +SimpleWirelessChannel::Add (Ptr device) +{ + m_devices.push_back (device); +} + +uint32_t +SimpleWirelessChannel::GetNDevices (void) const +{ + return m_devices.size (); +} + +Ptr +SimpleWirelessChannel::GetDevice (uint32_t i) const +{ + return m_devices[i]; +} + + +//******************************************************************** +// contention functions +void SimpleWirelessChannel::EnableFixedContention(void) +{ + m_fixedContentionEnabled = true; + + // Set up all the devices to support contention. + // IMPORTANT NOTE: There may not be any devices at this point on the channel. + // If there are not any, then the first packet sent by the device will use the + // full data rate and will not use contention. That is, the device will be notified + // by the channel when the channel gets the first packet from the device and that is + // after the data rate has been used to set the tx time. All subsequent packets sent + // by the device will use contention just not the first one. + for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) + { + Ptr tmp = *i; + tmp->ClearNbrCount(); + } +} + +void SimpleWirelessChannel::SetFixedContentionRange(double range) +{ + m_fixedContentionRange = range; +} + +//******************************************************************** +// Error Model functions +void SimpleWirelessChannel::setErrorModelType(ErrorModelType type) +{ + m_ErrorModel = type; + + // reset range to 0 if error model is PER CURVE so that + // we can compare to distances added to the curve to + // get the max range + if (m_ErrorModel == PER_CURVE) + { + m_range = 0; + } +} + +void SimpleWirelessChannel::setErrorRate(double error) +{ + m_errorRate = error; +} + +void SimpleWirelessChannel::addToPERmodel(double distance, double error) +{ + // NOTE: distance is in meters + mPERmap.insert(std::pair(distance, error)); + + if (distance > m_range) + { + m_range = distance; + } +} + + +//******************************************************************** +// Stochastic error functions + +void SimpleWirelessChannel::InitStochasticModel() +{ + // Build the map of neighbor links, setting all links to + // ON state and pick a duration for that state. + if (m_ErrorModel == STOCHASTIC) + { + if (m_devices.size() == 0) + { + NS_LOG_ERROR ("InitStochasticModel called but there are no devices on the channel. Be sure to call InitStochasticModel AFTER devices have been added."); + } + + m_randomUp = CreateObject (); + m_randomDown = CreateObject (); + + m_randomUp->SetAttribute ("Mean", DoubleValue (m_upDuration.GetMicroSeconds())); + m_randomDown->SetAttribute ("Mean", DoubleValue (m_downDuration.GetMicroSeconds())); + + Time currTime = Simulator::Now(); + + for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) + { + for (std::vector >::const_iterator j = m_devices.begin (); j != m_devices.end (); ++j) + { + int src = (*i)->GetNode()->GetId(); + int dst = (*j)->GetNode()->GetId(); + + if (src == dst) + continue; + + StochasticLink tempLink; + tempLink.linkState = true; + tempLink.stateExpireTime = currTime + MicroSeconds(m_randomUp->GetValue()); + //tempLink.stateExpireTime = Simulator::Now() + Seconds(1.0); + + m_StochasticLinks.insert(std::pair(StochasticKey(src,dst), tempLink)); + NS_LOG_DEBUG("Add link to stochastic map. src: " << src << " dst: " << dst << " expireTime: " + << std::setprecision (9) << tempLink.stateExpireTime.GetSeconds() << " state: " << tempLink.linkState); + } + } + } +} + + +// This returns true if we should NOT send the packet. +// That is, return true == packet fails to send + +bool SimpleWirelessChannel::CheckStochasticError(uint32_t srcId, uint32_t dstId) +{ + if (m_ErrorModel == STOCHASTIC) + { + // get entry from map for this src/dst pair + StochasIt iter = m_StochasticLinks.find(StochasticKey(srcId, dstId)); + NS_ASSERT( iter != m_StochasticLinks.end()); + + Time currTime = Simulator::Now(); + + //std::cout << std::setprecision (9) << currTime.GetSeconds() << " Checking state for link src: " << srcId << " dst: " << dstId << " expireTime: " << iter->second.stateExpireTime << std::endl; + + if (currTime >= iter->second.stateExpireTime) + { + // the time at which the previous state was set to end has already passed. + Time endTime = iter->second.stateExpireTime; + bool tempState = iter->second.linkState; + Time newDuration; + // Pick the new states until we get to one that is at or greater + // than the current time. + while (endTime < currTime) + { + // Now pick duration for the new state + if (!tempState) + { + newDuration = MicroSeconds(m_randomUp->GetValue()); + } + else + { + newDuration = MicroSeconds(m_randomDown->GetValue()); + } + endTime += newDuration; + tempState = !tempState; + + NS_LOG_DEBUG("---> " << std::setprecision (9) << currTime.GetSeconds() << " next state: " << tempState << " for link src: " << srcId << " dst: " << dstId + << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds() + << " expireTime: " << std::setprecision (9) << endTime.GetSeconds()); + } + + // When we get here, the new state and time are selected + iter->second.linkState = tempState; + iter->second.stateExpireTime = endTime; + + NS_LOG_DEBUG(std::setprecision (9) << currTime.GetSeconds() << " New state " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId + << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds() + << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds()); + + } + else + { + NS_LOG_DEBUG(std::setprecision (9) << currTime.GetSeconds() << " State " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId + << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds()); + } + + // now return true or false depending on state + // true = packet is in "error" and failes + // false = packet not in error and sends + if (iter->second.linkState) + { + return false; + } + else + { + return true; + } + } + else + { + return false; + } +} + +//******************************************************************** + +bool SimpleWirelessChannel::packetInError(double distance) +{ + std::map::iterator it; + std::map::iterator up_iter; + std::map::iterator low_iter; + + if (m_ErrorModel == CONSTANT) + { + if ( m_random->GetValue () < m_errorRate ) + { + NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); + return true; + } + } + else if (m_ErrorModel == PER_CURVE) + { + it = mPERmap.find(distance); + if (it != mPERmap.end()) + { + // we found an exact match in the map for this distance + if (m_random->GetValue() < it->second) + { + NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); + return true; + } + } + else + { + // we did not find an exact match in the map. That's OK + // since it could actually be unlikely to find one. + // Now we just extrapolate between the two entries in the map + + // first get iterator to upper bound + up_iter = mPERmap.upper_bound(distance); + if (up_iter == mPERmap.end()) + { + // We shouldn't hit this situation because we already checked the distance + // relative to the range but go ahead and leave this here + // this distance is beyond the upper bound so error is 100% + NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); + return true; + } + + // Set low iter to upper then decrement it + low_iter = up_iter; + --low_iter; + + double errorRate = low_iter->second + ( ((distance - low_iter->first)/(up_iter->first - low_iter->first)) * (up_iter->second - low_iter->second)); + NS_LOG_INFO("Error Model: " << m_ErrorModel << " distance: " << distance << " calculated error rate: " << errorRate << " low distance: " << low_iter->first << " low error: " << low_iter->second + << " high distance: " << up_iter->first << " high error: " << up_iter->second); + + if (m_random->GetValue() < errorRate) + { + return true; + } + } + } + + + // if we get here then there were no errors + return false; +} + + +} // namespace ns3 diff --git a/model/simple-wireless-channel.h b/model/simple-wireless-channel.h index d71cd4a..13125b5 100644 --- a/model/simple-wireless-channel.h +++ b/model/simple-wireless-channel.h @@ -1,143 +1,143 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * Copyright (c) 2010 University of Washington - * - * 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 - * - */ -#ifndef SIMPLE_WIRELESS_CHANNEL_H -#define SIMPLE_WIRELESS_CHANNEL_H - -#include -#include "ns3/channel.h" -#include "ns3/mac48-address.h" -#include "ns3/random-variable-stream.h" -#include "ns3/enum.h" -#include "ns3/string.h" - - - -namespace ns3 { - -class SimpleWirelessNetDevice; -class Packet; - -enum ErrorModelType { - /** - * In Constant mode, the packet error rate is constant within the - * specified distance range. - */ - CONSTANT, - /** - * In PER Curve mode, the packet error curves are used to - * determine the error rate. The distance is used to look up the - * error rate. Note that the range value specified is ignored. - * User must build the PER curve by calling addToPERmodel. - */ - PER_CURVE, - /** - * In Stochastic mode, there are no per packet errors. Instead, - * the link to each neighbor is either on or off for randomly - * selected durations. - */ - STOCHASTIC -}; - -//*************************************************************** -// Define key for stochastic error map key -//*************************************************************** -class StochasticKey { - public: - int srcNodeId; - int destNodeId; - - StochasticKey(int k1, int k2) - : srcNodeId(k1), destNodeId(k2){} - - // Ordering is: - // 1. lowest source node id - // 2. lowest destination node id - - bool operator<(const StochasticKey &right) const - { - if (srcNodeId == right.srcNodeId) - { - return(destNodeId < right.destNodeId); - } - else - { - return (srcNodeId < right.srcNodeId); - } - } -}; - -struct StochasticLink -{ - bool linkState; // 1 = ON, 0 = OFF - Time stateExpireTime; -}; - -typedef std::map ::iterator StochasIt; - -/** - * \ingroup channel - * \brief A simple channel, for simple things and testing - */ -class SimpleWirelessChannel : public Channel -{ -public: - static TypeId GetTypeId (void); - SimpleWirelessChannel (); - - void Send (Ptr p, uint16_t protocol, Mac48Address to, Mac48Address from, - Ptr sender, Time txTime, uint32_t destId); - - void Add (Ptr device); - - // inherited from ns3::Channel - virtual uint32_t GetNDevices (void) const; - virtual Ptr GetDevice (uint32_t i) const; - - void setErrorModelType(ErrorModelType type); - void setErrorRate(double error); - void addToPERmodel(double distance, double error); - bool packetInError(double distance); - void EnableFixedContention(void); - void SetFixedContentionRange(double error); - void InitStochasticModel(); - bool CheckStochasticError(uint32_t srcId, uint32_t dstId); - -private: - std::vector > m_devices; - double m_range; - double m_errorRate; - ErrorModelType m_ErrorModel; - Ptr m_random; - std::map mPERmap; - - bool m_fixedContentionEnabled; - double m_fixedContentionRange; - Ptr m_randomUp; - Ptr m_randomDown; - - Time m_upDuration; - Time m_downDuration; - std::map m_StochasticLinks; - -}; - -} // namespace ns3 - -#endif /* SIMPLE_WIRELESS_CHANNEL_H */ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2010 University of Washington + * + * 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 + * + */ +#ifndef SIMPLE_WIRELESS_CHANNEL_H +#define SIMPLE_WIRELESS_CHANNEL_H + +#include +#include "ns3/channel.h" +#include "ns3/mac48-address.h" +#include "ns3/random-variable-stream.h" +#include "ns3/enum.h" +#include "ns3/string.h" + + + +namespace ns3 { + +class SimpleWirelessNetDevice; +class Packet; + +enum ErrorModelType { + /** + * In Constant mode, the packet error rate is constant within the + * specified distance range. + */ + CONSTANT, + /** + * In PER Curve mode, the packet error curves are used to + * determine the error rate. The distance is used to look up the + * error rate. Note that the range value specified is ignored. + * User must build the PER curve by calling addToPERmodel. + */ + PER_CURVE, + /** + * In Stochastic mode, there are no per packet errors. Instead, + * the link to each neighbor is either on or off for randomly + * selected durations. + */ + STOCHASTIC +}; + +//*************************************************************** +// Define key for stochastic error map key +//*************************************************************** +class StochasticKey { + public: + int srcNodeId; + int destNodeId; + + StochasticKey(int k1, int k2) + : srcNodeId(k1), destNodeId(k2){} + + // Ordering is: + // 1. lowest source node id + // 2. lowest destination node id + + bool operator<(const StochasticKey &right) const + { + if (srcNodeId == right.srcNodeId) + { + return(destNodeId < right.destNodeId); + } + else + { + return (srcNodeId < right.srcNodeId); + } + } +}; + +struct StochasticLink +{ + bool linkState; // 1 = ON, 0 = OFF + Time stateExpireTime; +}; + +typedef std::map ::iterator StochasIt; + +/** + * \ingroup channel + * \brief A simple channel, for simple things and testing + */ +class SimpleWirelessChannel : public Channel +{ +public: + static TypeId GetTypeId (void); + SimpleWirelessChannel (); + + void Send (Ptr p, uint16_t protocol, Mac48Address to, Mac48Address from, + Ptr sender, Time txTime, uint32_t destId); + + void Add (Ptr device); + + // inherited from ns3::Channel + virtual uint32_t GetNDevices (void) const; + virtual Ptr GetDevice (uint32_t i) const; + + void setErrorModelType(ErrorModelType type); + void setErrorRate(double error); + void addToPERmodel(double distance, double error); + bool packetInError(double distance); + void EnableFixedContention(void); + void SetFixedContentionRange(double error); + void InitStochasticModel(); + bool CheckStochasticError(uint32_t srcId, uint32_t dstId); + +private: + std::vector > m_devices; + double m_range; + double m_errorRate; + ErrorModelType m_ErrorModel; + Ptr m_random; + std::map mPERmap; + + bool m_fixedContentionEnabled; + double m_fixedContentionRange; + Ptr m_randomUp; + Ptr m_randomDown; + + Time m_upDuration; + Time m_downDuration; + std::map m_StochasticLinks; + +}; + +} // namespace ns3 + +#endif /* SIMPLE_WIRELESS_CHANNEL_H */ diff --git a/model/simple-wireless-net-device.cc b/model/simple-wireless-net-device.cc index 8a5803d..32ccf25 100644 --- a/model/simple-wireless-net-device.cc +++ b/model/simple-wireless-net-device.cc @@ -1,877 +1,877 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * Copyright (c) 2010 University of Washington - * - * 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 - * - */ -#include "ns3/node.h" -#include "ns3/packet.h" -#include "ns3/log.h" -#include "ns3/pointer.h" -#include "ns3/error-model.h" -#include "ns3/trace-source-accessor.h" -#include "simple-wireless-net-device.h" -#include "simple-wireless-channel.h" - -#include // needed for noth for protocol # in sniffer - -NS_LOG_COMPONENT_DEFINE ("SimpleWirelessNetDevice"); - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (SimpleWirelessNetDevice); - -//******************************************************** -// TimestampTag used to store a timestamp with a packet -// when they are placed in the queue -//******************************************************** -TypeId TimestampTag::GetTypeId (void) -{ - static TypeId tid = TypeId ("TimestampTag") - .SetParent () - .AddConstructor () - .AddAttribute ("Timestamp", - "Some momentous point in time!", - EmptyAttributeValue (), - MakeTimeAccessor (&TimestampTag::GetTimestamp), - MakeTimeChecker ()) - ; - return tid; -} - -TypeId TimestampTag::GetInstanceTypeId (void) const -{ - return GetTypeId (); -} - -uint32_t TimestampTag::GetSerializedSize (void) const -{ - return 8; -} - -void TimestampTag::Serialize (TagBuffer i) const -{ - int64_t t = m_timestamp.GetNanoSeconds (); - i.Write ((const uint8_t *)&t, 8); -} - -void TimestampTag::Deserialize (TagBuffer i) -{ - int64_t t; - i.Read ((uint8_t *)&t, 8); - m_timestamp = NanoSeconds (t); -} - -void TimestampTag::SetTimestamp (Time time) -{ - m_timestamp = time; -} - -Time TimestampTag::GetTimestamp (void) const -{ - return m_timestamp; -} - -void TimestampTag::Print (std::ostream &os) const -{ - os << "t=" << m_timestamp; -} - -//******************************************************** - -//******************************************************** -// DestinationIdTag used to store a destination node id -// with a packet when they are placed in the queue. -// This is used by directional networks. -//******************************************************** -TypeId DestinationIdTag::GetTypeId (void) -{ - static TypeId tid = TypeId ("DestinationIdTag") - .SetParent () - .AddConstructor () - ; - return tid; -} - -TypeId DestinationIdTag::GetInstanceTypeId (void) const -{ - return GetTypeId (); -} - -DestinationIdTag::DestinationIdTag () -{ -} - -DestinationIdTag::DestinationIdTag (uint32_t destId) - : m_destnodeid (destId) -{ -} - -uint32_t DestinationIdTag::GetSerializedSize (void) const -{ - return 4; -} - -void DestinationIdTag::Serialize (TagBuffer i) const -{ - i.WriteU32 (m_destnodeid); -} - -void DestinationIdTag::Deserialize (TagBuffer i) -{ - m_destnodeid = i.ReadU32 (); -} - -void DestinationIdTag::SetDestinationId (uint32_t id) -{ - m_destnodeid = id; -} - -uint32_t DestinationIdTag::GetDestinationId (void) const -{ - return m_destnodeid; -} - -void DestinationIdTag::Print (std::ostream &os) const -{ - os << "t=" << m_destnodeid; -} - -//******************************************************** - -TypeId -SimpleWirelessNetDevice::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::SimpleWirelessNetDevice") - .SetParent () - .AddConstructor () - .AddAttribute ("ReceiveErrorModel", - "The receiver error model used to simulate packet loss", - PointerValue (), - MakePointerAccessor (&SimpleWirelessNetDevice::m_receiveErrorModel), - MakePointerChecker ()) - .AddAttribute ("DataRate", - "The default data rate for point to point links", - DataRateValue (DataRate ("1000000b/s")), - MakeDataRateAccessor (&SimpleWirelessNetDevice::m_bps), - MakeDataRateChecker ()) - // Transmit queueing discipline for the device which includes its own set - // of trace hooks. - .AddAttribute ("TxQueue", - "A queue to use as the transmit queue in the device.", - PointerValue (), - MakePointerAccessor (&SimpleWirelessNetDevice::m_queue), - MakePointerChecker ()) - .AddAttribute ("FixedNeighborListEnabled", - "Enabled or Disabled", - BooleanValue (false), - MakeBooleanAccessor (&SimpleWirelessNetDevice::m_fixedNbrListEnabled), - MakeBooleanChecker ()) - .AddTraceSource ("PhyTxBegin", - "Trace source indicating a packet has begun transmitting", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_TxBeginTrace)) - .AddTraceSource ("PhyRxDrop", - "Trace source indicating a packet has been dropped by the device during reception", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxDropTrace)) - .AddTraceSource ("PhyRxBegin", - "Trace source indicating a packet " - "has begun being received from the channel medium " - "by the device", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxBeginTrace)) - .AddTraceSource ("PhyRxEnd", - "Trace source indicating a packet " - "has been completely received from the channel medium " - "by the device", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxEndTrace)) - // Trace sources designed to simulate a packet sniffer facility (tcpdump). - .AddTraceSource ("PromiscSniffer", - "Trace source simulating a promiscuous packet sniffer attached to the device", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_promiscSnifferTrace)) - .AddTraceSource ("QueueLatency", - "Trace source to report the latency of a packet in the queue. Datatype returned is Time.", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_QueueLatencyTrace)) - .AddTraceSource ("MacTx", - "A packet has been received from higher layers and is being processed in preparation for " - "queueing for transmission.", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macTxTrace)) - .AddTraceSource ("MacRx", - "A packet has been received by this device, has been passed up from the physical layer " - "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macRxTrace)) - ; - return tid; -} - -SimpleWirelessNetDevice::SimpleWirelessNetDevice () - : m_channel (0), - m_node (0), - m_mtu (0xffff), - m_ifIndex (0), - m_txMachineState (READY), - m_queue(NULL), - m_pktRcvTotal(0), - m_pktRcvDrop(0), - m_pcapEnabled(false), - m_fixedNbrListEnabled(false), - m_nbrCount(0) - -{} - -void -SimpleWirelessNetDevice::Receive (Ptr packet, uint16_t protocol, - Mac48Address to, Mac48Address from) -{ - NS_LOG_FUNCTION (packet << protocol << to << from); - NetDevice::PacketType packetType; - - m_phyRxBeginTrace (packet, from, to, protocol); - m_pktRcvTotal++; - - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " receiving packet " << packet->GetUid () << " from " << from << " to " << to ); - - if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) ) - { - m_phyRxDropTrace (packet, from, to, protocol); - m_pktRcvDrop++; - return; - } - - if (m_pcapEnabled) - { - // Add the ethernet header to the packet for sniffer - // For some reason the Ethernet header is STRIPPED from the packet - // by the time we get here so we need to reconstruct it for the - // sniffer. - // allocate buffer for packet and mac addresses - uint8_t buffer[8192]; - uint8_t macBuffer[6]; - // get the dest and src addresses and copy into the buffer - to.CopyTo(macBuffer); - memcpy(&buffer[0], macBuffer, 6); - from.CopyTo(macBuffer); - memcpy(&buffer[6], macBuffer, 6); - //copy the protocol and the actual packet data in the the buffer - uint16_t tempProt = ntohs(protocol); - memcpy(&buffer[12], &tempProt, 2); - packet->CopyData(&buffer[14], packet->GetSize()); - // Now make a new temp packet to write to the sniffer - Ptr tempPacket = Create (buffer, packet->GetSize() + 14); - m_promiscSnifferTrace (tempPacket); - } - - if (to == m_address) - { - packetType = NetDevice::PACKET_HOST; - } - else if (to.IsBroadcast ()) - { - packetType = NetDevice::PACKET_BROADCAST; - } - else if (to.IsGroup ()) - { - packetType = NetDevice::PACKET_MULTICAST; - } - else - { - packetType = NetDevice::PACKET_OTHERHOST; - } - - m_phyRxEndTrace (packet, from, to, protocol); - - if (packetType != NetDevice::PACKET_OTHERHOST) - { - m_macRxTrace (packet); - m_rxCallback (this, packet, protocol, from); - } - - - if (!m_promiscCallback.IsNull ()) - { - m_promiscCallback (this, packet, protocol, from, to, packetType); - } - NS_LOG_DEBUG ("Total Rcvd: " << m_pktRcvTotal << " Total Dropped: " << m_pktRcvDrop); -} - -void -SimpleWirelessNetDevice::SetChannel (Ptr channel) -{ - m_channel = channel; - m_channel->Add (this); -} - -void -SimpleWirelessNetDevice::SetReceiveErrorModel (Ptr em) -{ - m_receiveErrorModel = em; -} - -void -SimpleWirelessNetDevice::SetIfIndex(const uint32_t index) -{ - m_ifIndex = index; -} -uint32_t -SimpleWirelessNetDevice::GetIfIndex(void) const -{ - return m_ifIndex; -} -Ptr -SimpleWirelessNetDevice::GetChannel (void) const -{ - return m_channel; -} -void -SimpleWirelessNetDevice::SetAddress (Address address) -{ - m_address = Mac48Address::ConvertFrom(address); -} -Address -SimpleWirelessNetDevice::GetAddress (void) const -{ - // - // Implicit conversion from Mac48Address to Address - // - return m_address; -} -bool -SimpleWirelessNetDevice::SetMtu (const uint16_t mtu) -{ - m_mtu = mtu; - return true; -} -uint16_t -SimpleWirelessNetDevice::GetMtu (void) const -{ - return m_mtu; -} -bool -SimpleWirelessNetDevice::IsLinkUp (void) const -{ - return true; -} -void -SimpleWirelessNetDevice::AddLinkChangeCallback (Callback callback) -{} -bool -SimpleWirelessNetDevice::IsBroadcast (void) const -{ - return true; -} -Address -SimpleWirelessNetDevice::GetBroadcast (void) const -{ - return Mac48Address ("ff:ff:ff:ff:ff:ff"); -} -bool -SimpleWirelessNetDevice::IsMulticast (void) const -{ - return false; -} -Address -SimpleWirelessNetDevice::GetMulticast (Ipv4Address multicastGroup) const -{ - return Mac48Address::GetMulticast (multicastGroup); -} - -Address SimpleWirelessNetDevice::GetMulticast (Ipv6Address addr) const -{ - return Mac48Address::GetMulticast (addr); -} - -bool -SimpleWirelessNetDevice::IsPointToPoint (void) const -{ - return false; -} - -bool -SimpleWirelessNetDevice::IsBridge (void) const -{ - return false; -} - -//******************************************************************** -// Directional Neighbor functions -bool SimpleWirelessNetDevice::AddDirectionalNeighbors(std::map nodesToAdd) -{ - // is directional neighbor feature enabled? - // If not return false so caller knows there is a problem - if (!m_fixedNbrListEnabled) - return false; - - for ( std::map ::iterator it = nodesToAdd.begin(); it != nodesToAdd.end(); ++it) - { - mDirectionalNbrs.insert(std::pair(it->first, it->second)); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " added directional neighbor " << it->first << " mac Address " << it->second); - } - return true; -} - -bool SimpleWirelessNetDevice::AddDirectionalNeighbor(uint32_t nodeid, Mac48Address macAddr) -{ - // is directional neighbor feature enabled? - // If not return false so caller knows there is a problem - if (!m_fixedNbrListEnabled) - return false; - - mDirectionalNbrs.insert(std::pair(nodeid, macAddr)); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " added directional neighbor " << nodeid << " mac Address " << macAddr); - return true; -} - -void SimpleWirelessNetDevice::DeleteDirectionalNeighbors(std::set nodeids) -{ - for ( std::set::iterator it = nodeids.begin(); it != nodeids.end(); ++it) - { - std::map::iterator it2 = mDirectionalNbrs.find(*it); - if (it2 != mDirectionalNbrs.end()) - { - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " deleted directional neighbor " << it2->first << " mac Address " << it2->second); - mDirectionalNbrs.erase(it2); - } - } -} - -void SimpleWirelessNetDevice::DeleteDirectionalNeighbor(uint32_t nodeid) -{ - std::map::iterator it = mDirectionalNbrs.find(nodeid); - if (it != mDirectionalNbrs.end()) - { - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " deleted directional neighbor " << nodeid << " mac Address " << it->second); - mDirectionalNbrs.erase(it); - } -} - -//******************************************************************** -// Fixed Contention functions -void SimpleWirelessNetDevice::ClearNbrCount(void) -{ - // When we clear the neighbor count, we actually set it to 1 and not 0 - // because we always have to count ourselves. - m_nbrCount = 1; -} - -void SimpleWirelessNetDevice::IncrementNbrCount(void) -{ - m_nbrCount++; -} - -int SimpleWirelessNetDevice::GetNbrCount(void) -{ - return m_nbrCount; -} - - -//******************************************************************** - -void -SimpleWirelessNetDevice::TransmitStart (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - - // This function is called to start the process of transmitting a packet. - // We need to tell the channel that we've started wiggling the wire and - // schedule an event that will be executed when the transmission is complete. - NS_ASSERT_MSG (m_txMachineState == READY, "Must be READY to transmit"); - m_txMachineState = BUSY; - m_currentPkt = p; - - if (m_pcapEnabled) - { - m_promiscSnifferTrace (p); - } - - // Remove the timestamp tag. calculate queue latency and peg trace - TimestampTag timeEnqueued; - p->RemovePacketTag (timeEnqueued); - Time latency = Simulator::Now() - timeEnqueued.GetTimestamp(); - m_QueueLatencyTrace(p, latency); - NS_LOG_DEBUG (Simulator::Now() << " Getting packet with timestamp: " << timeEnqueued.GetTimestamp() ); - - // Remove ethernet header since it is not sent over the air - // To this AFTER the queue latency trace in case the trace wants - // to use anything in the Ethernet header - EthernetHeader ethHeader; - p->RemoveHeader(ethHeader); - Mac48Address to = ethHeader.GetDestination (); - Mac48Address from = ethHeader.GetSource (); - uint16_t protocol = ethHeader.GetLengthType (); - - - // Get dest Id tag. This could be the default NO_DIRECTIONAL_NBR - DestinationIdTag destIdTag; - p->RemovePacketTag (destIdTag); - uint32_t destId = destIdTag.GetDestinationId(); - - Time txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ())); - - // If we have a non-zero neighbor count then that means we are using contention and - // the data rate changes. Note that when using contention, we will always have at least - // a value of 1 for neighbor count because we count ourselves. - // If this device is omni then data rate changes to data rate/# neighbors. - // Thus multiply the tx time by the number of neighbors (which is the same as dividing the - // data rate by # neighbors) - // If this device is directional then the data rate is rate/2. Thus multiply the tx time by 2. - - // IMPORTANT NOTE: If we are using contention, the first packet we send may not "know" - // that there is contention. This is a chicken and egg situation. - // The device keeps the neighbor count (which is init'd to 0) but the channel is - // the one that has contention. When contention is enabled on the channel, there may not be - // any devices to initial with the contention (i.e., set nbr count to 1). The function in the - // channel that sets contention enabled also notifies all the devices on the channel but if - // there are not devices yet when the function is called then the first packet sent on the - // channel by the device is what will cause the device to get init'd for contention. That is - // after the device set the txTime so that first packet will be sent at full data rate. - if (m_nbrCount) - { - if (m_fixedNbrListEnabled) - { - txTime = txTime * 2; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << p->GetSize ()); - } - else - { - txTime = txTime * m_nbrCount; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << p->GetSize ()); - } - } - // TO DO: do we need interframe gap?? - //Time txCompleteTime = txTime + m_tInterframeGap; - Time txCompleteTime = txTime; - - NS_LOG_DEBUG ("Schedule TransmitCompleteEvent in " << txCompleteTime.GetMicroSeconds () << "usec"); - Simulator::Schedule (txCompleteTime, &SimpleWirelessNetDevice::TransmitComplete, this); - - m_TxBeginTrace (p, from, to, protocol); - - m_channel->Send (p, protocol, to, from, this, txTime, destId); -} - -void -SimpleWirelessNetDevice::TransmitComplete (void) -{ - NS_LOG_FUNCTION_NOARGS (); - - // This function is called to when we're all done transmitting a packet. - // We try and pull another packet off of the transmit queue. If the queue - // is empty, we are done, otherwise we need to start transmitting the - // next packet. - NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting"); - m_txMachineState = READY; - - NS_ASSERT_MSG (m_currentPkt != 0, "SimpleWirelessNetDevice::TransmitComplete(): m_currentPkt zero"); - m_currentPkt = 0; - - NS_LOG_DEBUG (Simulator::Now() << " Tx complete. Packets in queue: " << m_queue->GetNPackets() << " Bytes in queue: " << m_queue->GetNBytes()); - - - Ptr p = m_queue->Dequeue (); - if (p == 0) - { - // No packet was on the queue, so we just exit. - return; - } - - // Got another packet off of the queue, so start the transmit process agin. - TransmitStart (p); -} - - -bool -SimpleWirelessNetDevice::Send(Ptr packet, const Address& dest, uint16_t protocolNumber) -{ - NS_LOG_FUNCTION (packet << dest << protocolNumber); - Mac48Address to = Mac48Address::ConvertFrom (dest); - - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " sending packet " << packet->GetUid () << " to " << to ); - - // For some reason the Ethernet header is STRIPPED from the packet - // by the time we get here so we need to reconstruct it for for two reasons. - // If queuing, add ethernet header to the packet in the queue so we can - // retrieve the to, from and protocol. Also Ethernet header is - // needed so we can apply a pcap filter in priority queues - EthernetHeader ethHeader; - ethHeader.SetSource (m_address); - ethHeader.SetDestination (to); - ethHeader.SetLengthType (protocolNumber); - packet->AddHeader (ethHeader); - - m_macTxTrace (packet); - - // If directional networking is enabled, then we have to make a copy - // of this packet and enqueue it for each destination. - if (m_fixedNbrListEnabled) - { - std::map::iterator it; - - // Look up the dest address in the eth header of the packet. - // This is necessary because in directional networks, the dest - // could have been changed by the trace - packet->PeekHeader(ethHeader); - to = ethHeader.GetDestination(); - - if (to.IsBroadcast()) - { - NS_LOG_INFO ("Address " << to << " is broadcast"); - // broadcast packet. Enqueue for all of our directional neighbors - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) - { - EnqueuePacket(packet->Copy(),m_address,to,protocolNumber,it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet to directional neighbor to node " << it->first); - } - } - else - { - NS_LOG_INFO ("Address " << to << " is NOT broadcast"); - // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) - { - if (it->second == to) - { - EnqueuePacket(packet->Copy(),m_address,to,protocolNumber, it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " found node " << it->first << " with matching Mac Address " << to); - break; - } - } - } - } - else - { - EnqueuePacket(packet,m_address,to,protocolNumber, NO_DIRECTIONAL_NBR); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet"); - } - - return true; - -} - - -bool -SimpleWirelessNetDevice::SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) -{ - NS_LOG_FUNCTION (packet << dest << protocolNumber); - Mac48Address to = Mac48Address::ConvertFrom (dest); - Mac48Address from = Mac48Address::ConvertFrom (source); - - // For some reason the Ethernet header is STRIPPED from the packet - // by the time we get here so we need to reconstruct it for for two reasons. - // If queuing, add ethernet header to the packet in the queue so we can - // retrieve the to, from and protocol. Also Ethernet header is - // needed so we can apply a pcap filter in priority queues - EthernetHeader ethHeader; - ethHeader.SetSource (from); - ethHeader.SetDestination (to); - ethHeader.SetLengthType (protocolNumber); - packet->AddHeader (ethHeader); - - m_macTxTrace (packet); - - - // If directional networking is enabled, then we have to make a copy - // of this packet and enqueue it for each destination. - if (m_fixedNbrListEnabled) - { - std::map::iterator it; - - // Look up the dest address in the eth header of the packet. - // This is necessary because in directional networks, the dest - // could have been changed by the trace - packet->PeekHeader(ethHeader); - to = ethHeader.GetDestination(); - - if (to.IsBroadcast()) - { - NS_LOG_INFO ("Address " << to << " is broadcast"); - // broadcast packet. Enqueue for all of our directional neighbors - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) - { - // Note that we do not alter the to (mac address) here but instead specify - // the node id as the destination. This gets carried with the packet - // as a destination tag and passed to the channel. At the channel it still - // appears as a broadcast packet but the channel only uses the dest id so it - // will know how to handle it from the perspective of directional networking. - EnqueuePacket(packet->Copy(),from,to,protocolNumber,it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet to directional neighbor to node " << it->first); - } - } - else - { - NS_LOG_INFO ("Address " << to << " is NOT broadcast"); - // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) - { - if (it->second == to) - { - EnqueuePacket(packet->Copy(),from,to,protocolNumber, it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " found node " << it->first << " with matching Mac Address " << to); - break; - } - } - } - } - else - { - EnqueuePacket(packet,from,to,protocolNumber, NO_DIRECTIONAL_NBR); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet"); - } - - return true; - -} - -bool -SimpleWirelessNetDevice::EnqueuePacket (Ptr packet, Mac48Address from, Mac48Address to, uint16_t protocolNumber, uint32_t destId) -{ - - if (m_queue) - { - // We are using queueing. - - // Add a timestamp tag for latency - TimestampTag timestamp; - timestamp.SetTimestamp (Simulator::Now ()); - packet->AddPacketTag (timestamp); - - // add destination tag - DestinationIdTag idTag(destId); - packet->AddPacketTag (idTag); - - NS_LOG_DEBUG ("Queueing packet for destination " << destId << ". Protocol "<< protocolNumber << " Current state is: " << m_txMachineState); - - // We should enqueue and dequeue the packet to hit the tracing hooks. - if (m_queue->Enqueue (packet)) - { - // If the channel is ready for transition we send the packet right now - if (m_txMachineState == READY) - { - packet = m_queue->Dequeue (); - TransmitStart (packet); - } - return true; - } - - // TO DO: do we return true or false here?? - return true; - } - else - { - // No queuing is being used. Just send the packet. - if (m_pcapEnabled) - { - m_promiscSnifferTrace (packet); - } - EthernetHeader ethHeader; - packet->RemoveHeader(ethHeader); - - m_TxBeginTrace (packet, m_address, to, protocolNumber); - Time txTime = Seconds (m_bps.CalculateTxTime (packet->GetSize ())); - // If we have a non-zero neighbor count then that means we are using contention and - // the data rate changes. - if (m_nbrCount) - { - if (m_fixedNbrListEnabled) - { - txTime = txTime * 2; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << packet->GetSize ()); - } - else - { - txTime = txTime * m_nbrCount; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << packet->GetSize ()); - } - } - m_channel->Send (packet, protocolNumber, to, from, this, txTime, destId); - return true; - } -} - - - - -Ptr -SimpleWirelessNetDevice::GetNode (void) const -{ - return m_node; -} -void -SimpleWirelessNetDevice::SetNode (Ptr node) -{ - m_node = node; -} -bool -SimpleWirelessNetDevice::NeedsArp (void) const -{ - return true; -} -void -SimpleWirelessNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb) -{ - m_rxCallback = cb; -} - -void -SimpleWirelessNetDevice::DoDispose (void) -{ - m_channel = 0; - m_node = 0; - m_receiveErrorModel = 0; - NetDevice::DoDispose (); -} - - -void -SimpleWirelessNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb) -{ - m_promiscCallback = cb; -} - -bool -SimpleWirelessNetDevice::SupportsSendFrom (void) const -{ - return true; -} - -void -SimpleWirelessNetDevice::SetDataRate (DataRate bps) -{ - NS_LOG_FUNCTION_NOARGS (); - m_bps = bps; -} - -void -SimpleWirelessNetDevice::SetQueue (Ptr q) -{ - NS_LOG_FUNCTION (this << q); - m_queue = q; -} - -Ptr -SimpleWirelessNetDevice::GetQueue (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_queue; -} - - -void SimpleWirelessNetDevice::EnablePcapAll (std::string filename) -{ - PcapHelper pcapHelper; - Ptr file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_EN10MB); - pcapHelper.HookDefaultSink (this, "PromiscSniffer", file); - m_pcapEnabled = true; -} - -} // namespace ns3 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2010 University of Washington + * + * 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 + * + */ +#include "ns3/node.h" +#include "ns3/packet.h" +#include "ns3/log.h" +#include "ns3/pointer.h" +#include "ns3/error-model.h" +#include "ns3/trace-source-accessor.h" +#include "simple-wireless-net-device.h" +#include "simple-wireless-channel.h" + +#include // needed for noth for protocol # in sniffer + +NS_LOG_COMPONENT_DEFINE ("SimpleWirelessNetDevice"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (SimpleWirelessNetDevice); + +//******************************************************** +// TimestampTag used to store a timestamp with a packet +// when they are placed in the queue +//******************************************************** +TypeId TimestampTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("TimestampTag") + .SetParent () + .AddConstructor () + .AddAttribute ("Timestamp", + "Some momentous point in time!", + EmptyAttributeValue (), + MakeTimeAccessor (&TimestampTag::GetTimestamp), + MakeTimeChecker ()) + ; + return tid; +} + +TypeId TimestampTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t TimestampTag::GetSerializedSize (void) const +{ + return 8; +} + +void TimestampTag::Serialize (TagBuffer i) const +{ + int64_t t = m_timestamp.GetNanoSeconds (); + i.Write ((const uint8_t *)&t, 8); +} + +void TimestampTag::Deserialize (TagBuffer i) +{ + int64_t t; + i.Read ((uint8_t *)&t, 8); + m_timestamp = NanoSeconds (t); +} + +void TimestampTag::SetTimestamp (Time time) +{ + m_timestamp = time; +} + +Time TimestampTag::GetTimestamp (void) const +{ + return m_timestamp; +} + +void TimestampTag::Print (std::ostream &os) const +{ + os << "t=" << m_timestamp; +} + +//******************************************************** + +//******************************************************** +// DestinationIdTag used to store a destination node id +// with a packet when they are placed in the queue. +// This is used by directional networks. +//******************************************************** +TypeId DestinationIdTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("DestinationIdTag") + .SetParent () + .AddConstructor () + ; + return tid; +} + +TypeId DestinationIdTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +DestinationIdTag::DestinationIdTag () +{ +} + +DestinationIdTag::DestinationIdTag (uint32_t destId) + : m_destnodeid (destId) +{ +} + +uint32_t DestinationIdTag::GetSerializedSize (void) const +{ + return 4; +} + +void DestinationIdTag::Serialize (TagBuffer i) const +{ + i.WriteU32 (m_destnodeid); +} + +void DestinationIdTag::Deserialize (TagBuffer i) +{ + m_destnodeid = i.ReadU32 (); +} + +void DestinationIdTag::SetDestinationId (uint32_t id) +{ + m_destnodeid = id; +} + +uint32_t DestinationIdTag::GetDestinationId (void) const +{ + return m_destnodeid; +} + +void DestinationIdTag::Print (std::ostream &os) const +{ + os << "t=" << m_destnodeid; +} + +//******************************************************** + +TypeId +SimpleWirelessNetDevice::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::SimpleWirelessNetDevice") + .SetParent () + .AddConstructor () + .AddAttribute ("ReceiveErrorModel", + "The receiver error model used to simulate packet loss", + PointerValue (), + MakePointerAccessor (&SimpleWirelessNetDevice::m_receiveErrorModel), + MakePointerChecker ()) + .AddAttribute ("DataRate", + "The default data rate for point to point links", + DataRateValue (DataRate ("1000000b/s")), + MakeDataRateAccessor (&SimpleWirelessNetDevice::m_bps), + MakeDataRateChecker ()) + // Transmit queueing discipline for the device which includes its own set + // of trace hooks. + .AddAttribute ("TxQueue", + "A queue to use as the transmit queue in the device.", + PointerValue (), + MakePointerAccessor (&SimpleWirelessNetDevice::m_queue), + MakePointerChecker ()) + .AddAttribute ("FixedNeighborListEnabled", + "Enabled or Disabled", + BooleanValue (false), + MakeBooleanAccessor (&SimpleWirelessNetDevice::m_fixedNbrListEnabled), + MakeBooleanChecker ()) + .AddTraceSource ("PhyTxBegin", + "Trace source indicating a packet has begun transmitting", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_TxBeginTrace)) + .AddTraceSource ("PhyRxDrop", + "Trace source indicating a packet has been dropped by the device during reception", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxDropTrace)) + .AddTraceSource ("PhyRxBegin", + "Trace source indicating a packet " + "has begun being received from the channel medium " + "by the device", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxBeginTrace)) + .AddTraceSource ("PhyRxEnd", + "Trace source indicating a packet " + "has been completely received from the channel medium " + "by the device", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxEndTrace)) + // Trace sources designed to simulate a packet sniffer facility (tcpdump). + .AddTraceSource ("PromiscSniffer", + "Trace source simulating a promiscuous packet sniffer attached to the device", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_promiscSnifferTrace)) + .AddTraceSource ("QueueLatency", + "Trace source to report the latency of a packet in the queue. Datatype returned is Time.", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_QueueLatencyTrace)) + .AddTraceSource ("MacTx", + "A packet has been received from higher layers and is being processed in preparation for " + "queueing for transmission.", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macTxTrace)) + .AddTraceSource ("MacRx", + "A packet has been received by this device, has been passed up from the physical layer " + "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,", + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macRxTrace)) + ; + return tid; +} + +SimpleWirelessNetDevice::SimpleWirelessNetDevice () + : m_channel (0), + m_node (0), + m_mtu (0xffff), + m_ifIndex (0), + m_txMachineState (READY), + m_queue(NULL), + m_pktRcvTotal(0), + m_pktRcvDrop(0), + m_pcapEnabled(false), + m_fixedNbrListEnabled(false), + m_nbrCount(0) + +{} + +void +SimpleWirelessNetDevice::Receive (Ptr packet, uint16_t protocol, + Mac48Address to, Mac48Address from) +{ + NS_LOG_FUNCTION (packet << protocol << to << from); + NetDevice::PacketType packetType; + + m_phyRxBeginTrace (packet, from, to, protocol); + m_pktRcvTotal++; + + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " receiving packet " << packet->GetUid () << " from " << from << " to " << to ); + + if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) ) + { + m_phyRxDropTrace (packet, from, to, protocol); + m_pktRcvDrop++; + return; + } + + if (m_pcapEnabled) + { + // Add the ethernet header to the packet for sniffer + // For some reason the Ethernet header is STRIPPED from the packet + // by the time we get here so we need to reconstruct it for the + // sniffer. + // allocate buffer for packet and mac addresses + uint8_t buffer[8192]; + uint8_t macBuffer[6]; + // get the dest and src addresses and copy into the buffer + to.CopyTo(macBuffer); + memcpy(&buffer[0], macBuffer, 6); + from.CopyTo(macBuffer); + memcpy(&buffer[6], macBuffer, 6); + //copy the protocol and the actual packet data in the the buffer + uint16_t tempProt = ntohs(protocol); + memcpy(&buffer[12], &tempProt, 2); + packet->CopyData(&buffer[14], packet->GetSize()); + // Now make a new temp packet to write to the sniffer + Ptr tempPacket = Create (buffer, packet->GetSize() + 14); + m_promiscSnifferTrace (tempPacket); + } + + if (to == m_address) + { + packetType = NetDevice::PACKET_HOST; + } + else if (to.IsBroadcast ()) + { + packetType = NetDevice::PACKET_BROADCAST; + } + else if (to.IsGroup ()) + { + packetType = NetDevice::PACKET_MULTICAST; + } + else + { + packetType = NetDevice::PACKET_OTHERHOST; + } + + m_phyRxEndTrace (packet, from, to, protocol); + + if (packetType != NetDevice::PACKET_OTHERHOST) + { + m_macRxTrace (packet); + m_rxCallback (this, packet, protocol, from); + } + + + if (!m_promiscCallback.IsNull ()) + { + m_promiscCallback (this, packet, protocol, from, to, packetType); + } + NS_LOG_DEBUG ("Total Rcvd: " << m_pktRcvTotal << " Total Dropped: " << m_pktRcvDrop); +} + +void +SimpleWirelessNetDevice::SetChannel (Ptr channel) +{ + m_channel = channel; + m_channel->Add (this); +} + +void +SimpleWirelessNetDevice::SetReceiveErrorModel (Ptr em) +{ + m_receiveErrorModel = em; +} + +void +SimpleWirelessNetDevice::SetIfIndex(const uint32_t index) +{ + m_ifIndex = index; +} +uint32_t +SimpleWirelessNetDevice::GetIfIndex(void) const +{ + return m_ifIndex; +} +Ptr +SimpleWirelessNetDevice::GetChannel (void) const +{ + return m_channel; +} +void +SimpleWirelessNetDevice::SetAddress (Address address) +{ + m_address = Mac48Address::ConvertFrom(address); +} +Address +SimpleWirelessNetDevice::GetAddress (void) const +{ + // + // Implicit conversion from Mac48Address to Address + // + return m_address; +} +bool +SimpleWirelessNetDevice::SetMtu (const uint16_t mtu) +{ + m_mtu = mtu; + return true; +} +uint16_t +SimpleWirelessNetDevice::GetMtu (void) const +{ + return m_mtu; +} +bool +SimpleWirelessNetDevice::IsLinkUp (void) const +{ + return true; +} +void +SimpleWirelessNetDevice::AddLinkChangeCallback (Callback callback) +{} +bool +SimpleWirelessNetDevice::IsBroadcast (void) const +{ + return true; +} +Address +SimpleWirelessNetDevice::GetBroadcast (void) const +{ + return Mac48Address ("ff:ff:ff:ff:ff:ff"); +} +bool +SimpleWirelessNetDevice::IsMulticast (void) const +{ + return false; +} +Address +SimpleWirelessNetDevice::GetMulticast (Ipv4Address multicastGroup) const +{ + return Mac48Address::GetMulticast (multicastGroup); +} + +Address SimpleWirelessNetDevice::GetMulticast (Ipv6Address addr) const +{ + return Mac48Address::GetMulticast (addr); +} + +bool +SimpleWirelessNetDevice::IsPointToPoint (void) const +{ + return false; +} + +bool +SimpleWirelessNetDevice::IsBridge (void) const +{ + return false; +} + +//******************************************************************** +// Directional Neighbor functions +bool SimpleWirelessNetDevice::AddDirectionalNeighbors(std::map nodesToAdd) +{ + // is directional neighbor feature enabled? + // If not return false so caller knows there is a problem + if (!m_fixedNbrListEnabled) + return false; + + for ( std::map ::iterator it = nodesToAdd.begin(); it != nodesToAdd.end(); ++it) + { + mDirectionalNbrs.insert(std::pair(it->first, it->second)); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " added directional neighbor " << it->first << " mac Address " << it->second); + } + return true; +} + +bool SimpleWirelessNetDevice::AddDirectionalNeighbor(uint32_t nodeid, Mac48Address macAddr) +{ + // is directional neighbor feature enabled? + // If not return false so caller knows there is a problem + if (!m_fixedNbrListEnabled) + return false; + + mDirectionalNbrs.insert(std::pair(nodeid, macAddr)); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " added directional neighbor " << nodeid << " mac Address " << macAddr); + return true; +} + +void SimpleWirelessNetDevice::DeleteDirectionalNeighbors(std::set nodeids) +{ + for ( std::set::iterator it = nodeids.begin(); it != nodeids.end(); ++it) + { + std::map::iterator it2 = mDirectionalNbrs.find(*it); + if (it2 != mDirectionalNbrs.end()) + { + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " deleted directional neighbor " << it2->first << " mac Address " << it2->second); + mDirectionalNbrs.erase(it2); + } + } +} + +void SimpleWirelessNetDevice::DeleteDirectionalNeighbor(uint32_t nodeid) +{ + std::map::iterator it = mDirectionalNbrs.find(nodeid); + if (it != mDirectionalNbrs.end()) + { + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " deleted directional neighbor " << nodeid << " mac Address " << it->second); + mDirectionalNbrs.erase(it); + } +} + +//******************************************************************** +// Fixed Contention functions +void SimpleWirelessNetDevice::ClearNbrCount(void) +{ + // When we clear the neighbor count, we actually set it to 1 and not 0 + // because we always have to count ourselves. + m_nbrCount = 1; +} + +void SimpleWirelessNetDevice::IncrementNbrCount(void) +{ + m_nbrCount++; +} + +int SimpleWirelessNetDevice::GetNbrCount(void) +{ + return m_nbrCount; +} + + +//******************************************************************** + +void +SimpleWirelessNetDevice::TransmitStart (Ptr p) +{ + NS_LOG_FUNCTION (this << p); + + // This function is called to start the process of transmitting a packet. + // We need to tell the channel that we've started wiggling the wire and + // schedule an event that will be executed when the transmission is complete. + NS_ASSERT_MSG (m_txMachineState == READY, "Must be READY to transmit"); + m_txMachineState = BUSY; + m_currentPkt = p; + + if (m_pcapEnabled) + { + m_promiscSnifferTrace (p); + } + + // Remove the timestamp tag. calculate queue latency and peg trace + TimestampTag timeEnqueued; + p->RemovePacketTag (timeEnqueued); + Time latency = Simulator::Now() - timeEnqueued.GetTimestamp(); + m_QueueLatencyTrace(p, latency); + NS_LOG_DEBUG (Simulator::Now() << " Getting packet with timestamp: " << timeEnqueued.GetTimestamp() ); + + // Remove ethernet header since it is not sent over the air + // To this AFTER the queue latency trace in case the trace wants + // to use anything in the Ethernet header + EthernetHeader ethHeader; + p->RemoveHeader(ethHeader); + Mac48Address to = ethHeader.GetDestination (); + Mac48Address from = ethHeader.GetSource (); + uint16_t protocol = ethHeader.GetLengthType (); + + + // Get dest Id tag. This could be the default NO_DIRECTIONAL_NBR + DestinationIdTag destIdTag; + p->RemovePacketTag (destIdTag); + uint32_t destId = destIdTag.GetDestinationId(); + + Time txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ())); + + // If we have a non-zero neighbor count then that means we are using contention and + // the data rate changes. Note that when using contention, we will always have at least + // a value of 1 for neighbor count because we count ourselves. + // If this device is omni then data rate changes to data rate/# neighbors. + // Thus multiply the tx time by the number of neighbors (which is the same as dividing the + // data rate by # neighbors) + // If this device is directional then the data rate is rate/2. Thus multiply the tx time by 2. + + // IMPORTANT NOTE: If we are using contention, the first packet we send may not "know" + // that there is contention. This is a chicken and egg situation. + // The device keeps the neighbor count (which is init'd to 0) but the channel is + // the one that has contention. When contention is enabled on the channel, there may not be + // any devices to initial with the contention (i.e., set nbr count to 1). The function in the + // channel that sets contention enabled also notifies all the devices on the channel but if + // there are not devices yet when the function is called then the first packet sent on the + // channel by the device is what will cause the device to get init'd for contention. That is + // after the device set the txTime so that first packet will be sent at full data rate. + if (m_nbrCount) + { + if (m_fixedNbrListEnabled) + { + txTime = txTime * 2; + NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << p->GetSize ()); + } + else + { + txTime = txTime * m_nbrCount; + NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << p->GetSize ()); + } + } + // TO DO: do we need interframe gap?? + //Time txCompleteTime = txTime + m_tInterframeGap; + Time txCompleteTime = txTime; + + NS_LOG_DEBUG ("Schedule TransmitCompleteEvent in " << txCompleteTime.GetMicroSeconds () << "usec"); + Simulator::Schedule (txCompleteTime, &SimpleWirelessNetDevice::TransmitComplete, this); + + m_TxBeginTrace (p, from, to, protocol); + + m_channel->Send (p, protocol, to, from, this, txTime, destId); +} + +void +SimpleWirelessNetDevice::TransmitComplete (void) +{ + NS_LOG_FUNCTION_NOARGS (); + + // This function is called to when we're all done transmitting a packet. + // We try and pull another packet off of the transmit queue. If the queue + // is empty, we are done, otherwise we need to start transmitting the + // next packet. + NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting"); + m_txMachineState = READY; + + NS_ASSERT_MSG (m_currentPkt != 0, "SimpleWirelessNetDevice::TransmitComplete(): m_currentPkt zero"); + m_currentPkt = 0; + + NS_LOG_DEBUG (Simulator::Now() << " Tx complete. Packets in queue: " << m_queue->GetNPackets() << " Bytes in queue: " << m_queue->GetNBytes()); + + + Ptr p = m_queue->Dequeue (); + if (p == 0) + { + // No packet was on the queue, so we just exit. + return; + } + + // Got another packet off of the queue, so start the transmit process agin. + TransmitStart (p); +} + + +bool +SimpleWirelessNetDevice::Send(Ptr packet, const Address& dest, uint16_t protocolNumber) +{ + NS_LOG_FUNCTION (packet << dest << protocolNumber); + Mac48Address to = Mac48Address::ConvertFrom (dest); + + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " sending packet " << packet->GetUid () << " to " << to ); + + // For some reason the Ethernet header is STRIPPED from the packet + // by the time we get here so we need to reconstruct it for for two reasons. + // If queuing, add ethernet header to the packet in the queue so we can + // retrieve the to, from and protocol. Also Ethernet header is + // needed so we can apply a pcap filter in priority queues + EthernetHeader ethHeader; + ethHeader.SetSource (m_address); + ethHeader.SetDestination (to); + ethHeader.SetLengthType (protocolNumber); + packet->AddHeader (ethHeader); + + m_macTxTrace (packet); + + // If directional networking is enabled, then we have to make a copy + // of this packet and enqueue it for each destination. + if (m_fixedNbrListEnabled) + { + std::map::iterator it; + + // Look up the dest address in the eth header of the packet. + // This is necessary because in directional networks, the dest + // could have been changed by the trace + packet->PeekHeader(ethHeader); + to = ethHeader.GetDestination(); + + if (to.IsBroadcast()) + { + NS_LOG_INFO ("Address " << to << " is broadcast"); + // broadcast packet. Enqueue for all of our directional neighbors + for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + { + EnqueuePacket(packet->Copy(),m_address,to,protocolNumber,it->first); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet to directional neighbor to node " << it->first); + } + } + else + { + NS_LOG_INFO ("Address " << to << " is NOT broadcast"); + // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) + for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + { + if (it->second == to) + { + EnqueuePacket(packet->Copy(),m_address,to,protocolNumber, it->first); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " found node " << it->first << " with matching Mac Address " << to); + break; + } + } + } + } + else + { + EnqueuePacket(packet,m_address,to,protocolNumber, NO_DIRECTIONAL_NBR); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet"); + } + + return true; + +} + + +bool +SimpleWirelessNetDevice::SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) +{ + NS_LOG_FUNCTION (packet << dest << protocolNumber); + Mac48Address to = Mac48Address::ConvertFrom (dest); + Mac48Address from = Mac48Address::ConvertFrom (source); + + // For some reason the Ethernet header is STRIPPED from the packet + // by the time we get here so we need to reconstruct it for for two reasons. + // If queuing, add ethernet header to the packet in the queue so we can + // retrieve the to, from and protocol. Also Ethernet header is + // needed so we can apply a pcap filter in priority queues + EthernetHeader ethHeader; + ethHeader.SetSource (from); + ethHeader.SetDestination (to); + ethHeader.SetLengthType (protocolNumber); + packet->AddHeader (ethHeader); + + m_macTxTrace (packet); + + + // If directional networking is enabled, then we have to make a copy + // of this packet and enqueue it for each destination. + if (m_fixedNbrListEnabled) + { + std::map::iterator it; + + // Look up the dest address in the eth header of the packet. + // This is necessary because in directional networks, the dest + // could have been changed by the trace + packet->PeekHeader(ethHeader); + to = ethHeader.GetDestination(); + + if (to.IsBroadcast()) + { + NS_LOG_INFO ("Address " << to << " is broadcast"); + // broadcast packet. Enqueue for all of our directional neighbors + for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + { + // Note that we do not alter the to (mac address) here but instead specify + // the node id as the destination. This gets carried with the packet + // as a destination tag and passed to the channel. At the channel it still + // appears as a broadcast packet but the channel only uses the dest id so it + // will know how to handle it from the perspective of directional networking. + EnqueuePacket(packet->Copy(),from,to,protocolNumber,it->first); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet to directional neighbor to node " << it->first); + } + } + else + { + NS_LOG_INFO ("Address " << to << " is NOT broadcast"); + // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) + for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + { + if (it->second == to) + { + EnqueuePacket(packet->Copy(),from,to,protocolNumber, it->first); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " found node " << it->first << " with matching Mac Address " << to); + break; + } + } + } + } + else + { + EnqueuePacket(packet,from,to,protocolNumber, NO_DIRECTIONAL_NBR); + NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet"); + } + + return true; + +} + +bool +SimpleWirelessNetDevice::EnqueuePacket (Ptr packet, Mac48Address from, Mac48Address to, uint16_t protocolNumber, uint32_t destId) +{ + + if (m_queue) + { + // We are using queueing. + + // Add a timestamp tag for latency + TimestampTag timestamp; + timestamp.SetTimestamp (Simulator::Now ()); + packet->AddPacketTag (timestamp); + + // add destination tag + DestinationIdTag idTag(destId); + packet->AddPacketTag (idTag); + + NS_LOG_DEBUG ("Queueing packet for destination " << destId << ". Protocol "<< protocolNumber << " Current state is: " << m_txMachineState); + + // We should enqueue and dequeue the packet to hit the tracing hooks. + if (m_queue->Enqueue (packet)) + { + // If the channel is ready for transition we send the packet right now + if (m_txMachineState == READY) + { + packet = m_queue->Dequeue (); + TransmitStart (packet); + } + return true; + } + + // TO DO: do we return true or false here?? + return true; + } + else + { + // No queuing is being used. Just send the packet. + if (m_pcapEnabled) + { + m_promiscSnifferTrace (packet); + } + EthernetHeader ethHeader; + packet->RemoveHeader(ethHeader); + + m_TxBeginTrace (packet, m_address, to, protocolNumber); + Time txTime = Seconds (m_bps.CalculateTxTime (packet->GetSize ())); + // If we have a non-zero neighbor count then that means we are using contention and + // the data rate changes. + if (m_nbrCount) + { + if (m_fixedNbrListEnabled) + { + txTime = txTime * 2; + NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << packet->GetSize ()); + } + else + { + txTime = txTime * m_nbrCount; + NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << packet->GetSize ()); + } + } + m_channel->Send (packet, protocolNumber, to, from, this, txTime, destId); + return true; + } +} + + + + +Ptr +SimpleWirelessNetDevice::GetNode (void) const +{ + return m_node; +} +void +SimpleWirelessNetDevice::SetNode (Ptr node) +{ + m_node = node; +} +bool +SimpleWirelessNetDevice::NeedsArp (void) const +{ + return true; +} +void +SimpleWirelessNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb) +{ + m_rxCallback = cb; +} + +void +SimpleWirelessNetDevice::DoDispose (void) +{ + m_channel = 0; + m_node = 0; + m_receiveErrorModel = 0; + NetDevice::DoDispose (); +} + + +void +SimpleWirelessNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb) +{ + m_promiscCallback = cb; +} + +bool +SimpleWirelessNetDevice::SupportsSendFrom (void) const +{ + return true; +} + +void +SimpleWirelessNetDevice::SetDataRate (DataRate bps) +{ + NS_LOG_FUNCTION_NOARGS (); + m_bps = bps; +} + +void +SimpleWirelessNetDevice::SetQueue (Ptr q) +{ + NS_LOG_FUNCTION (this << q); + m_queue = q; +} + +Ptr +SimpleWirelessNetDevice::GetQueue (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_queue; +} + + +void SimpleWirelessNetDevice::EnablePcapAll (std::string filename) +{ + PcapHelper pcapHelper; + Ptr file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_EN10MB); + pcapHelper.HookDefaultSink (this, "PromiscSniffer", file); + m_pcapEnabled = true; +} + +} // namespace ns3 diff --git a/model/simple-wireless-net-device.h b/model/simple-wireless-net-device.h index 2a6563a..ea0729d 100644 --- a/model/simple-wireless-net-device.h +++ b/model/simple-wireless-net-device.h @@ -1,362 +1,362 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (C) 2015 Massachusetts Institute of Technology - * Copyright (c) 2010 University of Washington - * - * 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 - * - */ -#ifndef SIMPLE_WIRELESS_NET_DEVICE_H -#define SIMPLE_WIRELESS_NET_DEVICE_H - -#include -#include -#include "ns3/traced-callback.h" -#include "ns3/net-device.h" -#include "ns3/mac48-address.h" -#include "ns3/trace-helper.h" -#include "ns3/data-rate.h" -#include "ns3/queue.h" -#include "ns3/ethernet-header.h" -#include "ns3/double.h" -#include "ns3/boolean.h" - -#include -#include - -namespace ns3 { - -class SimpleWirelessChannel; -class Node; -class ErrorModel; - -#define NO_DIRECTIONAL_NBR 0xFFFFFFFF - - -//******************************************************** -// TimestampTag used to store a timestamp with a packet -// when they are placed in the queue -//******************************************************** -class TimestampTag : public Tag { -public: - static TypeId GetTypeId (void); - virtual TypeId GetInstanceTypeId (void) const; - - virtual uint32_t GetSerializedSize (void) const; - virtual void Serialize (TagBuffer i) const; - virtual void Deserialize (TagBuffer i); - - // these are our accessors to our tag structure - void SetTimestamp (Time time); - Time GetTimestamp (void) const; - - void Print (std::ostream &os) const; - -private: - Time m_timestamp; - - // end class TimestampTag -}; - - -//******************************************************** -// DestinationIdTag used to store a destination node id -// with a packet when they are placed in the queue. -// This is used by directional networks. -//******************************************************** -class DestinationIdTag : public Tag { -public: - static TypeId GetTypeId (void); - virtual TypeId GetInstanceTypeId (void) const; - - virtual uint32_t GetSerializedSize (void) const; - virtual void Serialize (TagBuffer i) const; - virtual void Deserialize (TagBuffer i); - DestinationIdTag(); - - /** - * Constructs a DestinationIdTag with the given node id - * - * \param destId Id to use for the tag - */ - DestinationIdTag (uint32_t destId); - - // these are our accessors to our tag structure - void SetDestinationId (uint32_t destId); - uint32_t GetDestinationId (void) const; - - void Print (std::ostream &os) const; - -private: - uint32_t m_destnodeid; - - // end class DestinationIdTag -}; - - - -/** - * \ingroup netdevice - * - * This device does not have a helper and assumes 48-bit mac addressing; - * the default address assigned to each device is zero, so you must - * assign a real address to use it. There is also the possibility to - * add an ErrorModel if you want to force losses on the device. - * - * \brief simple net device for simple things and testing - */ -class SimpleWirelessNetDevice : public NetDevice -{ -public: - static TypeId GetTypeId (void); - SimpleWirelessNetDevice (); - - void Receive (Ptr packet, uint16_t protocol, Mac48Address to, Mac48Address from); - void SetChannel (Ptr channel); - - /** - * Attach a receive ErrorModel to the SimpleWirelessNetDevice. - * - * The SimpleWirelessNetDevice may optionally include an ErrorModel in - * the packet receive chain. - * - * \see ErrorModel - * \param em Ptr to the ErrorModel. - */ - void SetReceiveErrorModel(Ptr em); - - /** - * Set the Data Rate used for transmission of packets. The data rate is - * set in the Attach () method from the corresponding field in the channel - * to which the device is attached. It can be overridden using this method. - * - * @see Attach () - * @param bps the data rate at which this object operates - */ - void SetDataRate (DataRate bps); - - /** - * Attach a queue to the PointToPointNetDevice. - * - * The PointToPointNetDevice "owns" a queue that implements a queueing - * method such as DropTail or RED. - * - * @see Queue - * @see DropTailQueue - * @param queue Ptr to the new queue. - */ - void SetQueue (Ptr queue); - - /** - * Get a copy of the attached Queue. - * - * @returns Ptr to the queue. - */ - Ptr GetQueue (void) const; - - //****************************************** - // Directional Neighbor functions - bool AddDirectionalNeighbors(std::map nodesToAdd); - bool AddDirectionalNeighbor(uint32_t nodeid, Mac48Address macAddr); - void DeleteDirectionalNeighbors(std::set nodeids); - void DeleteDirectionalNeighbor(uint32_t nodeid); - - //****************************************** - // Fixed Contention functions - void ClearNbrCount(void); - void IncrementNbrCount(void); - int GetNbrCount(void); - - - void EnablePcapAll(std::string filename); - - // inherited from NetDevice base class. - virtual void SetIfIndex(const uint32_t index); - virtual uint32_t GetIfIndex(void) const; - virtual Ptr GetChannel (void) const; - virtual void SetAddress (Address address); - virtual Address GetAddress (void) const; - virtual bool SetMtu (const uint16_t mtu); - virtual uint16_t GetMtu (void) const; - virtual bool IsLinkUp (void) const; - virtual void AddLinkChangeCallback (Callback callback); - virtual bool IsBroadcast (void) const; - virtual Address GetBroadcast (void) const; - virtual bool IsMulticast (void) const; - virtual Address GetMulticast (Ipv4Address multicastGroup) const; - virtual bool IsPointToPoint (void) const; - virtual bool IsBridge (void) const; - virtual bool Send(Ptr packet, const Address& dest, uint16_t protocolNumber); - virtual bool SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); - virtual Ptr GetNode (void) const; - virtual void SetNode (Ptr node); - virtual bool NeedsArp (void) const; - virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb); - virtual bool EnqueuePacket(Ptr packet, Mac48Address from, Mac48Address to, uint16_t protocolNumber, uint32_t destId); - - virtual Address GetMulticast (Ipv6Address addr) const; - - virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb); - virtual bool SupportsSendFrom (void) const; - -protected: - virtual void DoDispose (void); -private: - Ptr m_channel; - NetDevice::ReceiveCallback m_rxCallback; - NetDevice::PromiscReceiveCallback m_promiscCallback; - Ptr m_node; - uint16_t m_mtu; - uint32_t m_ifIndex; - Mac48Address m_address; - Ptr m_receiveErrorModel; - - Ptr m_currentPkt; - - /** - * Start Sending a Packet Down the Wire. - * - * The TransmitStart method is the method that is used internally in the - * NetDevice to begin the process of sending a packet out on - * the channel. The corresponding method is called on the channel to let - * it know that the physical device this class represents has virtually - * started sending signals. An event is scheduled for the time at which - * the bits have been completely transmitted. - */ - void TransmitStart (Ptr); - - /** - * Stop Sending a Packet Down the Wire and Begin the Interframe Gap. - * - * The TransmitComplete method is used internally to finish the process - * of sending a packet out on the channel. - */ - void TransmitComplete (void); - - /** - * Enumeration of the states of the transmit machine of the net device. - */ - enum TxMachineState - { - READY, /**< The transmitter is ready to begin transmission of a packet */ - BUSY /**< The transmitter is busy transmitting a packet */ - }; - /** - * The state of the Net Device transmit state machine. - * @see TxMachineState - */ - TxMachineState m_txMachineState; - - - /** - * The data rate that the Net Device uses to simulate packet transmission - * timing. - * @see class DataRate - */ - DataRate m_bps; - - /** - * The Queue which this device uses as a packet source. - * Management of this Queue has been delegated to the device - * and it has the responsibility for deletion. - * @see class Queue - * @see class DropTailQueue - */ - Ptr m_queue; - - /** - * The trace source fired when a packet begins the reception process from - * the medium. - * - * \see class CallBackTraceSource - */ - TracedCallback, Mac48Address, Mac48Address, uint16_t > m_phyRxBeginTrace; - - /** - * The trace source fired when a packet ends the reception process from - * the medium. - * - * \see class CallBackTraceSource - */ - TracedCallback, Mac48Address, Mac48Address, uint16_t > m_phyRxEndTrace; - - /** - * The trace source fired when the phy layer drops a packet it has received - * due to the error model being active. Although SimpleWirelessNetDevice doesn't - * really have a Phy model, we choose this trace source name for alignment - * with other trace sources. - * - * \see class CallBackTraceSource - */ - TracedCallback, Mac48Address, Mac48Address, uint16_t > m_phyRxDropTrace; - - /** - * A trace source that emulates a promiscuous mode protocol sniffer connected - * to the device. This trace source fire on packets destined for any host - * just like your average everyday packet sniffer. - * - * The trace is captured on send and receive. - * - * \see class CallBackTraceSource - */ - TracedCallback > m_promiscSnifferTrace; - - /** - * The trace source fired when a packet begins the transmission process on - * the medium. - * - * \see class CallBackTraceSource - */ - TracedCallback, Mac48Address, Mac48Address, uint16_t > m_TxBeginTrace; - - /** - * The trace source fired when a packet is dequeued to be sent. - * It does NOT track queue latency for packets that get dropped - * in the queue only that that are actually sent from the queue - * - * \see class CallBackTraceSource - */ - TracedCallback, Time> m_QueueLatencyTrace; - - /** - * The trace source fired when packets come into the "top" of the device - * at the L3/L2 transition, before being queued for transmission. - * - * \see class CallBackTraceSource - */ - TracedCallback > m_macTxTrace; - - /** - * The trace source fired for packets successfully received by the device - * immediately before being forwarded up to higher layers (at the L2/L3 - * transition). This is a non- promiscuous trace. - * - * \see class CallBackTraceSource - */ - TracedCallback > m_macRxTrace; - - - uint32_t m_pktRcvTotal; - uint32_t m_pktRcvDrop; - bool m_pcapEnabled; - - bool m_fixedNbrListEnabled; - std::map mDirectionalNbrs; - - int m_nbrCount; -}; - -} // namespace ns3 - -#endif /* SIMPLE_WIRELESS_NET_DEVICE_H */ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (C) 2015 Massachusetts Institute of Technology + * Copyright (c) 2010 University of Washington + * + * 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 + * + */ +#ifndef SIMPLE_WIRELESS_NET_DEVICE_H +#define SIMPLE_WIRELESS_NET_DEVICE_H + +#include +#include +#include "ns3/traced-callback.h" +#include "ns3/net-device.h" +#include "ns3/mac48-address.h" +#include "ns3/trace-helper.h" +#include "ns3/data-rate.h" +#include "ns3/queue.h" +#include "ns3/ethernet-header.h" +#include "ns3/double.h" +#include "ns3/boolean.h" + +#include +#include + +namespace ns3 { + +class SimpleWirelessChannel; +class Node; +class ErrorModel; + +#define NO_DIRECTIONAL_NBR 0xFFFFFFFF + + +//******************************************************** +// TimestampTag used to store a timestamp with a packet +// when they are placed in the queue +//******************************************************** +class TimestampTag : public Tag { +public: + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + + // these are our accessors to our tag structure + void SetTimestamp (Time time); + Time GetTimestamp (void) const; + + void Print (std::ostream &os) const; + +private: + Time m_timestamp; + + // end class TimestampTag +}; + + +//******************************************************** +// DestinationIdTag used to store a destination node id +// with a packet when they are placed in the queue. +// This is used by directional networks. +//******************************************************** +class DestinationIdTag : public Tag { +public: + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + DestinationIdTag(); + + /** + * Constructs a DestinationIdTag with the given node id + * + * \param destId Id to use for the tag + */ + DestinationIdTag (uint32_t destId); + + // these are our accessors to our tag structure + void SetDestinationId (uint32_t destId); + uint32_t GetDestinationId (void) const; + + void Print (std::ostream &os) const; + +private: + uint32_t m_destnodeid; + + // end class DestinationIdTag +}; + + + +/** + * \ingroup netdevice + * + * This device does not have a helper and assumes 48-bit mac addressing; + * the default address assigned to each device is zero, so you must + * assign a real address to use it. There is also the possibility to + * add an ErrorModel if you want to force losses on the device. + * + * \brief simple net device for simple things and testing + */ +class SimpleWirelessNetDevice : public NetDevice +{ +public: + static TypeId GetTypeId (void); + SimpleWirelessNetDevice (); + + void Receive (Ptr packet, uint16_t protocol, Mac48Address to, Mac48Address from); + void SetChannel (Ptr channel); + + /** + * Attach a receive ErrorModel to the SimpleWirelessNetDevice. + * + * The SimpleWirelessNetDevice may optionally include an ErrorModel in + * the packet receive chain. + * + * \see ErrorModel + * \param em Ptr to the ErrorModel. + */ + void SetReceiveErrorModel(Ptr em); + + /** + * Set the Data Rate used for transmission of packets. The data rate is + * set in the Attach () method from the corresponding field in the channel + * to which the device is attached. It can be overridden using this method. + * + * @see Attach () + * @param bps the data rate at which this object operates + */ + void SetDataRate (DataRate bps); + + /** + * Attach a queue to the PointToPointNetDevice. + * + * The PointToPointNetDevice "owns" a queue that implements a queueing + * method such as DropTail or RED. + * + * @see Queue + * @see DropTailQueue + * @param queue Ptr to the new queue. + */ + void SetQueue (Ptr queue); + + /** + * Get a copy of the attached Queue. + * + * @returns Ptr to the queue. + */ + Ptr GetQueue (void) const; + + //****************************************** + // Directional Neighbor functions + bool AddDirectionalNeighbors(std::map nodesToAdd); + bool AddDirectionalNeighbor(uint32_t nodeid, Mac48Address macAddr); + void DeleteDirectionalNeighbors(std::set nodeids); + void DeleteDirectionalNeighbor(uint32_t nodeid); + + //****************************************** + // Fixed Contention functions + void ClearNbrCount(void); + void IncrementNbrCount(void); + int GetNbrCount(void); + + + void EnablePcapAll(std::string filename); + + // inherited from NetDevice base class. + virtual void SetIfIndex(const uint32_t index); + virtual uint32_t GetIfIndex(void) const; + virtual Ptr GetChannel (void) const; + virtual void SetAddress (Address address); + virtual Address GetAddress (void) const; + virtual bool SetMtu (const uint16_t mtu); + virtual uint16_t GetMtu (void) const; + virtual bool IsLinkUp (void) const; + virtual void AddLinkChangeCallback (Callback callback); + virtual bool IsBroadcast (void) const; + virtual Address GetBroadcast (void) const; + virtual bool IsMulticast (void) const; + virtual Address GetMulticast (Ipv4Address multicastGroup) const; + virtual bool IsPointToPoint (void) const; + virtual bool IsBridge (void) const; + virtual bool Send(Ptr packet, const Address& dest, uint16_t protocolNumber); + virtual bool SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); + virtual Ptr GetNode (void) const; + virtual void SetNode (Ptr node); + virtual bool NeedsArp (void) const; + virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb); + virtual bool EnqueuePacket(Ptr packet, Mac48Address from, Mac48Address to, uint16_t protocolNumber, uint32_t destId); + + virtual Address GetMulticast (Ipv6Address addr) const; + + virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb); + virtual bool SupportsSendFrom (void) const; + +protected: + virtual void DoDispose (void); +private: + Ptr m_channel; + NetDevice::ReceiveCallback m_rxCallback; + NetDevice::PromiscReceiveCallback m_promiscCallback; + Ptr m_node; + uint16_t m_mtu; + uint32_t m_ifIndex; + Mac48Address m_address; + Ptr m_receiveErrorModel; + + Ptr m_currentPkt; + + /** + * Start Sending a Packet Down the Wire. + * + * The TransmitStart method is the method that is used internally in the + * NetDevice to begin the process of sending a packet out on + * the channel. The corresponding method is called on the channel to let + * it know that the physical device this class represents has virtually + * started sending signals. An event is scheduled for the time at which + * the bits have been completely transmitted. + */ + void TransmitStart (Ptr); + + /** + * Stop Sending a Packet Down the Wire and Begin the Interframe Gap. + * + * The TransmitComplete method is used internally to finish the process + * of sending a packet out on the channel. + */ + void TransmitComplete (void); + + /** + * Enumeration of the states of the transmit machine of the net device. + */ + enum TxMachineState + { + READY, /**< The transmitter is ready to begin transmission of a packet */ + BUSY /**< The transmitter is busy transmitting a packet */ + }; + /** + * The state of the Net Device transmit state machine. + * @see TxMachineState + */ + TxMachineState m_txMachineState; + + + /** + * The data rate that the Net Device uses to simulate packet transmission + * timing. + * @see class DataRate + */ + DataRate m_bps; + + /** + * The Queue which this device uses as a packet source. + * Management of this Queue has been delegated to the device + * and it has the responsibility for deletion. + * @see class Queue + * @see class DropTailQueue + */ + Ptr m_queue; + + /** + * The trace source fired when a packet begins the reception process from + * the medium. + * + * \see class CallBackTraceSource + */ + TracedCallback, Mac48Address, Mac48Address, uint16_t > m_phyRxBeginTrace; + + /** + * The trace source fired when a packet ends the reception process from + * the medium. + * + * \see class CallBackTraceSource + */ + TracedCallback, Mac48Address, Mac48Address, uint16_t > m_phyRxEndTrace; + + /** + * The trace source fired when the phy layer drops a packet it has received + * due to the error model being active. Although SimpleWirelessNetDevice doesn't + * really have a Phy model, we choose this trace source name for alignment + * with other trace sources. + * + * \see class CallBackTraceSource + */ + TracedCallback, Mac48Address, Mac48Address, uint16_t > m_phyRxDropTrace; + + /** + * A trace source that emulates a promiscuous mode protocol sniffer connected + * to the device. This trace source fire on packets destined for any host + * just like your average everyday packet sniffer. + * + * The trace is captured on send and receive. + * + * \see class CallBackTraceSource + */ + TracedCallback > m_promiscSnifferTrace; + + /** + * The trace source fired when a packet begins the transmission process on + * the medium. + * + * \see class CallBackTraceSource + */ + TracedCallback, Mac48Address, Mac48Address, uint16_t > m_TxBeginTrace; + + /** + * The trace source fired when a packet is dequeued to be sent. + * It does NOT track queue latency for packets that get dropped + * in the queue only that that are actually sent from the queue + * + * \see class CallBackTraceSource + */ + TracedCallback, Time> m_QueueLatencyTrace; + + /** + * The trace source fired when packets come into the "top" of the device + * at the L3/L2 transition, before being queued for transmission. + * + * \see class CallBackTraceSource + */ + TracedCallback > m_macTxTrace; + + /** + * The trace source fired for packets successfully received by the device + * immediately before being forwarded up to higher layers (at the L2/L3 + * transition). This is a non- promiscuous trace. + * + * \see class CallBackTraceSource + */ + TracedCallback > m_macRxTrace; + + + uint32_t m_pktRcvTotal; + uint32_t m_pktRcvDrop; + bool m_pcapEnabled; + + bool m_fixedNbrListEnabled; + std::map mDirectionalNbrs; + + int m_nbrCount; +}; + +} // namespace ns3 + +#endif /* SIMPLE_WIRELESS_NET_DEVICE_H */ diff --git a/wscript b/wscript index 31126db..09ae499 100644 --- a/wscript +++ b/wscript @@ -1,23 +1,23 @@ -## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- - -def build(bld): - obj = bld.create_ns3_module('simple-wireless', ['network']) - obj.source = [ - 'model/simple-wireless-net-device.cc', - 'model/simple-wireless-channel.cc', - 'model/drop-head-queue.cc', - 'model/priority-queue.cc', - ] - headers = bld(features='ns3header') - headers.module = 'simple-wireless' - headers.source = [ - 'model/simple-wireless-net-device.h', - 'model/simple-wireless-channel.h', - 'model/drop-head-queue.h', - 'model/priority-queue.h', - ] - obj.env.append_value("LIB", ["pcap"]) - - if (bld.env['ENABLE_EXAMPLES']): - bld.recurse('examples') - +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + obj = bld.create_ns3_module('simple-wireless', ['network']) + obj.source = [ + 'model/simple-wireless-net-device.cc', + 'model/simple-wireless-channel.cc', + 'model/drop-head-queue.cc', + 'model/priority-queue.cc', + ] + headers = bld(features='ns3header') + headers.module = 'simple-wireless' + headers.source = [ + 'model/simple-wireless-net-device.h', + 'model/simple-wireless-channel.h', + 'model/drop-head-queue.h', + 'model/priority-queue.h', + ] + obj.env.append_value("LIB", ["pcap"]) + + if (bld.env['ENABLE_EXAMPLES']): + bld.recurse('examples') + From 8083df39061c8a6a1743f56edfffc24d395722e0 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 28 Sep 2018 06:51:51 -0700 Subject: [PATCH 2/8] apply check-style.py across all files --- examples/directional_test.cc | 612 +++++++++++++------------ examples/error_model_test.cc | 552 +++++++++++----------- examples/fixed_contention_test.cc | 554 +++++++++++----------- examples/mixed_directional_network.cc | 456 +++++++++--------- examples/multiple_interface_example.cc | 428 ++++++++--------- examples/queue_test.cc | 570 +++++++++++------------ model/drop-head-queue.cc | 14 +- model/drop-head-queue.h | 5 +- model/priority-queue.cc | 22 +- model/priority-queue.h | 9 +- model/simple-wireless-channel.cc | 470 +++++++++---------- model/simple-wireless-channel.h | 112 ++--- model/simple-wireless-net-device.cc | 582 +++++++++++------------ model/simple-wireless-net-device.h | 146 +++--- 14 files changed, 2283 insertions(+), 2249 deletions(-) diff --git a/examples/directional_test.cc b/examples/directional_test.cc index b47d7a3..cf106b8 100644 --- a/examples/directional_test.cc +++ b/examples/directional_test.cc @@ -10,14 +10,14 @@ * 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 */ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - + #include #include #include @@ -35,7 +35,7 @@ // This file is used to test the directional network option. // For directional networks, the user must specify a list of neighbors that // can be seen. If a neighbor can not be seen, all packets are dropped for -// that neighbr. If a neighbor can be seen, the configured error is then +// that neighbr. If a neighbor can be seen, the configured error is then // applied to the packet transmit. // // The scenario has the following: @@ -94,30 +94,30 @@ std::string PktSize = "1000"; // ****************************************************************** // This function supports OLSR when running on Simple Wireless // ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to, uint16_t protocol) { // Figure out if this is OLSR or data - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_sent_data++; - } + if (p->GetSize () == (APP_PKT_SIZE + 28)) + { + pkts_sent_data++; + } else - { - pkts_sent_cntl++; - } - - + { + pkts_sent_cntl++; + } + + } static void MacRxSuccess (std::string context, Ptr p) { - int id = atoi(context.c_str()); - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_by_node[id]++; - pkts_rcvd_data++; - } + int id = atoi (context.c_str ()); + if (p->GetSize () == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_by_node[id]++; + pkts_rcvd_data++; + } } // ****************************************************************** @@ -125,25 +125,25 @@ static void MacRxSuccess (std::string context, Ptr p) // ****************************************************************** static void QueueLatencyStats (Ptr p, Time latency) { - double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; - + double_t pkt_latency = double_t (latency.GetMicroSeconds ()) / 1000000.0; + queue_pkt_count++; - avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; - - // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. - // Packet passed in this trace still has the Ethernet header - if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) - { - queue_pkt_count_data++; - avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; - //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } + avg_queue_latency = avg_queue_latency * (queue_pkt_count - 1) / queue_pkt_count + pkt_latency / queue_pkt_count; + + // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. + // Packet passed in this trace still has the Ethernet header + if (p->GetSize () == (APP_PKT_SIZE + 28 + 14)) + { + queue_pkt_count_data++; + avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data - 1) / queue_pkt_count_data + pkt_latency / queue_pkt_count_data; + //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } else - { - queue_pkt_count_cntl++; - avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; - //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } + { + queue_pkt_count_cntl++; + avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl - 1) / queue_pkt_count_cntl + pkt_latency / queue_pkt_count_cntl; + //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } } @@ -160,8 +160,8 @@ static void SinkReceivedBytes (Ptr p, const Address & from) static void AppSendBytes (Ptr p) { - app_count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; + app_count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; } @@ -169,273 +169,275 @@ static void AppSendBytes (Ptr p) // MAIN // ****************************************************************** -int +int main (int argc, char *argv[]) { - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 65; - bool collectPcap = false; - double dataRate = 10000000.0; - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.Parse (argc,argv); - - std::cout << "Running scenario for " << simtime << " seconds "<< std::endl; - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer myNodes; - myNodes.Create (NUM_NODES); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - phy->setErrorRate(0.0); - phy->setErrorModelType(CONSTANT); - - // Uncomment these two lines if you would like to also use contention - //phy->EnableFixedContention(); - //phy->SetFixedContentionRange(100.0); - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - std::cout << "node id " << node->GetId() << " has macAddress of " << simpleWireless->GetAddress() << std::endl; - - // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "QUEUE_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - - // ------------------------------------------------------------------------ - // Set up directional network. Do this after adding all the devices because - // we need to get MAC addresses for the neighbors we want to add - // Only node 0 has directional neighbors. - - // Get node 0 device on the container. - // we added them in numerical order so we know that 0 is node0 - Ptr dev0 = devices.Get(0); - Ptr swDev0 = DynamicCast(dev0); - swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - std::map nbrSet; - // Now in this example, we use an iterator to get the devices. - for ( NetDeviceContainer::Iterator dIt = devices.Begin(); dIt != devices.End(); ++dIt) - { - Ptr node = (*dIt)->GetNode(); - uint32_t id = node->GetId(); - - if ( id == 1 || id == 3 || id == 4 || id == 7 || id == 10 || id == 11 ) - { - // Get mac addr of node and add to map - Address addr = (*dIt)->GetAddress(); - Mac48Address macAddr = Mac48Address::ConvertFrom (addr); - nbrSet.insert(std::pair(id, macAddr)); - std::cout << "Adding node " << id << " with mac address " << macAddr<< std::endl; - } - } - // Now add to dev on node 0 - if (!swDev0->AddDirectionalNeighbors(nbrSet)) - { - NS_FATAL_ERROR ("Call to AddDirectionalNeighbors failed. Please enabled directional neighbors."); - return 0; - } - // ------------------------------------------------------------------------ - - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - - // *********************************************************************** - // Define positions. - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); - positionAlloc->Add (Vector (25.0, 43.0, 0.0)); - positionAlloc->Add (Vector (43.0, 25.0, 0.0)); - positionAlloc->Add (Vector (50.0, 0.0, 0.0)); - positionAlloc->Add (Vector (43.0, -25.0, 0.0)); - positionAlloc->Add (Vector (25.0, -43.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); - positionAlloc->Add (Vector (-25.0,-43.0, 0.0)); - positionAlloc->Add (Vector (-43.0,-25.0, 0.0)); - positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); - positionAlloc->Add (Vector (-43.0, 25.0, 0.0)); - positionAlloc->Add (Vector (-25.0, 43.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (myNodes); - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (myNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. - - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; - - // start the OnOff app on source to destinations (using unicast) - //OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); - //std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; - - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - - ApplicationContainer apps = onoff.Install (myNodes.Get (0)); - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - } - else - { - // on all other nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); - ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; - } - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // For OLSR we need to get some stats - // *********************************************************************** - double rcvPercentData = 0.0; - uint32_t dataDropped = app_count_sent*NUM_DIR_NBR_NODES - app_count_recv; - if (app_count_sent) - rcvPercentData = ((double)app_count_recv/((double)app_count_sent*NUM_DIR_NBR_NODES))*100.0; - - std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv - << "\nControl Packets Sent: " << pkts_sent_cntl - << "\nData Packets Sent: " << pkts_sent_data - << "\nData Packets Received: " << pkts_rcvd_data - << "\nData Packets Dropped: " << dataDropped - << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0)< dev = devices.Get(0); - PointerValue val; - dev->GetAttribute("TxQueue", val); - Ptr queue = val.Get(); - Ptr dropHead = DynamicCast(queue); - std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets() << std::endl; - - for (int i = 1; i < NUM_NODES; i++) - { - std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; - } - - - - NS_LOG_INFO ("Run Completed Successfully"); - - return 0; + NodeContainer::Iterator it; + NodeContainer::Iterator it2; + std::list destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 65; + bool collectPcap = false; + double dataRate = 10000000.0; + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.Parse (argc,argv); + + std::cout << "Running scenario for " << simtime << " seconds " << std::endl; + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer myNodes; + myNodes.Create (NUM_NODES); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue (em)); + + // create channel + Ptr phy = CreateObject (); + phy->setErrorRate (0.0); + phy->setErrorModelType (CONSTANT); + + // Uncomment these two lines if you would like to also use contention + //phy->EnableFixedContention(); + //phy->SetFixedContentionRange(100.0); + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel (phy); + simpleWireless->SetNode (node); + simpleWireless->SetAddress (Mac48Address::Allocate ()); + simpleWireless->SetDataRate ((DataRate (dataRate))); + std::cout << "node id " << node->GetId () << " has macAddress of " << simpleWireless->GetAddress () << std::endl; + + // Set queue type to use + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue (queue); + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId (); + simpleWireless->TraceConnect ("MacRx", oss.str (), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "QUEUE_node_" << node->GetId () << ".pcap"; + fileStr = stringStream.str (); + simpleWireless->EnablePcapAll (fileStr); + } + } + + + // ------------------------------------------------------------------------ + // Set up directional network. Do this after adding all the devices because + // we need to get MAC addresses for the neighbors we want to add + // Only node 0 has directional neighbors. + + // Get node 0 device on the container. + // we added them in numerical order so we know that 0 is node0 + Ptr dev0 = devices.Get (0); + Ptr swDev0 = DynamicCast (dev0); + swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + std::map nbrSet; + // Now in this example, we use an iterator to get the devices. + for ( NetDeviceContainer::Iterator dIt = devices.Begin (); dIt != devices.End (); ++dIt) + { + Ptr node = (*dIt)->GetNode (); + uint32_t id = node->GetId (); + + if ( id == 1 || id == 3 || id == 4 || id == 7 || id == 10 || id == 11 ) + { + // Get mac addr of node and add to map + Address addr = (*dIt)->GetAddress (); + Mac48Address macAddr = Mac48Address::ConvertFrom (addr); + nbrSet.insert (std::pair (id, macAddr)); + std::cout << "Adding node " << id << " with mac address " << macAddr << std::endl; + } + } + // Now add to dev on node 0 + if (!swDev0->AddDirectionalNeighbors (nbrSet)) + { + NS_FATAL_ERROR ("Call to AddDirectionalNeighbors failed. Please enabled directional neighbors."); + return 0; + } + // ------------------------------------------------------------------------ + + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + + // *********************************************************************** + // Define positions. + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (25.0, 43.0, 0.0)); + positionAlloc->Add (Vector (43.0, 25.0, 0.0)); + positionAlloc->Add (Vector (50.0, 0.0, 0.0)); + positionAlloc->Add (Vector (43.0, -25.0, 0.0)); + positionAlloc->Add (Vector (25.0, -43.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); + positionAlloc->Add (Vector (-25.0,-43.0, 0.0)); + positionAlloc->Add (Vector (-43.0,-25.0, 0.0)); + positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); + positionAlloc->Add (Vector (-43.0, 25.0, 0.0)); + positionAlloc->Add (Vector (-25.0, 43.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (myNodes); + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (myNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId (); + + if (id == 0) + { + // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. + + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; + + // start the OnOff app on source to destinations (using unicast) + //OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); + //std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; + + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + + ApplicationContainer apps = onoff.Install (myNodes.Get (0)); + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + } + else + { + // on all other nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); + ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; + } + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds (simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // For OLSR we need to get some stats + // *********************************************************************** + double rcvPercentData = 0.0; + uint32_t dataDropped = app_count_sent * NUM_DIR_NBR_NODES - app_count_recv; + if (app_count_sent) + { + rcvPercentData = ((double)app_count_recv / ((double)app_count_sent * NUM_DIR_NBR_NODES)) * 100.0; + } + + std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv + << "\nControl Packets Sent: " << pkts_sent_cntl + << "\nData Packets Sent: " << pkts_sent_data + << "\nData Packets Received: " << pkts_rcvd_data + << "\nData Packets Dropped: " << dataDropped + << "\n% Data Received: " << std::fixed << std::setprecision (1) << rcvPercentData << std::noshowpoint << std::setprecision (0) << std::endl; + std::cout << "Average Queue Latency Data: " << std::fixed << std::setprecision (6) << avg_queue_latency_data + << "\nAverage Queue Latency Control: " << std::fixed << std::setprecision (6) << avg_queue_latency_cntl << std::noshowpoint << std::setprecision (0) << std::endl; + std::cout << "Overall Average Queue Latency: " << std::fixed << std::setprecision (6) << avg_queue_latency << std::noshowpoint << std::setprecision (0) << std::endl; + + // get queue packets dropped + Ptr dev = devices.Get (0); + PointerValue val; + dev->GetAttribute ("TxQueue", val); + Ptr queue = val.Get(); + Ptr dropHead = DynamicCast (queue); + std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets () << std::endl; + + for (int i = 1; i < NUM_NODES; i++) + { + std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; + } + + + + NS_LOG_INFO ("Run Completed Successfully"); + + return 0; } diff --git a/examples/error_model_test.cc b/examples/error_model_test.cc index c742e19..c37c380 100644 --- a/examples/error_model_test.cc +++ b/examples/error_model_test.cc @@ -10,14 +10,14 @@ * 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 */ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - + #include #include #include @@ -38,11 +38,11 @@ // The scenario has the following: // - 101 nodes // - node 0 is at the center of a circle -// - nodes 1-100 are randomly placed on a circle of radius 100 +// - nodes 1-100 are randomly placed on a circle of radius 100 // - NO mobility // - simple wireless model has: // + User specified error type -// + tx range of 100 +// + tx range of 100 // + NO queue // - OLSR used for routing // - On/Off application used for node 0 to send 1Mb/s to all 100 neighbor nodes @@ -68,34 +68,34 @@ uint32_t pkts_rcvd_by_node[NUM_NODES]; // ****************************************************************** // This function supports OLSR when running on Simple Wireless // ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to, uint16_t protocol) { // Figure out if this is OLSR or data - if (to.IsBroadcast () && p->GetSize() != (APP_PKT_SIZE + 28)) - { - pkts_sent_cntl++; - bytes_sent_cntl += p->GetSize(); - //std::cout << Simulator::Now ().GetSeconds () << " Node sending CONTROL packet of " << p->GetSize() << " bytes to address " << to << std::endl; - } + if (to.IsBroadcast () && p->GetSize () != (APP_PKT_SIZE + 28)) + { + pkts_sent_cntl++; + bytes_sent_cntl += p->GetSize (); + //std::cout << Simulator::Now ().GetSeconds () << " Node sending CONTROL packet of " << p->GetSize() << " bytes to address " << to << std::endl; + } else - { - pkts_sent_data++; - bytes_sent_data += p->GetSize(); - //std::cout << Simulator::Now ().GetSeconds () << " Node sending DATA packet of " << p->GetSize() << " bytes to address " << to << std::endl; - } + { + pkts_sent_data++; + bytes_sent_data += p->GetSize (); + //std::cout << Simulator::Now ().GetSeconds () << " Node sending DATA packet of " << p->GetSize() << " bytes to address " << to << std::endl; + } } static void MacRxSuccess (std::string context, Ptr p) { - int id = atoi(context.c_str()); - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_by_node[id]++; - // Uncomment this line for STOCHASTIC so that you can graph packets received vs time - std::cout << Simulator::Now ().GetSeconds () << " Node " << id << " receiving packet of " << p->GetSize() << " bytes."<< std::endl; - } - - + int id = atoi (context.c_str ()); + if (p->GetSize () == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_by_node[id]++; + // Uncomment this line for STOCHASTIC so that you can graph packets received vs time + std::cout << Simulator::Now ().GetSeconds () << " Node " << id << " receiving packet of " << p->GetSize () << " bytes." << std::endl; + } + + } @@ -110,8 +110,8 @@ static void SinkReceivedBytes (Ptr p, const Address & from) static void AppSendBytes (Ptr p) { - count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; + count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; } @@ -119,255 +119,255 @@ static void AppSendBytes (Ptr p) // MAIN // ****************************************************************** -int +int main (int argc, char *argv[]) { - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 65; - double dataRate = 1000000.0; - - bool collectPcap = false; - std::string errorModel = "CONSTANT"; - double errorRate = 0.0; - double errorUpAvg = 15000000.0; // 15 seconds up - double errorDownAvg = 5000000.0; // 5 second down - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.AddValue ("errorModel", "Error model to use. Must be one of: CONSTANT, CURVE, STOCHASTIC", errorModel); - cmd.AddValue ("errorRate", "Error rate if CONSTANT error model is used", errorRate); - cmd.AddValue ("errorUpAvg", "Average link up duration (microseconds) if STOCHASTIC error model is used", errorUpAvg); - cmd.AddValue ("errorDownAvg", "Average link down duration (microseconds) if STOCHASTIC error model is used", errorDownAvg); - cmd.Parse (argc,argv); - - if ((errorModel != "CONSTANT") && (errorModel != "CURVE") && (errorModel != "STOCHASTIC") ) - { - NS_ABORT_MSG ("Invalid errorModel type: Use --errorModel=CONSTANT or --errorModel=CURVE or --errorModel=STOCHASTIC"); - } - - std::cout << "Running scenario for " << simtime << " seconds using error type of "<< errorModel << std::endl; - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer myNodes; - myNodes.Create (NUM_NODES); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - if ( errorModel.compare ("CURVE") == 0 ) - { - phy->setErrorModelType(PER_CURVE); - phy->addToPERmodel(0.0, 0.0); - phy->addToPERmodel(10.0, 0.0); - phy->addToPERmodel(20.0, 0.05); - phy->addToPERmodel(30.0, 0.07); - phy->addToPERmodel(40.0, 0.12); - phy->addToPERmodel(50.0, 0.15); - phy->addToPERmodel(60.0, 0.5); - phy->addToPERmodel(70.0, 0.6); - phy->addToPERmodel(80.0, 0.70); - phy->addToPERmodel(90.0, 0.80); - phy->addToPERmodel(100.0, 1.0); - } - else if ( errorModel.compare ("CONSTANT") == 0 ) - { - phy->setErrorModelType (CONSTANT); - phy->setErrorRate (errorRate); - } - else if ( errorModel.compare ("STOCHASTIC") == 0 ) - { - phy->setErrorModelType(STOCHASTIC); - phy->SetAttribute("AvgLinkUpDuration", TimeValue (MicroSeconds (errorUpAvg))); - phy->SetAttribute("AvgLinkDownDuration", TimeValue (MicroSeconds (errorDownAvg))); - } - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "ErrorModelTest_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - // Must be done AFTER adding all the devices. Does nothing if not running STOCHASTIC error model - phy->InitStochasticModel(); - - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - - // *********************************************************************** - // Define positions. - ObjectFactory pos; - pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); - pos.Set ("X", DoubleValue (0.0)); - pos.Set ("Y", DoubleValue (0.0)); - pos.Set ("rho", DoubleValue (100)); - Ptr positionAlloc = pos.Create ()->GetObject (); - - // *********************************************************************** - // Define and install random mobility. Here we are using the circle set up above - // as the position allocator for mobility (i.e., the area they can move in) - // *********************************************************************** - MobilityHelper mobility; - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (myNodes); - - // print starting positions - for (it = n.Begin (); it != n.End (); ++it) - { - // get node ptr, position and node id - Ptr node = *it; - Ptr mob = node->GetObject (); - int id = node->GetId(); - - // set up source node - if (id == 0) - { - // placed at the center and is the source node! - mob->SetPosition (Vector (0.0,0.0,0.0)); - } - Vector pos = mob->GetPosition (); - double distance = sqrt(pos.x*pos.x + pos.y*pos.y); - std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: "<< distance << std::endl; - } - - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (myNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (myNodes.Get (0)); - std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - } - else - { - // on all other nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); - ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); - apps_sink.Start (Seconds (0.0)); - //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; - pkts_rcvd_by_node[id] = 0; - } - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // For OLSR we need to get some stats - // *********************************************************************** - std::cout << "App Sent Count: " << count_sent << "\nApp Receive Count: " << count_recv << std::endl; - std::cout << "Control Sent Count: " << pkts_sent_cntl << "\nData Sent Count: " << pkts_sent_data << std::endl; - for (int i = 1; i < NUM_NODES; i++) - { - std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; - } - - - NS_LOG_INFO ("Run Completed Successfully"); - - return 0; + NodeContainer::Iterator it; + NodeContainer::Iterator it2; + std::list destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 65; + double dataRate = 1000000.0; + + bool collectPcap = false; + std::string errorModel = "CONSTANT"; + double errorRate = 0.0; + double errorUpAvg = 15000000.0; // 15 seconds up + double errorDownAvg = 5000000.0; // 5 second down + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.AddValue ("errorModel", "Error model to use. Must be one of: CONSTANT, CURVE, STOCHASTIC", errorModel); + cmd.AddValue ("errorRate", "Error rate if CONSTANT error model is used", errorRate); + cmd.AddValue ("errorUpAvg", "Average link up duration (microseconds) if STOCHASTIC error model is used", errorUpAvg); + cmd.AddValue ("errorDownAvg", "Average link down duration (microseconds) if STOCHASTIC error model is used", errorDownAvg); + cmd.Parse (argc,argv); + + if ((errorModel != "CONSTANT") && (errorModel != "CURVE") && (errorModel != "STOCHASTIC") ) + { + NS_ABORT_MSG ("Invalid errorModel type: Use --errorModel=CONSTANT or --errorModel=CURVE or --errorModel=STOCHASTIC"); + } + + std::cout << "Running scenario for " << simtime << " seconds using error type of " << errorModel << std::endl; + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer myNodes; + myNodes.Create (NUM_NODES); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue (em)); + + // create channel + Ptr phy = CreateObject (); + if ( errorModel.compare ("CURVE") == 0 ) + { + phy->setErrorModelType (PER_CURVE); + phy->addToPERmodel (0.0, 0.0); + phy->addToPERmodel (10.0, 0.0); + phy->addToPERmodel (20.0, 0.05); + phy->addToPERmodel (30.0, 0.07); + phy->addToPERmodel (40.0, 0.12); + phy->addToPERmodel (50.0, 0.15); + phy->addToPERmodel (60.0, 0.5); + phy->addToPERmodel (70.0, 0.6); + phy->addToPERmodel (80.0, 0.70); + phy->addToPERmodel (90.0, 0.80); + phy->addToPERmodel (100.0, 1.0); + } + else if ( errorModel.compare ("CONSTANT") == 0 ) + { + phy->setErrorModelType (CONSTANT); + phy->setErrorRate (errorRate); + } + else if ( errorModel.compare ("STOCHASTIC") == 0 ) + { + phy->setErrorModelType (STOCHASTIC); + phy->SetAttribute ("AvgLinkUpDuration", TimeValue (MicroSeconds (errorUpAvg))); + phy->SetAttribute ("AvgLinkDownDuration", TimeValue (MicroSeconds (errorDownAvg))); + } + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel (phy); + simpleWireless->SetNode (node); + simpleWireless->SetAddress (Mac48Address::Allocate ()); + simpleWireless->SetDataRate ((DataRate (dataRate))); + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId (); + simpleWireless->TraceConnect ("MacRx", oss.str (), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "ErrorModelTest_node_" << node->GetId () << ".pcap"; + fileStr = stringStream.str (); + simpleWireless->EnablePcapAll (fileStr); + } + } + + // Must be done AFTER adding all the devices. Does nothing if not running STOCHASTIC error model + phy->InitStochasticModel (); + + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + + // *********************************************************************** + // Define positions. + ObjectFactory pos; + pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); + pos.Set ("X", DoubleValue (0.0)); + pos.Set ("Y", DoubleValue (0.0)); + pos.Set ("rho", DoubleValue (100)); + Ptr positionAlloc = pos.Create ()->GetObject (); + + // *********************************************************************** + // Define and install random mobility. Here we are using the circle set up above + // as the position allocator for mobility (i.e., the area they can move in) + // *********************************************************************** + MobilityHelper mobility; + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (myNodes); + + // print starting positions + for (it = n.Begin (); it != n.End (); ++it) + { + // get node ptr, position and node id + Ptr node = *it; + Ptr mob = node->GetObject (); + int id = node->GetId (); + + // set up source node + if (id == 0) + { + // placed at the center and is the source node! + mob->SetPosition (Vector (0.0,0.0,0.0)); + } + Vector pos = mob->GetPosition (); + double distance = sqrt (pos.x * pos.x + pos.y * pos.y); + std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: " << distance << std::endl; + } + + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (myNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId (); + + if (id == 0) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (myNodes.Get (0)); + std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + } + else + { + // on all other nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); + ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); + apps_sink.Start (Seconds (0.0)); + //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; + pkts_rcvd_by_node[id] = 0; + } + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds (simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // For OLSR we need to get some stats + // *********************************************************************** + std::cout << "App Sent Count: " << count_sent << "\nApp Receive Count: " << count_recv << std::endl; + std::cout << "Control Sent Count: " << pkts_sent_cntl << "\nData Sent Count: " << pkts_sent_data << std::endl; + for (int i = 1; i < NUM_NODES; i++) + { + std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; + } + + + NS_LOG_INFO ("Run Completed Successfully"); + + return 0; } diff --git a/examples/fixed_contention_test.cc b/examples/fixed_contention_test.cc index 38275ad..e292e95 100644 --- a/examples/fixed_contention_test.cc +++ b/examples/fixed_contention_test.cc @@ -10,14 +10,14 @@ * 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 */ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - + #include #include #include @@ -41,11 +41,11 @@ // The scenario has the following: // - 20 nodes // - node 0 is at the center of a circle -// - nodes 1-19 are randomly placed on a circle of radius 100 +// - nodes 1-19 are randomly placed on a circle of radius 100 // - random mobility within the circle // - simple wireless model has: // + constant error rate of 0 -// + tx range of 50 +// + tx range of 50 // + No queue // + fixed contention enabled // + fixed contention range is defaulted to 50 but is user configurable @@ -83,28 +83,28 @@ uint32_t nodePlacementRadius = 100; // ****************************************************************** // This function supports OLSR when running on Simple Wireless // ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to, uint16_t protocol) { // Figure out if this is OLSR or data - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_sent_data++; - } + if (p->GetSize () == (APP_PKT_SIZE + 28)) + { + pkts_sent_data++; + } else - { - pkts_sent_cntl++; - } + { + pkts_sent_cntl++; + } } static void MacRxSuccess (std::string context, Ptr p) { - int id = atoi(context.c_str()); - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_by_node[id]++; - pkts_rcvd_data++; - } + int id = atoi (context.c_str ()); + if (p->GetSize () == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_by_node[id]++; + pkts_rcvd_data++; + } } // ****************************************************************** @@ -112,25 +112,25 @@ static void MacRxSuccess (std::string context, Ptr p) // ****************************************************************** static void QueueLatencyStats (Ptr p, Time latency) { - double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; - + double_t pkt_latency = double_t (latency.GetMicroSeconds ()) / 1000000.0; + queue_pkt_count++; - avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; - - // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. - // Packet passed in this trace still has the Ethernet header - if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) - { - queue_pkt_count_data++; - avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; - //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } + avg_queue_latency = avg_queue_latency * (queue_pkt_count - 1) / queue_pkt_count + pkt_latency / queue_pkt_count; + + // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. + // Packet passed in this trace still has the Ethernet header + if (p->GetSize () == (APP_PKT_SIZE + 28 + 14)) + { + queue_pkt_count_data++; + avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data - 1) / queue_pkt_count_data + pkt_latency / queue_pkt_count_data; + //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } else - { - queue_pkt_count_cntl++; - avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; - //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } + { + queue_pkt_count_cntl++; + avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl - 1) / queue_pkt_count_cntl + pkt_latency / queue_pkt_count_cntl; + //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } } @@ -147,8 +147,8 @@ static void SinkReceivedBytes (Ptr p, const Address & from) static void AppSendBytes (Ptr p) { - app_count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; + app_count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; } @@ -156,245 +156,247 @@ static void AppSendBytes (Ptr p) // MAIN // ****************************************************************** -int +int main (int argc, char *argv[]) { - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 65; - bool collectPcap = false; - double dataRate = 10000000.0; - double contentionRange = 50.0; - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.AddValue ("contentionRange", "Distance to use for simple wireless contention range", contentionRange); - cmd.Parse (argc,argv); - - std::cout << "Running scenario for " << simtime << " seconds with contention range "<< contentionRange << std::endl; - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer myNodes; - myNodes.Create (NUM_NODES); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - phy->setErrorRate(0.0); - phy->setErrorModelType(CONSTANT); - phy->EnableFixedContention(); - phy->SetFixedContentionRange(contentionRange); - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "CONTENTION_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // Define positions. - ObjectFactory pos; - pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); - pos.Set ("X", DoubleValue (0.0)); - pos.Set ("Y", DoubleValue (0.0)); - pos.Set ("rho", DoubleValue (nodePlacementRadius)); - Ptr positionAlloc = pos.Create ()->GetObject (); - - // *********************************************************************** - // Define and install random mobility. Here we are using the circle set up above - // as the position allocator for mobility (i.e., the area they can move in) - // *********************************************************************** - MobilityHelper mobility; - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (myNodes); - - // print starting positions - for (it = n.Begin (); it != n.End (); ++it) - { - // get node ptr, position and node id - Ptr node = *it; - Ptr mob = node->GetObject (); - int id = node->GetId(); - - // set up source node - if (id == 0) - { - // placed at the center and is the source node! - mob->SetPosition (Vector (0.0,0.0,0.0)); - } - Vector pos = mob->GetPosition (); - double distance = sqrt(pos.x*pos.x + pos.y*pos.y); - std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: "<< distance << std::endl; - } - - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (myNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (myNodes.Get (0)); - std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - } - else - { - // on all other nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); - ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); - apps_sink.Start (Seconds (0.0)); - //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; - pkts_rcvd_by_node[id] = 0; - } - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // stats - // *********************************************************************** - double rcvPercentData = 0.0; - uint32_t dataDropped = app_count_sent*(NUM_NODES -1) - app_count_recv; - if (app_count_sent) - rcvPercentData = ((double)app_count_recv/((double)app_count_sent*(NUM_NODES -1)))*100.0; - - std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv - << "\nControl Packets Sent: " << pkts_sent_cntl - << "\nData Packets Sent: " << pkts_sent_data - << "\nData Packets Received: " << pkts_rcvd_data - << "\nData Packets Dropped: " << dataDropped - << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0)< dev = devices.Get(0); - PointerValue val; - dev->GetAttribute("TxQueue", val); - Ptr queue = val.Get(); - Ptr dropHead = DynamicCast(queue); - std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets() << std::endl; - - for (int i = 1; i < NUM_NODES; i++) - { - //std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; - } - - - NS_LOG_INFO ("Run Completed Successfully"); - - return 0; + NodeContainer::Iterator it; + NodeContainer::Iterator it2; + std::list destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 65; + bool collectPcap = false; + double dataRate = 10000000.0; + double contentionRange = 50.0; + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.AddValue ("contentionRange", "Distance to use for simple wireless contention range", contentionRange); + cmd.Parse (argc,argv); + + std::cout << "Running scenario for " << simtime << " seconds with contention range " << contentionRange << std::endl; + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer myNodes; + myNodes.Create (NUM_NODES); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue (em)); + + // create channel + Ptr phy = CreateObject (); + phy->setErrorRate (0.0); + phy->setErrorModelType (CONSTANT); + phy->EnableFixedContention (); + phy->SetFixedContentionRange (contentionRange); + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel (phy); + simpleWireless->SetNode (node); + simpleWireless->SetAddress (Mac48Address::Allocate ()); + simpleWireless->SetDataRate ((DataRate (dataRate))); + + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue (queue); + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId (); + simpleWireless->TraceConnect ("MacRx", oss.str (), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "CONTENTION_node_" << node->GetId () << ".pcap"; + fileStr = stringStream.str (); + simpleWireless->EnablePcapAll (fileStr); + } + } + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // Define positions. + ObjectFactory pos; + pos.SetTypeId ("ns3::UniformDiscPositionAllocator"); + pos.Set ("X", DoubleValue (0.0)); + pos.Set ("Y", DoubleValue (0.0)); + pos.Set ("rho", DoubleValue (nodePlacementRadius)); + Ptr positionAlloc = pos.Create ()->GetObject (); + + // *********************************************************************** + // Define and install random mobility. Here we are using the circle set up above + // as the position allocator for mobility (i.e., the area they can move in) + // *********************************************************************** + MobilityHelper mobility; + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (myNodes); + + // print starting positions + for (it = n.Begin (); it != n.End (); ++it) + { + // get node ptr, position and node id + Ptr node = *it; + Ptr mob = node->GetObject (); + int id = node->GetId (); + + // set up source node + if (id == 0) + { + // placed at the center and is the source node! + mob->SetPosition (Vector (0.0,0.0,0.0)); + } + Vector pos = mob->GetPosition (); + double distance = sqrt (pos.x * pos.x + pos.y * pos.y); + std::cout << "Node " << id << ". Position (" << pos.x << ", " << pos.y << ", " << pos.z << ") Distance to Node 0: " << distance << std::endl; + } + + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (myNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId (); + + if (id == 0) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (myNodes.Get (0)); + std::cout << "Node 0 installed app to send to 255.255.255.255" << std::endl; + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + } + else + { + // on all other nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (id), 8080)); + ApplicationContainer apps_sink = sink.Install (myNodes.Get (id)); + apps_sink.Start (Seconds (0.0)); + //std::cout << "Node " << id << " installed sink to receive on " << interfaces.GetAddress (id) << std::endl; + pkts_rcvd_by_node[id] = 0; + } + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds (simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // stats + // *********************************************************************** + double rcvPercentData = 0.0; + uint32_t dataDropped = app_count_sent * (NUM_NODES - 1) - app_count_recv; + if (app_count_sent) + { + rcvPercentData = ((double)app_count_recv / ((double)app_count_sent * (NUM_NODES - 1))) * 100.0; + } + + std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv + << "\nControl Packets Sent: " << pkts_sent_cntl + << "\nData Packets Sent: " << pkts_sent_data + << "\nData Packets Received: " << pkts_rcvd_data + << "\nData Packets Dropped: " << dataDropped + << "\n% Data Received: " << std::fixed << std::setprecision (1) << rcvPercentData << std::noshowpoint << std::setprecision (0) << std::endl; + std::cout << "Average Queue Latency Data: " << std::fixed << std::setprecision (6) << avg_queue_latency_data + << "\nAverage Queue Latency Control: " << std::fixed << std::setprecision (6) << avg_queue_latency_cntl << std::noshowpoint << std::setprecision (0) << std::endl; + std::cout << "Overall Average Queue Latency: " << std::fixed << std::setprecision (6) << avg_queue_latency << std::noshowpoint << std::setprecision (0) << std::endl; + + // get queue packets dropped + Ptr dev = devices.Get (0); + PointerValue val; + dev->GetAttribute ("TxQueue", val); + Ptr queue = val.Get(); + Ptr dropHead = DynamicCast (queue); + std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets () << std::endl; + + for (int i = 1; i < NUM_NODES; i++) + { + //std::cout << "Packets received by Node " << i << ": " << pkts_rcvd_by_node[i] << std::endl; + } + + + NS_LOG_INFO ("Run Completed Successfully"); + + return 0; } diff --git a/examples/mixed_directional_network.cc b/examples/mixed_directional_network.cc index 8de4f79..f76af88 100644 --- a/examples/mixed_directional_network.cc +++ b/examples/mixed_directional_network.cc @@ -10,7 +10,7 @@ * 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 @@ -24,16 +24,16 @@ // // 1 // || -// || +// || // 7--- || ---5 // |---4======0======2-| // 8--- || ---6 // || -// || +// || // 3 // Node 0 is placed at the origin (0,0) -// Nodes 1, 2, 3, 4 are 50m away from Node 0 +// Nodes 1, 2, 3, 4 are 50m away from Node 0 // Nodes 5, 6 are placed 10m away from Node 2 // Nodes 7, 8 are placed 10m away from Node 4 @@ -82,16 +82,16 @@ static void SinkReceivedBytes (Ptr p, const Address & from) static void AppSendBytes (Ptr p) { - count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; + count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; } -int +int main (int argc, char *argv[]) { - NodeContainer::Iterator it; - double simtime = 60; - double dataRate = 10000000.0; + NodeContainer::Iterator it; + double simtime = 60; + double dataRate = 10000000.0; NodeContainer n; n.Create (9); @@ -100,222 +100,222 @@ main (int argc, char *argv[]) InternetStackHelper internet; internet.Install (n); - - - // Create container to hold devices - NetDeviceContainer dAll; - NetDeviceContainer d2; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Create error model and set as default - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // *********************************************************************** - // create first network - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (40.0)); - Ptr phy1 = CreateObject (); - phy1->setErrorRate(0.0); - phy1->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless1 = CreateObject (); - simpleWireless1->SetChannel(phy1); - simpleWireless1->SetNode(node); - simpleWireless1->SetAddress(Mac48Address::Allocate ()); - simpleWireless1->SetDataRate((DataRate (dataRate))); - - // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless1->SetQueue(queue); - - node->AddDevice (simpleWireless1); - dAll.Add (simpleWireless1); - } - - // *********************************************************************** - // create second network - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - Ptr phy2 = CreateObject (); - phy2->setErrorRate(0.0); - phy2->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - // network 2 is only on node 0, 1, 2, 3, 4 - if (id < 5) - { - // create device - Ptr simpleWireless2 = CreateObject (); - simpleWireless2->SetChannel(phy2); - simpleWireless2->SetNode(node); - simpleWireless2->SetAddress(Mac48Address::Allocate ()); - simpleWireless2->SetDataRate((DataRate (dataRate))); - - std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress() << std::endl; - - // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless2->SetQueue(queue); - - node->AddDevice (simpleWireless2); - d2.Add (simpleWireless2); - } - } - - // ------------------------------------------------------------------------ - // Set up directional network. Do this after adding all the devices because - // we need to get MAC addresses for the neighbors we want to add - // network 2 is only on node 0, 1, 2, 3, 4 - // node 0 has directional neighbors to nodes 1, 4 - // node 2 has directional networking but no neighbors - - // Get node 0, 1, 2, 4 device on the container. MUST use d2 container - // since that is the container with the SW interfaces that use directional - // network. - // In this example we get the ptr to the NetDevice using the index in the - // containter. We added them in numerical order so we know that 0 is node0, - // 1 is node 1, etc. - Ptr dev0 = d2.Get(0); - Ptr dev1 = d2.Get(1); - Ptr dev2 = d2.Get(2); - Ptr dev4 = d2.Get(4); - Ptr swDev0 = DynamicCast(dev0); - Ptr swDev1 = DynamicCast(dev1); - Ptr swDev2 = DynamicCast(dev2); - Ptr swDev4 = DynamicCast(dev4); - - // node 0 has directional neighbors to nodes 1, 4 - swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - // Here we use the function that takes map to add multiple neighbors one call - std::map nbrSet; - // Get mac addr of node 1 and add to map - Address addr = swDev1->GetAddress(); - Mac48Address macAddr = Mac48Address::ConvertFrom (addr); - nbrSet.insert(std::pair(1, macAddr)); - std::cout << "Adding node 1 with mac address " << macAddr<< std::endl; - // Get mac addr of node 4 and add to map - addr = swDev4->GetAddress(); - macAddr = Mac48Address::ConvertFrom (addr); - nbrSet.insert(std::pair(4, macAddr)); - std::cout << "Adding node 4 with mac address " << macAddr<< std::endl; - // Now add to dev on node 0 - swDev0->AddDirectionalNeighbors(nbrSet); - - // Now just set the fixed neigbor feature enabled on dev 2 but don't - // add any neighbors because it has none - swDev2->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - // ------------------------------------------------------------------------ - - - // Later, we add IP addresses. - Ipv4AddressHelper ipv4; - ipv4.SetBase ("10.1.1.0", "255.255.255.0"); - Ipv4InterfaceContainer interfaces = ipv4.Assign (dAll); - - ipv4.SetBase ("10.1.2.0", "255.255.255.0"); - ipv4.Assign (d2); - - // Create router nodes, initialize routing database and set up the routing - // tables in the nodes. - Ipv4GlobalRoutingHelper::PopulateRoutingTables (); - - // *********************************************************************** - // Define positions. - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); - positionAlloc->Add (Vector (50.0, 0.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); - positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); - positionAlloc->Add (Vector (60.0, -2.0, 0.0)); - positionAlloc->Add (Vector (60.0, 2.0, 0.0)); - positionAlloc->Add (Vector (-60.0, 2.0, 0.0)); - positionAlloc->Add (Vector (-60.0, -2.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (n); - - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on all nodes except node 0 - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - if (id == 0) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("1000")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (n.Get (0)); - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 1.0)); - } - else if (id == 2) - { - // start the OnOff app on source to destinations (using broadcast) - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("1000")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (n.Get (2)); - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 1.0)); - } - - // on nodes start a packet sink - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); - ApplicationContainer apps_sink = sink.Install (n.Get (id)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node " << id << " installed sink " << std::endl; - - } - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - std::cout << "Sent: " << count_sent << "\nReceive Count: " << count_recv << std::endl; - - - NS_LOG_INFO ("Run Completed Successfully"); + + + // Create container to hold devices + NetDeviceContainer dAll; + NetDeviceContainer d2; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Create error model and set as default + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue (em)); + + // *********************************************************************** + // create first network + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (40.0)); + Ptr phy1 = CreateObject (); + phy1->setErrorRate (0.0); + phy1->setErrorModelType (CONSTANT); + + // create simple wireless device on each node + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless1 = CreateObject (); + simpleWireless1->SetChannel (phy1); + simpleWireless1->SetNode (node); + simpleWireless1->SetAddress (Mac48Address::Allocate ()); + simpleWireless1->SetDataRate ((DataRate (dataRate))); + + // Set queue type to use + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless1->SetQueue (queue); + + node->AddDevice (simpleWireless1); + dAll.Add (simpleWireless1); + } + + // *********************************************************************** + // create second network + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + Ptr phy2 = CreateObject (); + phy2->setErrorRate (0.0); + phy2->setErrorModelType (CONSTANT); + + // create simple wireless device on each node + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId (); + + // network 2 is only on node 0, 1, 2, 3, 4 + if (id < 5) + { + // create device + Ptr simpleWireless2 = CreateObject (); + simpleWireless2->SetChannel (phy2); + simpleWireless2->SetNode (node); + simpleWireless2->SetAddress (Mac48Address::Allocate ()); + simpleWireless2->SetDataRate ((DataRate (dataRate))); + + std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress () << std::endl; + + // Set queue type to use + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless2->SetQueue (queue); + + node->AddDevice (simpleWireless2); + d2.Add (simpleWireless2); + } + } + + // ------------------------------------------------------------------------ + // Set up directional network. Do this after adding all the devices because + // we need to get MAC addresses for the neighbors we want to add + // network 2 is only on node 0, 1, 2, 3, 4 + // node 0 has directional neighbors to nodes 1, 4 + // node 2 has directional networking but no neighbors + + // Get node 0, 1, 2, 4 device on the container. MUST use d2 container + // since that is the container with the SW interfaces that use directional + // network. + // In this example we get the ptr to the NetDevice using the index in the + // containter. We added them in numerical order so we know that 0 is node0, + // 1 is node 1, etc. + Ptr dev0 = d2.Get (0); + Ptr dev1 = d2.Get (1); + Ptr dev2 = d2.Get (2); + Ptr dev4 = d2.Get (4); + Ptr swDev0 = DynamicCast (dev0); + Ptr swDev1 = DynamicCast (dev1); + Ptr swDev2 = DynamicCast (dev2); + Ptr swDev4 = DynamicCast (dev4); + + // node 0 has directional neighbors to nodes 1, 4 + swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + // Here we use the function that takes map to add multiple neighbors one call + std::map nbrSet; + // Get mac addr of node 1 and add to map + Address addr = swDev1->GetAddress (); + Mac48Address macAddr = Mac48Address::ConvertFrom (addr); + nbrSet.insert (std::pair (1, macAddr)); + std::cout << "Adding node 1 with mac address " << macAddr << std::endl; + // Get mac addr of node 4 and add to map + addr = swDev4->GetAddress (); + macAddr = Mac48Address::ConvertFrom (addr); + nbrSet.insert (std::pair (4, macAddr)); + std::cout << "Adding node 4 with mac address " << macAddr << std::endl; + // Now add to dev on node 0 + swDev0->AddDirectionalNeighbors (nbrSet); + + // Now just set the fixed neigbor feature enabled on dev 2 but don't + // add any neighbors because it has none + swDev2->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + // ------------------------------------------------------------------------ + + + // Later, we add IP addresses. + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces = ipv4.Assign (dAll); + + ipv4.SetBase ("10.1.2.0", "255.255.255.0"); + ipv4.Assign (d2); + + // Create router nodes, initialize routing database and set up the routing + // tables in the nodes. + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + // *********************************************************************** + // Define positions. + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); + positionAlloc->Add (Vector (50.0, 0.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, -50.0, 0.0)); + positionAlloc->Add (Vector (-50.0, 0.0, 0.0)); + positionAlloc->Add (Vector (60.0, -2.0, 0.0)); + positionAlloc->Add (Vector (60.0, 2.0, 0.0)); + positionAlloc->Add (Vector (-60.0, 2.0, 0.0)); + positionAlloc->Add (Vector (-60.0, -2.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (n); + + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on all nodes except node 0 + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId (); + + if (id == 0) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("1000")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (n.Get (0)); + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 1.0)); + } + else if (id == 2) + { + // start the OnOff app on source to destinations (using broadcast) + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("255.255.255.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("1000")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (n.Get (2)); + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 1.0)); + } + + // on nodes start a packet sink + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); + ApplicationContainer apps_sink = sink.Install (n.Get (id)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node " << id << " installed sink " << std::endl; + + } + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds (simtime)); + Simulator::Run (); + Simulator::Destroy (); + + std::cout << "Sent: " << count_sent << "\nReceive Count: " << count_recv << std::endl; + + + NS_LOG_INFO ("Run Completed Successfully"); } diff --git a/examples/multiple_interface_example.cc b/examples/multiple_interface_example.cc index 96147d2..0169d31 100644 --- a/examples/multiple_interface_example.cc +++ b/examples/multiple_interface_example.cc @@ -10,7 +10,7 @@ * 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 @@ -62,229 +62,237 @@ uint32_t count_recv_app2 = 0; // ****************************************************************** static void SinkReceivedBytes (Ptr p, const Address & from) { - if (p->GetSize() > 500) - count_recv_app1++; - else - count_recv_app2++; + if (p->GetSize () > 500) + { + count_recv_app1++; + } + else + { + count_recv_app2++; + } - std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize() << " bytes."<< std::endl; + std::cout << Simulator::Now ().GetSeconds () << " Node receiving packet of " << p->GetSize () << " bytes." << std::endl; } static void AppSendBytes (Ptr p) { - if (p->GetSize() > 500) - count_sent_app1++; - else - count_sent_app2++; + if (p->GetSize () > 500) + { + count_sent_app1++; + } + else + { + count_sent_app2++; + } - std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. "<< std::endl; + std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize () << " bytes. " << std::endl; } static void removeDirectionalNbr (Ptr sw) { - // remove directional neigbhor 1 - sw->DeleteDirectionalNeighbor(1); + // remove directional neigbhor 1 + sw->DeleteDirectionalNeighbor (1); } -int +int main (int argc, char *argv[]) { - NodeContainer::Iterator it; - double simtime = 126; - double dataRate = 10000000.0; //10Mb/s - - // create node container for the omni network - NodeContainer n1; - n1.Create (2); - // create node container for the directional network - NodeContainer n2_dir = NodeContainer (n1.Get (0), n1.Get (1)); - - - InternetStackHelper internet; - internet.Install (n1); - - - // Create container to hold devices - NetDeviceContainer d1_omni; - NetDeviceContainer d2_dir; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Create error model and set as default - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // *********************************************************************** - // create first network - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // channel - Ptr phy1 = CreateObject (); - phy1->setErrorRate(0.0); - phy1->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n1.Begin (); it != n1.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless1 = CreateObject (); - simpleWireless1->SetChannel(phy1); - simpleWireless1->SetNode(node); - simpleWireless1->SetAddress(Mac48Address::Allocate ()); - simpleWireless1->SetDataRate((DataRate (dataRate))); - - // create queue type - Ptr queue = CreateObject (); - simpleWireless1->SetQueue(queue); - - node->AddDevice (simpleWireless1); - d1_omni.Add (simpleWireless1); - } - - // *********************************************************************** - // create second network - Ptr phy2 = CreateObject (); - phy2->setErrorRate(0.0); - phy2->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - for (it = n2_dir.Begin (); it != n2_dir.End (); ++it) - { - Ptr node = *it; - uint32_t id = node->GetId(); - - // create device - Ptr simpleWireless2 = CreateObject (); - simpleWireless2->SetChannel(phy2); - simpleWireless2->SetNode(node); - simpleWireless2->SetAddress(Mac48Address::Allocate ()); - simpleWireless2->SetDataRate((DataRate (dataRate))); - std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress() << std::endl; - - // create queue type - Ptr queue = CreateObject (); - simpleWireless2->SetQueue(queue); - - if (id == 0) - { - // schedule function which removed node 0's directional neighbor - Simulator::Schedule (Seconds (60.0), &removeDirectionalNbr, simpleWireless2); - } - - node->AddDevice (simpleWireless2); - d2_dir.Add (simpleWireless2); - } - - - // *********************************************************************** - // Set up directional network. Do this after adding all the devices because - // we need to get MAC addresses for the neighbors we want to add - - // Get node 0, 1 device on the container. MUST use d2_dir container - // since that is the container with the SW interfaces that use directional - // network. - // In this example we get the ptr to the NetDevice using the index in the - // containter. We added them in numerical order so we know that 0 is node0, - // 1 is node 1, etc. - Ptr dev0 = d2_dir.Get(0); - Ptr dev1 = d2_dir.Get(1); - Ptr swDev0 = DynamicCast(dev0); - Ptr swDev1 = DynamicCast(dev1); - - // node 0 has directional neighbors to node 1 - swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - // Here we use the function that takes a single node to add - Address addr = swDev1->GetAddress(); - Mac48Address macAddr = Mac48Address::ConvertFrom (addr); - swDev0->AddDirectionalNeighbor(1,macAddr); - - // node 1 has directional neighbors to node 0 - swDev1->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); - addr = swDev0->GetAddress(); - macAddr = Mac48Address::ConvertFrom (addr); - swDev1->AddDirectionalNeighbor(0,macAddr); - - - // *********************************************************************** - // add IP addresses. - Ipv4AddressHelper ipv4; - ipv4.SetBase ("10.1.1.0", "255.255.255.0"); - Ipv4InterfaceContainer interfaces = ipv4.Assign (d1_omni); - - ipv4.SetBase ("10.1.2.0", "255.255.255.0"); - ipv4.Assign (d2_dir); - - // Create router nodes, initialize routing database and set up the routing - // tables in the nodes. - Ipv4GlobalRoutingHelper::PopulateRoutingTables (); - - // *********************************************************************** - // Define positions. - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); - positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (n1); - - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on node 1 - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); - ApplicationContainer apps_sink = sink.Install (n1.Get (1)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node 1 installed sink " << std::endl; - - // start the OnOff app on source to destinations in the omni network - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.255"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("1000")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - ApplicationContainer apps1 = onoff.Install (n1.Get (0)); - apps1.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - apps1.Start (Seconds (5.0)); - apps1.Stop (Seconds (simtime - 1.0)); - - // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. - // start the OnOff app on source to destinations in the directional network - onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.255"), 8080)); - //onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.2"), 8080)); - onoff.SetAttribute ("PacketSize", StringValue ("500")); - onoff.SetAttribute ("DataRate", StringValue ("100000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - ApplicationContainer apps2 = onoff.Install (n2_dir.Get (0)); - apps2.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - apps2.Start (Seconds (5.0)); - apps2.Stop (Seconds (simtime - 1.0)); - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - std::cout << "App1 Sent: " << count_sent_app1 << " Received: " << count_recv_app1 << std::endl; - std::cout << "App2 Sent: " << count_sent_app2 << " Received: " << count_recv_app2 << std::endl; - - - NS_LOG_INFO ("Run Completed Successfully"); + NodeContainer::Iterator it; + double simtime = 126; + double dataRate = 10000000.0; //10Mb/s + + // create node container for the omni network + NodeContainer n1; + n1.Create (2); + // create node container for the directional network + NodeContainer n2_dir = NodeContainer (n1.Get (0), n1.Get (1)); + + + InternetStackHelper internet; + internet.Install (n1); + + + // Create container to hold devices + NetDeviceContainer d1_omni; + NetDeviceContainer d2_dir; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Create error model and set as default + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue (em)); + + // *********************************************************************** + // create first network + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // channel + Ptr phy1 = CreateObject (); + phy1->setErrorRate (0.0); + phy1->setErrorModelType (CONSTANT); + + // create simple wireless device on each node + for (it = n1.Begin (); it != n1.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless1 = CreateObject (); + simpleWireless1->SetChannel (phy1); + simpleWireless1->SetNode (node); + simpleWireless1->SetAddress (Mac48Address::Allocate ()); + simpleWireless1->SetDataRate ((DataRate (dataRate))); + + // create queue type + Ptr queue = CreateObject (); + simpleWireless1->SetQueue (queue); + + node->AddDevice (simpleWireless1); + d1_omni.Add (simpleWireless1); + } + + // *********************************************************************** + // create second network + Ptr phy2 = CreateObject (); + phy2->setErrorRate (0.0); + phy2->setErrorModelType (CONSTANT); + + // create simple wireless device on each node + for (it = n2_dir.Begin (); it != n2_dir.End (); ++it) + { + Ptr node = *it; + uint32_t id = node->GetId (); + + // create device + Ptr simpleWireless2 = CreateObject (); + simpleWireless2->SetChannel (phy2); + simpleWireless2->SetNode (node); + simpleWireless2->SetAddress (Mac48Address::Allocate ()); + simpleWireless2->SetDataRate ((DataRate (dataRate))); + std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress () << std::endl; + + // create queue type + Ptr queue = CreateObject (); + simpleWireless2->SetQueue (queue); + + if (id == 0) + { + // schedule function which removed node 0's directional neighbor + Simulator::Schedule (Seconds (60.0), &removeDirectionalNbr, simpleWireless2); + } + + node->AddDevice (simpleWireless2); + d2_dir.Add (simpleWireless2); + } + + + // *********************************************************************** + // Set up directional network. Do this after adding all the devices because + // we need to get MAC addresses for the neighbors we want to add + + // Get node 0, 1 device on the container. MUST use d2_dir container + // since that is the container with the SW interfaces that use directional + // network. + // In this example we get the ptr to the NetDevice using the index in the + // containter. We added them in numerical order so we know that 0 is node0, + // 1 is node 1, etc. + Ptr dev0 = d2_dir.Get (0); + Ptr dev1 = d2_dir.Get (1); + Ptr swDev0 = DynamicCast (dev0); + Ptr swDev1 = DynamicCast (dev1); + + // node 0 has directional neighbors to node 1 + swDev0->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + // Here we use the function that takes a single node to add + Address addr = swDev1->GetAddress (); + Mac48Address macAddr = Mac48Address::ConvertFrom (addr); + swDev0->AddDirectionalNeighbor (1,macAddr); + + // node 1 has directional neighbors to node 0 + swDev1->SetAttributeFailSafe ("FixedNeighborListEnabled", BooleanValue (true)); + addr = swDev0->GetAddress (); + macAddr = Mac48Address::ConvertFrom (addr); + swDev1->AddDirectionalNeighbor (0,macAddr); + + + // *********************************************************************** + // add IP addresses. + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces = ipv4.Assign (d1_omni); + + ipv4.SetBase ("10.1.2.0", "255.255.255.0"); + ipv4.Assign (d2_dir); + + // Create router nodes, initialize routing database and set up the routing + // tables in the nodes. + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + // *********************************************************************** + // Define positions. + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector ( 0.0, 0.0, 0.0)); + positionAlloc->Add (Vector ( 0.0, 50.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (n1); + + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on node 1 + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 8080)); + ApplicationContainer apps_sink = sink.Install (n1.Get (1)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node 1 installed sink " << std::endl; + + // start the OnOff app on source to destinations in the omni network + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.255"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("1000")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + ApplicationContainer apps1 = onoff.Install (n1.Get (0)); + apps1.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + apps1.Start (Seconds (5.0)); + apps1.Stop (Seconds (simtime - 1.0)); + + // **** Choose if you want bcast or unicast traffic by uncommented appropriate line below. + // start the OnOff app on source to destinations in the directional network + onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.255"), 8080)); + //onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.2.2"), 8080)); + onoff.SetAttribute ("PacketSize", StringValue ("500")); + onoff.SetAttribute ("DataRate", StringValue ("100000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + ApplicationContainer apps2 = onoff.Install (n2_dir.Get (0)); + apps2.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + apps2.Start (Seconds (5.0)); + apps2.Stop (Seconds (simtime - 1.0)); + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds (simtime)); + Simulator::Run (); + Simulator::Destroy (); + + std::cout << "App1 Sent: " << count_sent_app1 << " Received: " << count_recv_app1 << std::endl; + std::cout << "App2 Sent: " << count_sent_app2 << " Received: " << count_recv_app2 << std::endl; + + + NS_LOG_INFO ("Run Completed Successfully"); } diff --git a/examples/queue_test.cc b/examples/queue_test.cc index 57a96fc..65b0c97 100644 --- a/examples/queue_test.cc +++ b/examples/queue_test.cc @@ -10,14 +10,14 @@ * 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 */ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ - + #include #include #include @@ -43,7 +43,7 @@ // Drop Queue Tail - when queues are full, drop at the tail of the queue. That is, the // newly received packet is dropped // Drop Queue Head - when queues are full, drop at the head of the queue. That is, the -// oldest packet is dropped and newly received packet is inserted +// oldest packet is dropped and newly received packet is inserted // into the queue // Priority Queue - defines two queues: control and data. Each queue is configured // independently to be either drop head or drop tail. Differentiation @@ -86,34 +86,34 @@ std::string PktSize = "1000"; // ****************************************************************** // This function supports OLSR when running on Simple Wireless // ****************************************************************** -static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to , uint16_t protocol) +static void TransmitStatsSW (Ptr p, Mac48Address from, Mac48Address to, uint16_t protocol) { // Figure out if this is OLSR or data - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_sent_data++; - bytes_sent_data += p->GetSize(); - } + if (p->GetSize () == (APP_PKT_SIZE + 28)) + { + pkts_sent_data++; + bytes_sent_data += p->GetSize (); + } else - { - pkts_sent_cntl++; - bytes_sent_cntl += p->GetSize(); - } + { + pkts_sent_cntl++; + bytes_sent_cntl += p->GetSize (); + } } static void MacRxSuccess (std::string context, Ptr p) { - if (p->GetSize() == (APP_PKT_SIZE + 28)) - { - pkts_rcvd_data++; - } + if (p->GetSize () == (APP_PKT_SIZE + 28)) + { + pkts_rcvd_data++; + } else - { - pkts_rcvd_cntl++; - } - - + { + pkts_rcvd_cntl++; + } + + } // ****************************************************************** @@ -121,25 +121,25 @@ static void MacRxSuccess (std::string context, Ptr p) // ****************************************************************** static void QueueLatencyStats (Ptr p, Time latency) { - double_t pkt_latency = double_t(latency.GetMicroSeconds())/1000000.0; - + double_t pkt_latency = double_t (latency.GetMicroSeconds ()) / 1000000.0; + queue_pkt_count++; - avg_queue_latency = avg_queue_latency * (queue_pkt_count-1)/queue_pkt_count + pkt_latency/queue_pkt_count; - - // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. - // Packet passed in this trace still has the Ethernet header - if (p->GetSize() == (APP_PKT_SIZE + 28 + 14)) - { - queue_pkt_count_data++; - avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data-1)/queue_pkt_count_data + pkt_latency/queue_pkt_count_data; - //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } + avg_queue_latency = avg_queue_latency * (queue_pkt_count - 1) / queue_pkt_count + pkt_latency / queue_pkt_count; + + // add 28 bytes to ap size for UDP/IP header and also add 14 for ethernet header. + // Packet passed in this trace still has the Ethernet header + if (p->GetSize () == (APP_PKT_SIZE + 28 + 14)) + { + queue_pkt_count_data++; + avg_queue_latency_data = avg_queue_latency_data * (queue_pkt_count_data - 1) / queue_pkt_count_data + pkt_latency / queue_pkt_count_data; + //std::cout << Simulator::Now ().GetSeconds () << " DATA Packet latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } else - { - queue_pkt_count_cntl++; - avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl-1)/queue_pkt_count_cntl + pkt_latency/queue_pkt_count_cntl; - //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; - } + { + queue_pkt_count_cntl++; + avg_queue_latency_cntl = avg_queue_latency_cntl * (queue_pkt_count_cntl - 1) / queue_pkt_count_cntl + pkt_latency / queue_pkt_count_cntl; + //std::cout << Simulator::Now ().GetSeconds () << " CONTROL Packet ("<< p->GetSize() << ") latency: " << std::setprecision(9) << pkt_latency << " seconds"<< std::endl; + } } @@ -156,8 +156,8 @@ static void SinkReceivedBytes (Ptr p, const Address & from) static void AppSendBytes (Ptr p) { - app_count_sent++; - //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; + app_count_sent++; + //std::cout << Simulator::Now ().GetSeconds () << " Node sending packet of " << p->GetSize() << " bytes. count_sent is "<< count_sent << std::endl; } @@ -165,248 +165,252 @@ static void AppSendBytes (Ptr p) // MAIN // ****************************************************************** -int +int main (int argc, char *argv[]) { - NodeContainer::Iterator it; - NodeContainer::Iterator it2; - std::list destAddresses; // used by OLSR - - Ipv4Address sourceNodeAddr; - - - // *********************************************************************** - // Initialize all value that are to be used in the scenario - // *********************************************************************** - double simtime = 120; - bool collectPcap = false; - double dataRate = 10000000.0; - std::string queueType = "DropTail"; - - // *********************************************************************** - // parse command line - // *********************************************************************** - CommandLine cmd; - cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); - cmd.AddValue ("datarate", "Data Rate of wireless link in bits per second", dataRate); - cmd.AddValue ("queueType", "Set Queue type to NoQueue, DropHead, DropTail or PriorityHead or PriorityTail", queueType); - cmd.Parse (argc,argv); - - std::cout << "Running scenario for " << simtime << " seconds with queue type: "<< queueType <<" and data rate: " << std::fixed << std::setprecision(1) << dataRate <<"bps"<< std::endl; - - if ((queueType != "NoQueue") && (queueType != "DropHead") && (queueType != "DropTail") && (queueType != "PriorityHead") && (queueType != "PriorityTail")) - { - NS_ABORT_MSG ("Invalid queue type: Use --queueType=DropHead or --queueType=DropTail or --queueType=PriorityHead or --queueType=PriorityTail"); - } - - // *********************************************************************** - // Create all the nodes - // *********************************************************************** - NodeContainer NpNodes; - NpNodes.Create (2); - NodeContainer const & n = NodeContainer::GetGlobal (); - - // Create container to hold devices - NetDeviceContainer devices; - - // *********************************************************************** - // Set up the physical/radio layer - // *********************************************************************** - // Set transmission range - Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); - - // Create error model and set as default for the device Receive side - // ALWAYS set the error rate to 0 here. The error is handled on the send side - // by the channel model in the simple wireless - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.0)); - em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); - Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue(em)); - - // create channel - Ptr phy = CreateObject (); - phy->setErrorRate(0.0); - phy->setErrorModelType(CONSTANT); - - // create simple wireless device on each node - std::string fileStr; - for (it = n.Begin (); it != n.End (); ++it) - { - Ptr node = *it; - - // create device - Ptr simpleWireless = CreateObject (); - simpleWireless->SetChannel(phy); - simpleWireless->SetNode(node); - simpleWireless->SetAddress(Mac48Address::Allocate ()); - simpleWireless->SetDataRate((DataRate (dataRate))); - - // Set queue type to use. Set nothing if NoQueue - if (queueType == "DropHead") - { - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - } - else if (queueType == "DropTail") - { - Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); - simpleWireless->SetQueue(queue); - } - else if (queueType == "PriorityHead") - { - Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr controlQueue = CreateObject (); - Ptr dataQueue = CreateObject (); - Ptr queue = CreateObject (); - queue->Initialize(); - queue->SetControlQueue(controlQueue); - queue->SetDataQueue(dataQueue); - simpleWireless->SetQueue(queue); - } - else if (queueType == "PriorityTail") - { - Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); - Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); - Ptr controlQueue = CreateObject (); - Ptr dataQueue = CreateObject (); - Ptr queue = CreateObject (); - queue->Initialize(); - queue->SetControlQueue(controlQueue); - queue->SetDataQueue(dataQueue); - simpleWireless->SetQueue(queue); - } - - // Set up trace to pass node id on the RX end - std::ostringstream oss; - oss << node->GetId(); - simpleWireless->TraceConnect ("MacRx", oss.str(), MakeCallback (&MacRxSuccess)); - - node->AddDevice (simpleWireless); - devices.Add (simpleWireless); - - // set up pcap capture - if (collectPcap) - { - std::ostringstream stringStream; - stringStream << "QUEUE_node_" << node->GetId() << ".pcap"; - fileStr = stringStream.str(); - simpleWireless->EnablePcapAll(fileStr); - } - } - - // set up call back for traces - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); - Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); - - // *********************************************************************** - // Define positions. Nodes are 50 apart - MobilityHelper mobility; - Ptr positionAlloc = CreateObject (); - positionAlloc->Add (Vector (0.0, 0.0, 0.0)); - positionAlloc->Add (Vector (50.0, 0.0, 0.0)); - mobility.SetPositionAllocator (positionAlloc); - mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); - mobility.Install (NpNodes); - - - // *********************************************************************** - // Set up routing OLSR - // *********************************************************************** - // don't have to use the Ipv4ListRoutingHelper but it prints - // the routing table in a better format than directly installing olsr. - InternetStackHelper stack; - OlsrHelper olsr; - Ipv4ListRoutingHelper list; - - // Add the routing to the route helper - list.Add (olsr, 10); - - // print the olsr routing table to a file every 10 seconds - //Ptr routingStream = Create ("400node_OLSR.routes", std::ios::out); - //olsr.PrintRoutingTableAllEvery (Seconds (10), routingStream); - - // now set the routing and install on all nodes - stack.SetRoutingHelper (list); - stack.Install (NpNodes); - - // set up IP addresses - Ipv4AddressHelper address; - address.SetBase ("10.0.0.0", "255.255.0.0"); - Ipv4InterfaceContainer interfaces = address.Assign (devices); - - // *********************************************************************** - // Set up application - // *********************************************************************** - // start the packet sink on destination node - PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); - ApplicationContainer apps_sink = sink.Install (NpNodes.Get (1)); - apps_sink.Start (Seconds (0.0)); - std::cout << "Node 1 installed sink to receive on " << interfaces.GetAddress (1) << std::endl; - - // set up the sink receive callback on all packet sinks - Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); - - // Now start the OnOff app on source to destinations - OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); - onoff.SetAttribute ("PacketSize", StringValue (PktSize)); - onoff.SetAttribute ("DataRate", StringValue ("1000000")); - onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); - onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); - - ApplicationContainer apps = onoff.Install (NpNodes.Get (0)); - std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; - apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); - - apps.Start (Seconds (5.0)); - apps.Stop (Seconds (simtime - 5.0)); - - - // *********************************************************************** - // and finally ... off we go! - // *********************************************************************** - - Simulator::Stop (Seconds(simtime)); - Simulator::Run (); - Simulator::Destroy (); - - // *********************************************************************** - // For OLSR we need to get some stats - // *********************************************************************** - double rcvPercentData = 0.0; - uint32_t dataDropped = app_count_sent - app_count_recv; - if (app_count_sent) - rcvPercentData = ((double)app_count_recv/(double)app_count_sent)*100.0; - - double rcvPercentCntrl = 0.0; - uint32_t cntlDropped = pkts_sent_cntl - pkts_rcvd_cntl; - if (pkts_sent_cntl) - rcvPercentCntrl = ((double)pkts_rcvd_cntl/(double)pkts_sent_cntl)*100.0; - - std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv - << "\nControl Packets Sent: " << pkts_sent_cntl << "\nControl Bytes Sent: " << bytes_sent_cntl - << "\nData Packets Sent: " << pkts_sent_data << "\nData Bytes Sent: " << bytes_sent_data - << "\nControl Packets Received: " << pkts_rcvd_cntl << "\nData Packets Received: " << pkts_rcvd_data - << "\nData Packets Dropped: " << dataDropped << "\nControl Packets Dropped: " << cntlDropped - << "\n% Data Received: " << std::fixed << std::setprecision(1) << rcvPercentData << std::noshowpoint << std::setprecision(0) - << "\n% Control Received: " << std::fixed << std::setprecision(1) << rcvPercentCntrl << std::noshowpoint << std::setprecision(0) < destAddresses; // used by OLSR + + Ipv4Address sourceNodeAddr; + + + // *********************************************************************** + // Initialize all value that are to be used in the scenario + // *********************************************************************** + double simtime = 120; + bool collectPcap = false; + double dataRate = 10000000.0; + std::string queueType = "DropTail"; + + // *********************************************************************** + // parse command line + // *********************************************************************** + CommandLine cmd; + cmd.AddValue ("pcap", "Set to 1 to collect pcap traces", collectPcap); + cmd.AddValue ("datarate", "Data Rate of wireless link in bits per second", dataRate); + cmd.AddValue ("queueType", "Set Queue type to NoQueue, DropHead, DropTail or PriorityHead or PriorityTail", queueType); + cmd.Parse (argc,argv); + + std::cout << "Running scenario for " << simtime << " seconds with queue type: " << queueType << " and data rate: " << std::fixed << std::setprecision (1) << dataRate << "bps" << std::endl; + + if ((queueType != "NoQueue") && (queueType != "DropHead") && (queueType != "DropTail") && (queueType != "PriorityHead") && (queueType != "PriorityTail")) + { + NS_ABORT_MSG ("Invalid queue type: Use --queueType=DropHead or --queueType=DropTail or --queueType=PriorityHead or --queueType=PriorityTail"); + } + + // *********************************************************************** + // Create all the nodes + // *********************************************************************** + NodeContainer NpNodes; + NpNodes.Create (2); + NodeContainer const & n = NodeContainer::GetGlobal (); + + // Create container to hold devices + NetDeviceContainer devices; + + // *********************************************************************** + // Set up the physical/radio layer + // *********************************************************************** + // Set transmission range + Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); + + // Create error model and set as default for the device Receive side + // ALWAYS set the error rate to 0 here. The error is handled on the send side + // by the channel model in the simple wireless + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (0.0)); + em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET")); + Config::SetDefault ("ns3::SimpleWirelessNetDevice::ReceiveErrorModel", PointerValue (em)); + + // create channel + Ptr phy = CreateObject (); + phy->setErrorRate (0.0); + phy->setErrorModelType (CONSTANT); + + // create simple wireless device on each node + std::string fileStr; + for (it = n.Begin (); it != n.End (); ++it) + { + Ptr node = *it; + + // create device + Ptr simpleWireless = CreateObject (); + simpleWireless->SetChannel (phy); + simpleWireless->SetNode (node); + simpleWireless->SetAddress (Mac48Address::Allocate ()); + simpleWireless->SetDataRate ((DataRate (dataRate))); + + // Set queue type to use. Set nothing if NoQueue + if (queueType == "DropHead") + { + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue (queue); + } + else if (queueType == "DropTail") + { + Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); + Ptr queue = CreateObject (); + simpleWireless->SetQueue (queue); + } + else if (queueType == "PriorityHead") + { + Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); + Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); + Ptr controlQueue = CreateObject (); + Ptr dataQueue = CreateObject (); + Ptr queue = CreateObject (); + queue->Initialize (); + queue->SetControlQueue (controlQueue); + queue->SetDataQueue (dataQueue); + simpleWireless->SetQueue (queue); + } + else if (queueType == "PriorityTail") + { + Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); + Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); + Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); + Ptr controlQueue = CreateObject (); + Ptr dataQueue = CreateObject (); + Ptr queue = CreateObject (); + queue->Initialize (); + queue->SetControlQueue (controlQueue); + queue->SetDataQueue (dataQueue); + simpleWireless->SetQueue (queue); + } + + // Set up trace to pass node id on the RX end + std::ostringstream oss; + oss << node->GetId (); + simpleWireless->TraceConnect ("MacRx", oss.str (), MakeCallback (&MacRxSuccess)); + + node->AddDevice (simpleWireless); + devices.Add (simpleWireless); + + // set up pcap capture + if (collectPcap) + { + std::ostringstream stringStream; + stringStream << "QUEUE_node_" << node->GetId () << ".pcap"; + fileStr = stringStream.str (); + simpleWireless->EnablePcapAll (fileStr); + } + } + + // set up call back for traces + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/QueueLatency", MakeCallback (&QueueLatencyStats)); + Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/$ns3::SimpleWirelessNetDevice/PhyTxBegin", MakeCallback (&TransmitStatsSW)); + + // *********************************************************************** + // Define positions. Nodes are 50 apart + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (50.0, 0.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (NpNodes); + + + // *********************************************************************** + // Set up routing OLSR + // *********************************************************************** + // don't have to use the Ipv4ListRoutingHelper but it prints + // the routing table in a better format than directly installing olsr. + InternetStackHelper stack; + OlsrHelper olsr; + Ipv4ListRoutingHelper list; + + // Add the routing to the route helper + list.Add (olsr, 10); + + // print the olsr routing table to a file every 10 seconds + //Ptr routingStream = Create ("400node_OLSR.routes", std::ios::out); + //olsr.PrintRoutingTableAllEvery (Seconds (10), routingStream); + + // now set the routing and install on all nodes + stack.SetRoutingHelper (list); + stack.Install (NpNodes); + + // set up IP addresses + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.0.0"); + Ipv4InterfaceContainer interfaces = address.Assign (devices); + + // *********************************************************************** + // Set up application + // *********************************************************************** + // start the packet sink on destination node + PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); + ApplicationContainer apps_sink = sink.Install (NpNodes.Get (1)); + apps_sink.Start (Seconds (0.0)); + std::cout << "Node 1 installed sink to receive on " << interfaces.GetAddress (1) << std::endl; + + // set up the sink receive callback on all packet sinks + Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&SinkReceivedBytes)); + + // Now start the OnOff app on source to destinations + OnOffHelper onoff = OnOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (interfaces.GetAddress (1), 8080)); + onoff.SetAttribute ("PacketSize", StringValue (PktSize)); + onoff.SetAttribute ("DataRate", StringValue ("1000000")); + onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + + ApplicationContainer apps = onoff.Install (NpNodes.Get (0)); + std::cout << "Node 0 installed app to send to " << interfaces.GetAddress (1) << std::endl; + apps.Get (0)->TraceConnectWithoutContext ("Tx", MakeCallback (&AppSendBytes)); + + apps.Start (Seconds (5.0)); + apps.Stop (Seconds (simtime - 5.0)); + + + // *********************************************************************** + // and finally ... off we go! + // *********************************************************************** + + Simulator::Stop (Seconds (simtime)); + Simulator::Run (); + Simulator::Destroy (); + + // *********************************************************************** + // For OLSR we need to get some stats + // *********************************************************************** + double rcvPercentData = 0.0; + uint32_t dataDropped = app_count_sent - app_count_recv; + if (app_count_sent) + { + rcvPercentData = ((double)app_count_recv / (double)app_count_sent) * 100.0; + } + + double rcvPercentCntrl = 0.0; + uint32_t cntlDropped = pkts_sent_cntl - pkts_rcvd_cntl; + if (pkts_sent_cntl) + { + rcvPercentCntrl = ((double)pkts_rcvd_cntl / (double)pkts_sent_cntl) * 100.0; + } + + std::cout << "App Packets Sent: " << app_count_sent << "\nApp Packets Received: " << app_count_recv + << "\nControl Packets Sent: " << pkts_sent_cntl << "\nControl Bytes Sent: " << bytes_sent_cntl + << "\nData Packets Sent: " << pkts_sent_data << "\nData Bytes Sent: " << bytes_sent_data + << "\nControl Packets Received: " << pkts_rcvd_cntl << "\nData Packets Received: " << pkts_rcvd_data + << "\nData Packets Dropped: " << dataDropped << "\nControl Packets Dropped: " << cntlDropped + << "\n% Data Received: " << std::fixed << std::setprecision (1) << rcvPercentData << std::noshowpoint << std::setprecision (0) + << "\n% Control Received: " << std::fixed << std::setprecision (1) << rcvPercentCntrl << std::noshowpoint << std::setprecision (0) << std::endl; + if ( (queueType == "PriorityHead") || (queueType == "PriorityTail") ) + { + std::cout << "Average Queue Latency Data: " << std::fixed << std::setprecision (6) << avg_queue_latency_data + << "\nAverage Queue Latency Control: " << std::fixed << std::setprecision (6) << avg_queue_latency_cntl << std::noshowpoint << std::setprecision (0) << std::endl; + } + else + { + std::cout << "Average Queue Latency: " << std::fixed << std::setprecision (6) << avg_queue_latency << std::noshowpoint << std::setprecision (0) << std::endl; + } + + NS_LOG_INFO ("Run Completed Successfully"); + + return 0; } diff --git a/model/drop-head-queue.cc b/model/drop-head-queue.cc index 4010682..07a8547 100644 --- a/model/drop-head-queue.cc +++ b/model/drop-head-queue.cc @@ -28,23 +28,23 @@ NS_LOG_COMPONENT_DEFINE ("DropHeadQueue"); NS_OBJECT_ENSURE_REGISTERED (DropHeadQueue); -TypeId DropHeadQueue::GetTypeId (void) +TypeId DropHeadQueue::GetTypeId (void) { static TypeId tid = TypeId ("ns3::DropHeadQueue") .SetParent () .AddConstructor () - .AddAttribute ("Mode", + .AddAttribute ("Mode", "Whether to use bytes (see MaxBytes) or packets (see MaxPackets) as the maximum queue size metric.", EnumValue (QUEUE_MODE_PACKETS), MakeEnumAccessor (&DropHeadQueue::SetMode), MakeEnumChecker (QUEUE_MODE_BYTES, "QUEUE_MODE_BYTES", QUEUE_MODE_PACKETS, "QUEUE_MODE_PACKETS")) - .AddAttribute ("MaxPackets", + .AddAttribute ("MaxPackets", "The maximum number of packets accepted by this DropHeadQueue.", UintegerValue (100), MakeUintegerAccessor (&DropHeadQueue::m_maxPackets), MakeUintegerChecker ()) - .AddAttribute ("MaxBytes", + .AddAttribute ("MaxBytes", "The maximum number of bytes accepted by this DropHeadQueue.", UintegerValue (100 * 65535), MakeUintegerAccessor (&DropHeadQueue::m_maxBytes), @@ -81,7 +81,7 @@ DropHeadQueue::GetMode (void) return m_mode; } -bool +bool DropHeadQueue::DoEnqueue (Ptr p) { NS_LOG_FUNCTION (this << p); @@ -89,7 +89,7 @@ DropHeadQueue::DoEnqueue (Ptr p) if (m_mode == QUEUE_MODE_PACKETS && (m_packets.size () >= m_maxPackets)) { NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt"); - Ptr head_packet = Dequeue(); + Ptr head_packet = Dequeue (); Drop (head_packet); } @@ -99,7 +99,7 @@ DropHeadQueue::DoEnqueue (Ptr p) while (m_bytesInQueue + p->GetSize () >= m_maxBytes) { NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- droppping pkt"); - Ptr head_packet = Dequeue(); + Ptr head_packet = Dequeue (); Drop (head_packet); } } diff --git a/model/drop-head-queue.h b/model/drop-head-queue.h index 59ff30b..d11c4d4 100644 --- a/model/drop-head-queue.h +++ b/model/drop-head-queue.h @@ -33,7 +33,8 @@ class TraceContainer; * * \brief A FIFO packet queue that drops head-end packets on overflow */ -class DropHeadQueue : public Queue { +class DropHeadQueue : public Queue +{ public: /** * \brief Get the type ID. @@ -47,7 +48,7 @@ class DropHeadQueue : public Queue { */ DropHeadQueue (); - virtual ~DropHeadQueue(); + virtual ~DropHeadQueue (); /** * Set the operating mode of this device. diff --git a/model/priority-queue.cc b/model/priority-queue.cc index e4fa67d..72a7305 100644 --- a/model/priority-queue.cc +++ b/model/priority-queue.cc @@ -30,23 +30,23 @@ NS_LOG_COMPONENT_DEFINE ("PriorityQueue"); NS_OBJECT_ENSURE_REGISTERED (PriorityQueue); -TypeId PriorityQueue::GetTypeId (void) +TypeId PriorityQueue::GetTypeId (void) { static TypeId tid = TypeId ("ns3::PriorityQueue") .SetParent () .AddConstructor () - - .AddAttribute ("ControlQueue", + + .AddAttribute ("ControlQueue", "A queue to use as the transmit queue in the device.", PointerValue (), MakePointerAccessor (&PriorityQueue::m_controlQueue), MakePointerChecker ()) - .AddAttribute ("DataQueue", + .AddAttribute ("DataQueue", "A queue to use as the transmit queue in the device.", PointerValue (), MakePointerAccessor (&PriorityQueue::m_dataQueue), MakePointerChecker ()) - .AddAttribute ("ControlPacketClassifier", + .AddAttribute ("ControlPacketClassifier", "Pcap style filter to classify control packets", StringValue (), MakeStringAccessor (&PriorityQueue::m_classifier), @@ -100,20 +100,20 @@ PriorityQueue::SetDataQueue (Ptr q) } Ptr -PriorityQueue::GetControlQueue (void) const -{ +PriorityQueue::GetControlQueue (void) const +{ NS_LOG_FUNCTION_NOARGS (); return m_controlQueue; } Ptr -PriorityQueue::GetDataQueue (void) const -{ +PriorityQueue::GetDataQueue (void) const +{ NS_LOG_FUNCTION_NOARGS (); return m_dataQueue; } -PriorityQueue::PacketClass +PriorityQueue::PacketClass PriorityQueue::Classify (Ptr p) { pcap_pkthdr pcapPkthdr; @@ -136,7 +136,7 @@ PriorityQueue::Classify (Ptr p) } } -bool +bool PriorityQueue::DoEnqueue (Ptr p) { NS_LOG_FUNCTION (this << p); diff --git a/model/priority-queue.h b/model/priority-queue.h index 5a5cff7..0489b7d 100644 --- a/model/priority-queue.h +++ b/model/priority-queue.h @@ -35,7 +35,8 @@ class TraceContainer; * * \brief A strict priority queue with two subqueues, one for control packets and one for data */ -class PriorityQueue : public Queue { +class PriorityQueue : public Queue +{ public: /** * \brief Get the type ID. @@ -49,7 +50,7 @@ class PriorityQueue : public Queue { */ PriorityQueue (); - virtual ~PriorityQueue(); + virtual ~PriorityQueue (); /** * \brief PriorityQueue Constructor @@ -61,7 +62,7 @@ class PriorityQueue : public Queue { /** * Attach a queue to hold data packets to the PriorityQueue. * - * The PriorityQueue "owns" a sub queue that implements a queueing + * The PriorityQueue "owns" a sub queue that implements a queueing * method such as DropTailQueue, DropHeadQueue or RedQueue * * \param queue Ptr to the new queue. @@ -71,7 +72,7 @@ class PriorityQueue : public Queue { /** * Attach a queue to hold control packets to the PriorityQueue. * - * The PriorityQueue "owns" a sub queue that implements a queueing + * The PriorityQueue "owns" a sub queue that implements a queueing * method such as DropTailQueue, DropHeadQueue or RedQueue * * \param queue Ptr to the new queue. diff --git a/model/simple-wireless-channel.cc b/model/simple-wireless-channel.cc index 1580cf0..2d2e154 100644 --- a/model/simple-wireless-channel.cc +++ b/model/simple-wireless-channel.cc @@ -35,7 +35,7 @@ namespace ns3 { NS_OBJECT_ENSURE_REGISTERED (SimpleWirelessChannel); -TypeId +TypeId SimpleWirelessChannel::GetTypeId (void) { static TypeId tid = TypeId ("ns3::SimpleWirelessChannel") @@ -46,7 +46,7 @@ SimpleWirelessChannel::GetTypeId (void) DoubleValue (250), MakeDoubleAccessor (&SimpleWirelessChannel::m_range), MakeDoubleChecker ()) - .AddAttribute ("RangeErrorModel", + .AddAttribute ("RangeErrorModel", "Type or range based error model", EnumValue (CONSTANT), MakeEnumAccessor (&SimpleWirelessChannel::m_ErrorModel), @@ -55,14 +55,14 @@ SimpleWirelessChannel::GetTypeId (void) STOCHASTIC, "STOCHASTIC")) .AddAttribute ("RangeErrorRate", "Error rate when using constant Range Error Model", - StringValue("0.0"), + StringValue ("0.0"), MakeDoubleAccessor (&SimpleWirelessChannel::m_errorRate), MakeDoubleChecker ()) - .AddAttribute ("EnableFixedContention", + .AddAttribute ("EnableFixedContention", "Enabled or Disabled", BooleanValue (false), MakeBooleanAccessor (&SimpleWirelessChannel::m_fixedContentionEnabled), - MakeBooleanChecker ()) + MakeBooleanChecker ()) .AddAttribute ("FixedContentionRange", "Maximum Range (meters) for Fixed Contention", DoubleValue (0), // default to 0 so we can use the tx range as default if the user does not set this @@ -78,123 +78,125 @@ SimpleWirelessChannel::GetTypeId (void) TimeValue (MicroSeconds (100.0)), MakeTimeAccessor (&SimpleWirelessChannel::m_downDuration), MakeTimeChecker ()) - ; + ; return tid; } SimpleWirelessChannel::SimpleWirelessChannel () { - // Default to a constant error model with 0 errors - m_random = CreateObject (); - m_ErrorModel = CONSTANT; - m_errorRate = 0.0; - m_fixedContentionEnabled = false; - m_fixedContentionRange = 0; + // Default to a constant error model with 0 errors + m_random = CreateObject (); + m_ErrorModel = CONSTANT; + m_errorRate = 0.0; + m_fixedContentionEnabled = false; + m_fixedContentionRange = 0; } void -SimpleWirelessChannel::Send (Ptr p, uint16_t protocol, - Mac48Address to, Mac48Address from, - Ptr sender, Time txTime, uint32_t destId) +SimpleWirelessChannel::Send (Ptr p, uint16_t protocol, + Mac48Address to, Mac48Address from, + Ptr sender, Time txTime, uint32_t destId) { NS_LOG_FUNCTION (p << protocol << to << from << sender); - - uint32_t senderNodeId = sender->GetNode()->GetId(); - + + uint32_t senderNodeId = sender->GetNode ()->GetId (); + if (m_fixedContentionEnabled) - { - sender->ClearNbrCount(); - - // if the range has not been set, use the tx range. - // We do this here because we want the value for range that the user selected value. - // If we set the contention range to m_range in other places (like the call to - // EnableFixedContention), at that point the range could still be the default - // value and not the value the user has set. - if (m_fixedContentionRange == 0) - m_fixedContentionRange = m_range; - } + { + sender->ClearNbrCount (); + + // if the range has not been set, use the tx range. + // We do this here because we want the value for range that the user selected value. + // If we set the contention range to m_range in other places (like the call to + // EnableFixedContention), at that point the range could still be the default + // value and not the value the user has set. + if (m_fixedContentionRange == 0) + { + m_fixedContentionRange = m_range; + } + } for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) { Ptr tmp = *i; - uint32_t destNodeId = tmp->GetNode()->GetId(); - + uint32_t destNodeId = tmp->GetNode ()->GetId (); + // don't send to ourselves if (tmp == sender) { NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Node is self"); continue; } - + // See if we have directional networking enabled and if so if this is destination node if ( (destId != NO_DIRECTIONAL_NBR) && (destNodeId != destId) ) - { - NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Directional networking enabled and node is not destination " << destId); - continue; - } - + { + NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Directional networking enabled and node is not destination " << destId); + continue; + } + // See if we are using stochastic. If so see if the sender's link // to the destination is up or down if (CheckStochasticError (senderNodeId, destNodeId)) - { - NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Stochastic error enabled and link to node is in OFF state"); - continue; - } + { + NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". Stochastic error enabled and link to node is in OFF state"); + continue; + } Ptr a = sender->GetNode ()->GetObject (); Ptr b = tmp->GetNode ()->GetObject (); NS_ASSERT_MSG (a && b, "Error: nodes must have mobility models"); - + // Get distance and determine error rate based on that // and the error model double distance = a->GetDistanceFrom (b); - - + + // if fixed contention is enabled then we need to peg the neighbor count if ( (m_fixedContentionEnabled) && (distance < m_fixedContentionRange) ) - { - sender->IncrementNbrCount(); - NS_LOG_INFO ("Node " << senderNodeId << " pegging nbr count for contention. distane is " << distance << ". count is now " << sender->GetNbrCount()); - } - + { + sender->IncrementNbrCount (); + NS_LOG_INFO ("Node " << senderNodeId << " pegging nbr count for contention. distane is " << distance << ". count is now " << sender->GetNbrCount ()); + } + // Is this packet beyond the transmission range? if (distance > m_range) - { - NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". distance of " << distance << " is out of range"); - continue; - } - + { + NS_LOG_INFO ("Node " << senderNodeId << " NOT sending to node " << destNodeId << ". distance of " << distance << " is out of range"); + continue; + } + // Is this packet in error or can we send it based on the distance? - if (packetInError(distance)) - { - continue; - } + if (packetInError (distance)) + { + continue; + } // propagation delay. speed of light is 3.3 ns/meter double propDelay = 3.3 * distance; - NS_LOG_INFO ("Node " << senderNodeId << " sending to node " << destNodeId - << " at distance " << distance << " meters; time (ns): "<< Simulator::Now().GetNanoSeconds () - << " txDelay: " << txTime << " propDelay: " << propDelay); - + NS_LOG_INFO ("Node " << senderNodeId << " sending to node " << destNodeId + << " at distance " << distance << " meters; time (ns): " << Simulator::Now ().GetNanoSeconds () + << " txDelay: " << txTime << " propDelay: " << propDelay); + Simulator::ScheduleWithContext (destNodeId, NanoSeconds (txTime + propDelay), &SimpleWirelessNetDevice::Receive, tmp, p->Copy (), protocol, to, from); } } -void +void SimpleWirelessChannel::Add (Ptr device) { m_devices.push_back (device); } -uint32_t +uint32_t SimpleWirelessChannel::GetNDevices (void) const { return m_devices.size (); } -Ptr +Ptr SimpleWirelessChannel::GetDevice (uint32_t i) const { return m_devices[i]; @@ -203,10 +205,10 @@ SimpleWirelessChannel::GetDevice (uint32_t i) const //******************************************************************** // contention functions -void SimpleWirelessChannel::EnableFixedContention(void) +void SimpleWirelessChannel::EnableFixedContention (void) { m_fixedContentionEnabled = true; - + // Set up all the devices to support contention. // IMPORTANT NOTE: There may not be any devices at this point on the channel. // If there are not any, then the first packet sent by the device will use the @@ -215,229 +217,231 @@ void SimpleWirelessChannel::EnableFixedContention(void) // after the data rate has been used to set the tx time. All subsequent packets sent // by the device will use contention just not the first one. for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) - { - Ptr tmp = *i; - tmp->ClearNbrCount(); - } + { + Ptr tmp = *i; + tmp->ClearNbrCount (); + } } - -void SimpleWirelessChannel::SetFixedContentionRange(double range) + +void SimpleWirelessChannel::SetFixedContentionRange (double range) { m_fixedContentionRange = range; } //******************************************************************** // Error Model functions -void SimpleWirelessChannel::setErrorModelType(ErrorModelType type) +void SimpleWirelessChannel::setErrorModelType (ErrorModelType type) { m_ErrorModel = type; - + // reset range to 0 if error model is PER CURVE so that // we can compare to distances added to the curve to // get the max range if (m_ErrorModel == PER_CURVE) - { - m_range = 0; - } + { + m_range = 0; + } } -void SimpleWirelessChannel::setErrorRate(double error) +void SimpleWirelessChannel::setErrorRate (double error) { m_errorRate = error; } -void SimpleWirelessChannel::addToPERmodel(double distance, double error) +void SimpleWirelessChannel::addToPERmodel (double distance, double error) { // NOTE: distance is in meters - mPERmap.insert(std::pair(distance, error)); - + mPERmap.insert (std::pair (distance, error)); + if (distance > m_range) - { - m_range = distance; - } + { + m_range = distance; + } } //******************************************************************** // Stochastic error functions -void SimpleWirelessChannel::InitStochasticModel() +void SimpleWirelessChannel::InitStochasticModel () { // Build the map of neighbor links, setting all links to // ON state and pick a duration for that state. if (m_ErrorModel == STOCHASTIC) - { - if (m_devices.size() == 0) - { - NS_LOG_ERROR ("InitStochasticModel called but there are no devices on the channel. Be sure to call InitStochasticModel AFTER devices have been added."); - } - - m_randomUp = CreateObject (); - m_randomDown = CreateObject (); - - m_randomUp->SetAttribute ("Mean", DoubleValue (m_upDuration.GetMicroSeconds())); - m_randomDown->SetAttribute ("Mean", DoubleValue (m_downDuration.GetMicroSeconds())); - - Time currTime = Simulator::Now(); - - for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) - { - for (std::vector >::const_iterator j = m_devices.begin (); j != m_devices.end (); ++j) + { + if (m_devices.size () == 0) + { + NS_LOG_ERROR ("InitStochasticModel called but there are no devices on the channel. Be sure to call InitStochasticModel AFTER devices have been added."); + } + + m_randomUp = CreateObject (); + m_randomDown = CreateObject (); + + m_randomUp->SetAttribute ("Mean", DoubleValue (m_upDuration.GetMicroSeconds ())); + m_randomDown->SetAttribute ("Mean", DoubleValue (m_downDuration.GetMicroSeconds ())); + + Time currTime = Simulator::Now (); + + for (std::vector >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i) { - int src = (*i)->GetNode()->GetId(); - int dst = (*j)->GetNode()->GetId(); - - if (src == dst) - continue; - - StochasticLink tempLink; - tempLink.linkState = true; - tempLink.stateExpireTime = currTime + MicroSeconds(m_randomUp->GetValue()); - //tempLink.stateExpireTime = Simulator::Now() + Seconds(1.0); - - m_StochasticLinks.insert(std::pair(StochasticKey(src,dst), tempLink)); - NS_LOG_DEBUG("Add link to stochastic map. src: " << src << " dst: " << dst << " expireTime: " - << std::setprecision (9) << tempLink.stateExpireTime.GetSeconds() << " state: " << tempLink.linkState); + for (std::vector >::const_iterator j = m_devices.begin (); j != m_devices.end (); ++j) + { + int src = (*i)->GetNode ()->GetId (); + int dst = (*j)->GetNode ()->GetId (); + + if (src == dst) + { + continue; + } + + StochasticLink tempLink; + tempLink.linkState = true; + tempLink.stateExpireTime = currTime + MicroSeconds (m_randomUp->GetValue ()); + //tempLink.stateExpireTime = Simulator::Now() + Seconds(1.0); + + m_StochasticLinks.insert (std::pair (StochasticKey (src,dst), tempLink)); + NS_LOG_DEBUG ("Add link to stochastic map. src: " << src << " dst: " << dst << " expireTime: " + << std::setprecision (9) << tempLink.stateExpireTime.GetSeconds () << " state: " << tempLink.linkState); + } } - } - } + } } // This returns true if we should NOT send the packet. // That is, return true == packet fails to send -bool SimpleWirelessChannel::CheckStochasticError(uint32_t srcId, uint32_t dstId) +bool SimpleWirelessChannel::CheckStochasticError (uint32_t srcId, uint32_t dstId) { if (m_ErrorModel == STOCHASTIC) - { - // get entry from map for this src/dst pair - StochasIt iter = m_StochasticLinks.find(StochasticKey(srcId, dstId)); - NS_ASSERT( iter != m_StochasticLinks.end()); - - Time currTime = Simulator::Now(); - - //std::cout << std::setprecision (9) << currTime.GetSeconds() << " Checking state for link src: " << srcId << " dst: " << dstId << " expireTime: " << iter->second.stateExpireTime << std::endl; - - if (currTime >= iter->second.stateExpireTime) - { - // the time at which the previous state was set to end has already passed. - Time endTime = iter->second.stateExpireTime; - bool tempState = iter->second.linkState; - Time newDuration; - // Pick the new states until we get to one that is at or greater - // than the current time. - while (endTime < currTime) + { + // get entry from map for this src/dst pair + StochasIt iter = m_StochasticLinks.find (StochasticKey (srcId, dstId)); + NS_ASSERT ( iter != m_StochasticLinks.end ()); + + Time currTime = Simulator::Now (); + + //std::cout << std::setprecision (9) << currTime.GetSeconds() << " Checking state for link src: " << srcId << " dst: " << dstId << " expireTime: " << iter->second.stateExpireTime << std::endl; + + if (currTime >= iter->second.stateExpireTime) { - // Now pick duration for the new state - if (!tempState) - { - newDuration = MicroSeconds(m_randomUp->GetValue()); - } - else + // the time at which the previous state was set to end has already passed. + Time endTime = iter->second.stateExpireTime; + bool tempState = iter->second.linkState; + Time newDuration; + // Pick the new states until we get to one that is at or greater + // than the current time. + while (endTime < currTime) { - newDuration = MicroSeconds(m_randomDown->GetValue()); + // Now pick duration for the new state + if (!tempState) + { + newDuration = MicroSeconds (m_randomUp->GetValue ()); + } + else + { + newDuration = MicroSeconds (m_randomDown->GetValue ()); + } + endTime += newDuration; + tempState = !tempState; + + NS_LOG_DEBUG ("---> " << std::setprecision (9) << currTime.GetSeconds () << " next state: " << tempState << " for link src: " << srcId << " dst: " << dstId + << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds () + << " expireTime: " << std::setprecision (9) << endTime.GetSeconds ()); } - endTime += newDuration; - tempState = !tempState; - - NS_LOG_DEBUG("---> " << std::setprecision (9) << currTime.GetSeconds() << " next state: " << tempState << " for link src: " << srcId << " dst: " << dstId - << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds() - << " expireTime: " << std::setprecision (9) << endTime.GetSeconds()); - } - - // When we get here, the new state and time are selected - iter->second.linkState = tempState; - iter->second.stateExpireTime = endTime; - - NS_LOG_DEBUG(std::setprecision (9) << currTime.GetSeconds() << " New state " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId - << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds() - << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds()); - - } - else - { - NS_LOG_DEBUG(std::setprecision (9) << currTime.GetSeconds() << " State " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId - << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds()); - } - - // now return true or false depending on state - // true = packet is in "error" and failes - // false = packet not in error and sends - if (iter->second.linkState) - { - return false; - } - else - { - return true; - } - } + + // When we get here, the new state and time are selected + iter->second.linkState = tempState; + iter->second.stateExpireTime = endTime; + + NS_LOG_DEBUG (std::setprecision (9) << currTime.GetSeconds () << " New state " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId + << " duration of next state: " << std::setprecision (9) << newDuration.GetSeconds () + << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds ()); + + } + else + { + NS_LOG_DEBUG (std::setprecision (9) << currTime.GetSeconds () << " State " << iter->second.linkState << " for link src: " << srcId << " dst: " << dstId + << " expireTime: " << std::setprecision (9) << iter->second.stateExpireTime.GetSeconds ()); + } + + // now return true or false depending on state + // true = packet is in "error" and failes + // false = packet not in error and sends + if (iter->second.linkState) + { + return false; + } + else + { + return true; + } + } else - { - return false; - } + { + return false; + } } //******************************************************************** -bool SimpleWirelessChannel::packetInError(double distance) +bool SimpleWirelessChannel::packetInError (double distance) { std::map::iterator it; std::map::iterator up_iter; std::map::iterator low_iter; - + if (m_ErrorModel == CONSTANT) - { + { if ( m_random->GetValue () < m_errorRate ) - { - NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); - return true; - } - } - else if (m_ErrorModel == PER_CURVE) - { - it = mPERmap.find(distance); - if (it != mPERmap.end()) - { - // we found an exact match in the map for this distance - if (m_random->GetValue() < it->second) - { - NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); - return true; - } - } - else - { - // we did not find an exact match in the map. That's OK - // since it could actually be unlikely to find one. - // Now we just extrapolate between the two entries in the map - - // first get iterator to upper bound - up_iter = mPERmap.upper_bound(distance); - if (up_iter == mPERmap.end()) - { - // We shouldn't hit this situation because we already checked the distance - // relative to the range but go ahead and leave this here - // this distance is beyond the upper bound so error is 100% - NS_LOG_INFO("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); - return true; - } - - // Set low iter to upper then decrement it - low_iter = up_iter; - --low_iter; - - double errorRate = low_iter->second + ( ((distance - low_iter->first)/(up_iter->first - low_iter->first)) * (up_iter->second - low_iter->second)); - NS_LOG_INFO("Error Model: " << m_ErrorModel << " distance: " << distance << " calculated error rate: " << errorRate << " low distance: " << low_iter->first << " low error: " << low_iter->second - << " high distance: " << up_iter->first << " high error: " << up_iter->second); - - if (m_random->GetValue() < errorRate) - { + { + NS_LOG_INFO ("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); return true; - } - } - } + } + } + else if (m_ErrorModel == PER_CURVE) + { + it = mPERmap.find (distance); + if (it != mPERmap.end ()) + { + // we found an exact match in the map for this distance + if (m_random->GetValue () < it->second) + { + NS_LOG_INFO ("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); + return true; + } + } + else + { + // we did not find an exact match in the map. That's OK + // since it could actually be unlikely to find one. + // Now we just extrapolate between the two entries in the map + + // first get iterator to upper bound + up_iter = mPERmap.upper_bound (distance); + if (up_iter == mPERmap.end ()) + { + // We shouldn't hit this situation because we already checked the distance + // relative to the range but go ahead and leave this here + // this distance is beyond the upper bound so error is 100% + NS_LOG_INFO ("Error Model: " << m_ErrorModel << " Checking for error at distance: " << distance << " Too high error. Packet in error."); + return true; + } + + // Set low iter to upper then decrement it + low_iter = up_iter; + --low_iter; + + double errorRate = low_iter->second + ( ((distance - low_iter->first) / (up_iter->first - low_iter->first)) * (up_iter->second - low_iter->second)); + NS_LOG_INFO ("Error Model: " << m_ErrorModel << " distance: " << distance << " calculated error rate: " << errorRate << " low distance: " << low_iter->first << " low error: " << low_iter->second + << " high distance: " << up_iter->first << " high error: " << up_iter->second); + + if (m_random->GetValue () < errorRate) + { + return true; + } + } + } // if we get here then there were no errors diff --git a/model/simple-wireless-channel.h b/model/simple-wireless-channel.h index 13125b5..fe09992 100644 --- a/model/simple-wireless-channel.h +++ b/model/simple-wireless-channel.h @@ -34,59 +34,63 @@ namespace ns3 { class SimpleWirelessNetDevice; class Packet; -enum ErrorModelType { - /** - * In Constant mode, the packet error rate is constant within the - * specified distance range. - */ - CONSTANT, - /** - * In PER Curve mode, the packet error curves are used to - * determine the error rate. The distance is used to look up the - * error rate. Note that the range value specified is ignored. - * User must build the PER curve by calling addToPERmodel. - */ - PER_CURVE, - /** - * In Stochastic mode, there are no per packet errors. Instead, - * the link to each neighbor is either on or off for randomly - * selected durations. - */ - STOCHASTIC +enum ErrorModelType +{ + /** + * In Constant mode, the packet error rate is constant within the + * specified distance range. + */ + CONSTANT, + /** + * In PER Curve mode, the packet error curves are used to + * determine the error rate. The distance is used to look up the + * error rate. Note that the range value specified is ignored. + * User must build the PER curve by calling addToPERmodel. + */ + PER_CURVE, + /** + * In Stochastic mode, there are no per packet errors. Instead, + * the link to each neighbor is either on or off for randomly + * selected durations. + */ + STOCHASTIC }; //*************************************************************** // Define key for stochastic error map key //*************************************************************** -class StochasticKey { - public: - int srcNodeId; - int destNodeId; - - StochasticKey(int k1, int k2) - : srcNodeId(k1), destNodeId(k2){} - - // Ordering is: - // 1. lowest source node id - // 2. lowest destination node id - - bool operator<(const StochasticKey &right) const - { - if (srcNodeId == right.srcNodeId) +class StochasticKey +{ +public: + int srcNodeId; + int destNodeId; + + StochasticKey (int k1, int k2) + : srcNodeId (k1), destNodeId (k2) + { + } + + // Ordering is: + // 1. lowest source node id + // 2. lowest destination node id + + bool operator< (const StochasticKey &right) const + { + if (srcNodeId == right.srcNodeId) { - return(destNodeId < right.destNodeId); + return(destNodeId < right.destNodeId); } - else + else { - return (srcNodeId < right.srcNodeId); + return (srcNodeId < right.srcNodeId); } - } + } }; struct StochasticLink { - bool linkState; // 1 = ON, 0 = OFF - Time stateExpireTime; + bool linkState; // 1 = ON, 0 = OFF + Time stateExpireTime; }; typedef std::map ::iterator StochasIt; @@ -102,23 +106,23 @@ class SimpleWirelessChannel : public Channel SimpleWirelessChannel (); void Send (Ptr p, uint16_t protocol, Mac48Address to, Mac48Address from, - Ptr sender, Time txTime, uint32_t destId); + Ptr sender, Time txTime, uint32_t destId); void Add (Ptr device); // inherited from ns3::Channel virtual uint32_t GetNDevices (void) const; virtual Ptr GetDevice (uint32_t i) const; - - void setErrorModelType(ErrorModelType type); - void setErrorRate(double error); - void addToPERmodel(double distance, double error); - bool packetInError(double distance); - void EnableFixedContention(void); - void SetFixedContentionRange(double error); - void InitStochasticModel(); - bool CheckStochasticError(uint32_t srcId, uint32_t dstId); - + + void setErrorModelType (ErrorModelType type); + void setErrorRate (double error); + void addToPERmodel (double distance, double error); + bool packetInError (double distance); + void EnableFixedContention (void); + void SetFixedContentionRange (double error); + void InitStochasticModel (); + bool CheckStochasticError (uint32_t srcId, uint32_t dstId); + private: std::vector > m_devices; double m_range; @@ -126,16 +130,16 @@ class SimpleWirelessChannel : public Channel ErrorModelType m_ErrorModel; Ptr m_random; std::map mPERmap; - + bool m_fixedContentionEnabled; double m_fixedContentionRange; Ptr m_randomUp; Ptr m_randomDown; - + Time m_upDuration; Time m_downDuration; std::map m_StochasticLinks; - + }; } // namespace ns3 diff --git a/model/simple-wireless-net-device.cc b/model/simple-wireless-net-device.cc index 32ccf25..a6a6d7e 100644 --- a/model/simple-wireless-net-device.cc +++ b/model/simple-wireless-net-device.cc @@ -93,8 +93,8 @@ void TimestampTag::Print (std::ostream &os) const //******************************************************** //******************************************************** -// DestinationIdTag used to store a destination node id -// with a packet when they are placed in the queue. +// DestinationIdTag used to store a destination node id +// with a packet when they are placed in the queue. // This is used by directional networks. //******************************************************** TypeId DestinationIdTag::GetTypeId (void) @@ -152,7 +152,7 @@ void DestinationIdTag::Print (std::ostream &os) const //******************************************************** -TypeId +TypeId SimpleWirelessNetDevice::GetTypeId (void) { static TypeId tid = TypeId ("ns3::SimpleWirelessNetDevice") @@ -163,19 +163,19 @@ SimpleWirelessNetDevice::GetTypeId (void) PointerValue (), MakePointerAccessor (&SimpleWirelessNetDevice::m_receiveErrorModel), MakePointerChecker ()) - .AddAttribute ("DataRate", + .AddAttribute ("DataRate", "The default data rate for point to point links", DataRateValue (DataRate ("1000000b/s")), MakeDataRateAccessor (&SimpleWirelessNetDevice::m_bps), MakeDataRateChecker ()) // Transmit queueing discipline for the device which includes its own set // of trace hooks. - .AddAttribute ("TxQueue", + .AddAttribute ("TxQueue", "A queue to use as the transmit queue in the device.", PointerValue (), MakePointerAccessor (&SimpleWirelessNetDevice::m_queue), MakePointerChecker ()) - .AddAttribute ("FixedNeighborListEnabled", + .AddAttribute ("FixedNeighborListEnabled", "Enabled or Disabled", BooleanValue (false), MakeBooleanAccessor (&SimpleWirelessNetDevice::m_fixedNbrListEnabled), @@ -197,7 +197,7 @@ SimpleWirelessNetDevice::GetTypeId (void) "by the device", MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxEndTrace)) // Trace sources designed to simulate a packet sniffer facility (tcpdump). - .AddTraceSource ("PromiscSniffer", + .AddTraceSource ("PromiscSniffer", "Trace source simulating a promiscuous packet sniffer attached to the device", MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_promiscSnifferTrace)) .AddTraceSource ("QueueLatency", @@ -210,37 +210,38 @@ SimpleWirelessNetDevice::GetTypeId (void) .AddTraceSource ("MacRx", "A packet has been received by this device, has been passed up from the physical layer " "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macRxTrace)) - ; + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macRxTrace)) + ; return tid; } SimpleWirelessNetDevice::SimpleWirelessNetDevice () : m_channel (0), - m_node (0), - m_mtu (0xffff), - m_ifIndex (0), - m_txMachineState (READY), - m_queue(NULL), - m_pktRcvTotal(0), - m_pktRcvDrop(0), - m_pcapEnabled(false), - m_fixedNbrListEnabled(false), - m_nbrCount(0) - -{} - -void -SimpleWirelessNetDevice::Receive (Ptr packet, uint16_t protocol, - Mac48Address to, Mac48Address from) + m_node (0), + m_mtu (0xffff), + m_ifIndex (0), + m_txMachineState (READY), + m_queue (NULL), + m_pktRcvTotal (0), + m_pktRcvDrop (0), + m_pcapEnabled (false), + m_fixedNbrListEnabled (false), + m_nbrCount (0) + +{ +} + +void +SimpleWirelessNetDevice::Receive (Ptr packet, uint16_t protocol, + Mac48Address to, Mac48Address from) { NS_LOG_FUNCTION (packet << protocol << to << from); NetDevice::PacketType packetType; - + m_phyRxBeginTrace (packet, from, to, protocol); m_pktRcvTotal++; - - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " receiving packet " << packet->GetUid () << " from " << from << " to " << to ); + + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " receiving packet " << packet->GetUid () << " from " << from << " to " << to ); if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) ) { @@ -248,29 +249,29 @@ SimpleWirelessNetDevice::Receive (Ptr packet, uint16_t protocol, m_pktRcvDrop++; return; } - + if (m_pcapEnabled) - { - // Add the ethernet header to the packet for sniffer - // For some reason the Ethernet header is STRIPPED from the packet - // by the time we get here so we need to reconstruct it for the - // sniffer. - // allocate buffer for packet and mac addresses - uint8_t buffer[8192]; - uint8_t macBuffer[6]; - // get the dest and src addresses and copy into the buffer - to.CopyTo(macBuffer); - memcpy(&buffer[0], macBuffer, 6); - from.CopyTo(macBuffer); - memcpy(&buffer[6], macBuffer, 6); - //copy the protocol and the actual packet data in the the buffer - uint16_t tempProt = ntohs(protocol); - memcpy(&buffer[12], &tempProt, 2); - packet->CopyData(&buffer[14], packet->GetSize()); - // Now make a new temp packet to write to the sniffer - Ptr tempPacket = Create (buffer, packet->GetSize() + 14); - m_promiscSnifferTrace (tempPacket); - } + { + // Add the ethernet header to the packet for sniffer + // For some reason the Ethernet header is STRIPPED from the packet + // by the time we get here so we need to reconstruct it for the + // sniffer. + // allocate buffer for packet and mac addresses + uint8_t buffer[8192]; + uint8_t macBuffer[6]; + // get the dest and src addresses and copy into the buffer + to.CopyTo (macBuffer); + memcpy (&buffer[0], macBuffer, 6); + from.CopyTo (macBuffer); + memcpy (&buffer[6], macBuffer, 6); + //copy the protocol and the actual packet data in the the buffer + uint16_t tempProt = ntohs (protocol); + memcpy (&buffer[12], &tempProt, 2); + packet->CopyData (&buffer[14], packet->GetSize ()); + // Now make a new temp packet to write to the sniffer + Ptr tempPacket = Create (buffer, packet->GetSize () + 14); + m_promiscSnifferTrace (tempPacket); + } if (to == m_address) { @@ -284,28 +285,28 @@ SimpleWirelessNetDevice::Receive (Ptr packet, uint16_t protocol, { packetType = NetDevice::PACKET_MULTICAST; } - else + else { packetType = NetDevice::PACKET_OTHERHOST; } - + m_phyRxEndTrace (packet, from, to, protocol); - + if (packetType != NetDevice::PACKET_OTHERHOST) { m_macRxTrace (packet); m_rxCallback (this, packet, protocol, from); } - + if (!m_promiscCallback.IsNull ()) { m_promiscCallback (this, packet, protocol, from, to, packetType); } - NS_LOG_DEBUG ("Total Rcvd: " << m_pktRcvTotal << " Total Dropped: " << m_pktRcvDrop); + NS_LOG_DEBUG ("Total Rcvd: " << m_pktRcvTotal << " Total Dropped: " << m_pktRcvDrop); } -void +void SimpleWirelessNetDevice::SetChannel (Ptr channel) { m_channel = channel; @@ -318,17 +319,17 @@ SimpleWirelessNetDevice::SetReceiveErrorModel (Ptr em) m_receiveErrorModel = em; } -void -SimpleWirelessNetDevice::SetIfIndex(const uint32_t index) +void +SimpleWirelessNetDevice::SetIfIndex (const uint32_t index) { m_ifIndex = index; } -uint32_t -SimpleWirelessNetDevice::GetIfIndex(void) const +uint32_t +SimpleWirelessNetDevice::GetIfIndex (void) const { return m_ifIndex; } -Ptr +Ptr SimpleWirelessNetDevice::GetChannel (void) const { return m_channel; @@ -336,9 +337,9 @@ SimpleWirelessNetDevice::GetChannel (void) const void SimpleWirelessNetDevice::SetAddress (Address address) { - m_address = Mac48Address::ConvertFrom(address); + m_address = Mac48Address::ConvertFrom (address); } -Address +Address SimpleWirelessNetDevice::GetAddress (void) const { // @@ -346,26 +347,27 @@ SimpleWirelessNetDevice::GetAddress (void) const // return m_address; } -bool +bool SimpleWirelessNetDevice::SetMtu (const uint16_t mtu) { m_mtu = mtu; return true; } -uint16_t +uint16_t SimpleWirelessNetDevice::GetMtu (void) const { return m_mtu; } -bool +bool SimpleWirelessNetDevice::IsLinkUp (void) const { return true; } -void +void SimpleWirelessNetDevice::AddLinkChangeCallback (Callback callback) -{} -bool +{ +} +bool SimpleWirelessNetDevice::IsBroadcast (void) const { return true; @@ -375,12 +377,12 @@ SimpleWirelessNetDevice::GetBroadcast (void) const { return Mac48Address ("ff:ff:ff:ff:ff:ff"); } -bool +bool SimpleWirelessNetDevice::IsMulticast (void) const { return false; } -Address +Address SimpleWirelessNetDevice::GetMulticast (Ipv4Address multicastGroup) const { return Mac48Address::GetMulticast (multicastGroup); @@ -388,16 +390,16 @@ SimpleWirelessNetDevice::GetMulticast (Ipv4Address multicastGroup) const Address SimpleWirelessNetDevice::GetMulticast (Ipv6Address addr) const { - return Mac48Address::GetMulticast (addr); + return Mac48Address::GetMulticast (addr); } -bool +bool SimpleWirelessNetDevice::IsPointToPoint (void) const { return false; } -bool +bool SimpleWirelessNetDevice::IsBridge (void) const { return false; @@ -405,71 +407,75 @@ SimpleWirelessNetDevice::IsBridge (void) const //******************************************************************** // Directional Neighbor functions -bool SimpleWirelessNetDevice::AddDirectionalNeighbors(std::map nodesToAdd) +bool SimpleWirelessNetDevice::AddDirectionalNeighbors (std::map nodesToAdd) { // is directional neighbor feature enabled? // If not return false so caller knows there is a problem if (!m_fixedNbrListEnabled) - return false; - - for ( std::map ::iterator it = nodesToAdd.begin(); it != nodesToAdd.end(); ++it) - { - mDirectionalNbrs.insert(std::pair(it->first, it->second)); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " added directional neighbor " << it->first << " mac Address " << it->second); - } + { + return false; + } + + for ( std::map ::iterator it = nodesToAdd.begin (); it != nodesToAdd.end (); ++it) + { + mDirectionalNbrs.insert (std::pair (it->first, it->second)); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " added directional neighbor " << it->first << " mac Address " << it->second); + } return true; } -bool SimpleWirelessNetDevice::AddDirectionalNeighbor(uint32_t nodeid, Mac48Address macAddr) +bool SimpleWirelessNetDevice::AddDirectionalNeighbor (uint32_t nodeid, Mac48Address macAddr) { // is directional neighbor feature enabled? // If not return false so caller knows there is a problem if (!m_fixedNbrListEnabled) - return false; - - mDirectionalNbrs.insert(std::pair(nodeid, macAddr)); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " added directional neighbor " << nodeid << " mac Address " << macAddr); + { + return false; + } + + mDirectionalNbrs.insert (std::pair (nodeid, macAddr)); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " added directional neighbor " << nodeid << " mac Address " << macAddr); return true; } -void SimpleWirelessNetDevice::DeleteDirectionalNeighbors(std::set nodeids) +void SimpleWirelessNetDevice::DeleteDirectionalNeighbors (std::set nodeids) { - for ( std::set::iterator it = nodeids.begin(); it != nodeids.end(); ++it) - { - std::map::iterator it2 = mDirectionalNbrs.find(*it); - if (it2 != mDirectionalNbrs.end()) - { - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " deleted directional neighbor " << it2->first << " mac Address " << it2->second); - mDirectionalNbrs.erase(it2); - } - } + for ( std::set::iterator it = nodeids.begin (); it != nodeids.end (); ++it) + { + std::map::iterator it2 = mDirectionalNbrs.find (*it); + if (it2 != mDirectionalNbrs.end ()) + { + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " deleted directional neighbor " << it2->first << " mac Address " << it2->second); + mDirectionalNbrs.erase (it2); + } + } } -void SimpleWirelessNetDevice::DeleteDirectionalNeighbor(uint32_t nodeid) +void SimpleWirelessNetDevice::DeleteDirectionalNeighbor (uint32_t nodeid) { - std::map::iterator it = mDirectionalNbrs.find(nodeid); - if (it != mDirectionalNbrs.end()) - { - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " deleted directional neighbor " << nodeid << " mac Address " << it->second); - mDirectionalNbrs.erase(it); - } + std::map::iterator it = mDirectionalNbrs.find (nodeid); + if (it != mDirectionalNbrs.end ()) + { + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " deleted directional neighbor " << nodeid << " mac Address " << it->second); + mDirectionalNbrs.erase (it); + } } //******************************************************************** // Fixed Contention functions -void SimpleWirelessNetDevice::ClearNbrCount(void) +void SimpleWirelessNetDevice::ClearNbrCount (void) { // When we clear the neighbor count, we actually set it to 1 and not 0 // because we always have to count ourselves. m_nbrCount = 1; } -void SimpleWirelessNetDevice::IncrementNbrCount(void) +void SimpleWirelessNetDevice::IncrementNbrCount (void) { m_nbrCount++; } -int SimpleWirelessNetDevice::GetNbrCount(void) +int SimpleWirelessNetDevice::GetNbrCount (void) { return m_nbrCount; } @@ -488,44 +494,44 @@ SimpleWirelessNetDevice::TransmitStart (Ptr p) NS_ASSERT_MSG (m_txMachineState == READY, "Must be READY to transmit"); m_txMachineState = BUSY; m_currentPkt = p; - + if (m_pcapEnabled) - { - m_promiscSnifferTrace (p); - } + { + m_promiscSnifferTrace (p); + } // Remove the timestamp tag. calculate queue latency and peg trace TimestampTag timeEnqueued; p->RemovePacketTag (timeEnqueued); - Time latency = Simulator::Now() - timeEnqueued.GetTimestamp(); - m_QueueLatencyTrace(p, latency); - NS_LOG_DEBUG (Simulator::Now() << " Getting packet with timestamp: " << timeEnqueued.GetTimestamp() ); - + Time latency = Simulator::Now () - timeEnqueued.GetTimestamp (); + m_QueueLatencyTrace (p, latency); + NS_LOG_DEBUG (Simulator::Now () << " Getting packet with timestamp: " << timeEnqueued.GetTimestamp () ); + // Remove ethernet header since it is not sent over the air // To this AFTER the queue latency trace in case the trace wants // to use anything in the Ethernet header EthernetHeader ethHeader; - p->RemoveHeader(ethHeader); + p->RemoveHeader (ethHeader); Mac48Address to = ethHeader.GetDestination (); Mac48Address from = ethHeader.GetSource (); uint16_t protocol = ethHeader.GetLengthType (); - - + + // Get dest Id tag. This could be the default NO_DIRECTIONAL_NBR DestinationIdTag destIdTag; p->RemovePacketTag (destIdTag); - uint32_t destId = destIdTag.GetDestinationId(); - + uint32_t destId = destIdTag.GetDestinationId (); + Time txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ())); - + // If we have a non-zero neighbor count then that means we are using contention and // the data rate changes. Note that when using contention, we will always have at least // a value of 1 for neighbor count because we count ourselves. - // If this device is omni then data rate changes to data rate/# neighbors. + // If this device is omni then data rate changes to data rate/# neighbors. // Thus multiply the tx time by the number of neighbors (which is the same as dividing the // data rate by # neighbors) // If this device is directional then the data rate is rate/2. Thus multiply the tx time by 2. - + // IMPORTANT NOTE: If we are using contention, the first packet we send may not "know" // that there is contention. This is a chicken and egg situation. // The device keeps the neighbor count (which is init'd to 0) but the channel is @@ -536,18 +542,18 @@ SimpleWirelessNetDevice::TransmitStart (Ptr p) // channel by the device is what will cause the device to get init'd for contention. That is // after the device set the txTime so that first packet will be sent at full data rate. if (m_nbrCount) - { - if (m_fixedNbrListEnabled) - { - txTime = txTime * 2; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << p->GetSize ()); - } - else - { - txTime = txTime * m_nbrCount; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << p->GetSize ()); - } - } + { + if (m_fixedNbrListEnabled) + { + txTime = txTime * 2; + NS_LOG_DEBUG ("Node " << m_node->GetId () << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << p->GetSize ()); + } + else + { + txTime = txTime * m_nbrCount; + NS_LOG_DEBUG ("Node " << m_node->GetId () << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << p->GetSize ()); + } + } // TO DO: do we need interframe gap?? //Time txCompleteTime = txTime + m_tInterframeGap; Time txCompleteTime = txTime; @@ -556,7 +562,7 @@ SimpleWirelessNetDevice::TransmitStart (Ptr p) Simulator::Schedule (txCompleteTime, &SimpleWirelessNetDevice::TransmitComplete, this); m_TxBeginTrace (p, from, to, protocol); - + m_channel->Send (p, protocol, to, from, this, txTime, destId); } @@ -574,9 +580,9 @@ SimpleWirelessNetDevice::TransmitComplete (void) NS_ASSERT_MSG (m_currentPkt != 0, "SimpleWirelessNetDevice::TransmitComplete(): m_currentPkt zero"); m_currentPkt = 0; - - NS_LOG_DEBUG (Simulator::Now() << " Tx complete. Packets in queue: " << m_queue->GetNPackets() << " Bytes in queue: " << m_queue->GetNBytes()); - + + NS_LOG_DEBUG (Simulator::Now () << " Tx complete. Packets in queue: " << m_queue->GetNPackets () << " Bytes in queue: " << m_queue->GetNBytes ()); + Ptr p = m_queue->Dequeue (); if (p == 0) @@ -590,14 +596,14 @@ SimpleWirelessNetDevice::TransmitComplete (void) } -bool -SimpleWirelessNetDevice::Send(Ptr packet, const Address& dest, uint16_t protocolNumber) +bool +SimpleWirelessNetDevice::Send (Ptr packet, const Address& dest, uint16_t protocolNumber) { NS_LOG_FUNCTION (packet << dest << protocolNumber); Mac48Address to = Mac48Address::ConvertFrom (dest); - - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " sending packet " << packet->GetUid () << " to " << to ); - + + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " sending packet " << packet->GetUid () << " to " << to ); + // For some reason the Ethernet header is STRIPPED from the packet // by the time we get here so we need to reconstruct it for for two reasons. // If queuing, add ethernet header to the packet in the queue so we can @@ -608,64 +614,64 @@ SimpleWirelessNetDevice::Send(Ptr packet, const Address& dest, uint16_t ethHeader.SetDestination (to); ethHeader.SetLengthType (protocolNumber); packet->AddHeader (ethHeader); - + m_macTxTrace (packet); - + // If directional networking is enabled, then we have to make a copy // of this packet and enqueue it for each destination. if (m_fixedNbrListEnabled) - { - std::map::iterator it; - - // Look up the dest address in the eth header of the packet. - // This is necessary because in directional networks, the dest - // could have been changed by the trace - packet->PeekHeader(ethHeader); - to = ethHeader.GetDestination(); - - if (to.IsBroadcast()) - { - NS_LOG_INFO ("Address " << to << " is broadcast"); - // broadcast packet. Enqueue for all of our directional neighbors - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + { + std::map::iterator it; + + // Look up the dest address in the eth header of the packet. + // This is necessary because in directional networks, the dest + // could have been changed by the trace + packet->PeekHeader (ethHeader); + to = ethHeader.GetDestination (); + + if (to.IsBroadcast ()) { - EnqueuePacket(packet->Copy(),m_address,to,protocolNumber,it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet to directional neighbor to node " << it->first); + NS_LOG_INFO ("Address " << to << " is broadcast"); + // broadcast packet. Enqueue for all of our directional neighbors + for ( it = mDirectionalNbrs.begin (); it != mDirectionalNbrs.end (); ++it) + { + EnqueuePacket (packet->Copy (),m_address,to,protocolNumber,it->first); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " queueing packet to directional neighbor to node " << it->first); + } } - } - else - { - NS_LOG_INFO ("Address " << to << " is NOT broadcast"); - // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + else { - if (it->second == to) - { - EnqueuePacket(packet->Copy(),m_address,to,protocolNumber, it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " found node " << it->first << " with matching Mac Address " << to); - break; - } + NS_LOG_INFO ("Address " << to << " is NOT broadcast"); + // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) + for ( it = mDirectionalNbrs.begin (); it != mDirectionalNbrs.end (); ++it) + { + if (it->second == to) + { + EnqueuePacket (packet->Copy (),m_address,to,protocolNumber, it->first); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " found node " << it->first << " with matching Mac Address " << to); + break; + } + } } - } - } + } else - { - EnqueuePacket(packet,m_address,to,protocolNumber, NO_DIRECTIONAL_NBR); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet"); - } - + { + EnqueuePacket (packet,m_address,to,protocolNumber, NO_DIRECTIONAL_NBR); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " queueing packet"); + } + return true; } -bool -SimpleWirelessNetDevice::SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) +bool +SimpleWirelessNetDevice::SendFrom (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) { NS_LOG_FUNCTION (packet << dest << protocolNumber); Mac48Address to = Mac48Address::ConvertFrom (dest); Mac48Address from = Mac48Address::ConvertFrom (source); - + // For some reason the Ethernet header is STRIPPED from the packet // by the time we get here so we need to reconstruct it for for two reasons. // If queuing, add ethernet header to the packet in the queue so we can @@ -676,147 +682,147 @@ SimpleWirelessNetDevice::SendFrom(Ptr packet, const Address& source, con ethHeader.SetDestination (to); ethHeader.SetLengthType (protocolNumber); packet->AddHeader (ethHeader); - + m_macTxTrace (packet); - + // If directional networking is enabled, then we have to make a copy // of this packet and enqueue it for each destination. if (m_fixedNbrListEnabled) - { - std::map::iterator it; - - // Look up the dest address in the eth header of the packet. - // This is necessary because in directional networks, the dest - // could have been changed by the trace - packet->PeekHeader(ethHeader); - to = ethHeader.GetDestination(); - - if (to.IsBroadcast()) - { - NS_LOG_INFO ("Address " << to << " is broadcast"); - // broadcast packet. Enqueue for all of our directional neighbors - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + { + std::map::iterator it; + + // Look up the dest address in the eth header of the packet. + // This is necessary because in directional networks, the dest + // could have been changed by the trace + packet->PeekHeader (ethHeader); + to = ethHeader.GetDestination (); + + if (to.IsBroadcast ()) { - // Note that we do not alter the to (mac address) here but instead specify - // the node id as the destination. This gets carried with the packet - // as a destination tag and passed to the channel. At the channel it still - // appears as a broadcast packet but the channel only uses the dest id so it - // will know how to handle it from the perspective of directional networking. - EnqueuePacket(packet->Copy(),from,to,protocolNumber,it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet to directional neighbor to node " << it->first); + NS_LOG_INFO ("Address " << to << " is broadcast"); + // broadcast packet. Enqueue for all of our directional neighbors + for ( it = mDirectionalNbrs.begin (); it != mDirectionalNbrs.end (); ++it) + { + // Note that we do not alter the to (mac address) here but instead specify + // the node id as the destination. This gets carried with the packet + // as a destination tag and passed to the channel. At the channel it still + // appears as a broadcast packet but the channel only uses the dest id so it + // will know how to handle it from the perspective of directional networking. + EnqueuePacket (packet->Copy (),from,to,protocolNumber,it->first); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " queueing packet to directional neighbor to node " << it->first); + } } - } - else - { - NS_LOG_INFO ("Address " << to << " is NOT broadcast"); - // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) - for ( it = mDirectionalNbrs.begin(); it != mDirectionalNbrs.end(); ++it) + else { - if (it->second == to) - { - EnqueuePacket(packet->Copy(),from,to,protocolNumber, it->first); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " found node " << it->first << " with matching Mac Address " << to); - break; - } + NS_LOG_INFO ("Address " << to << " is NOT broadcast"); + // unicast packet. Find the directional neighbor with matching MAC address. (There might not be one) + for ( it = mDirectionalNbrs.begin (); it != mDirectionalNbrs.end (); ++it) + { + if (it->second == to) + { + EnqueuePacket (packet->Copy (),from,to,protocolNumber, it->first); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " found node " << it->first << " with matching Mac Address " << to); + break; + } + } } - } - } + } else - { - EnqueuePacket(packet,from,to,protocolNumber, NO_DIRECTIONAL_NBR); - NS_LOG_INFO ("Node " << this->GetNode()->GetId() << " queueing packet"); - } - + { + EnqueuePacket (packet,from,to,protocolNumber, NO_DIRECTIONAL_NBR); + NS_LOG_INFO ("Node " << this->GetNode ()->GetId () << " queueing packet"); + } + return true; - + } -bool +bool SimpleWirelessNetDevice::EnqueuePacket (Ptr packet, Mac48Address from, Mac48Address to, uint16_t protocolNumber, uint32_t destId) { - + if (m_queue) - { - // We are using queueing. - - // Add a timestamp tag for latency - TimestampTag timestamp; - timestamp.SetTimestamp (Simulator::Now ()); - packet->AddPacketTag (timestamp); - - // add destination tag - DestinationIdTag idTag(destId); - packet->AddPacketTag (idTag); - - NS_LOG_DEBUG ("Queueing packet for destination " << destId << ". Protocol "<< protocolNumber << " Current state is: " << m_txMachineState); - - // We should enqueue and dequeue the packet to hit the tracing hooks. - if (m_queue->Enqueue (packet)) { - // If the channel is ready for transition we send the packet right now - if (m_txMachineState == READY) + // We are using queueing. + + // Add a timestamp tag for latency + TimestampTag timestamp; + timestamp.SetTimestamp (Simulator::Now ()); + packet->AddPacketTag (timestamp); + + // add destination tag + DestinationIdTag idTag (destId); + packet->AddPacketTag (idTag); + + NS_LOG_DEBUG ("Queueing packet for destination " << destId << ". Protocol " << protocolNumber << " Current state is: " << m_txMachineState); + + // We should enqueue and dequeue the packet to hit the tracing hooks. + if (m_queue->Enqueue (packet)) { - packet = m_queue->Dequeue (); - TransmitStart (packet); + // If the channel is ready for transition we send the packet right now + if (m_txMachineState == READY) + { + packet = m_queue->Dequeue (); + TransmitStart (packet); + } + return true; } - return true; + + // TO DO: do we return true or false here?? + return true; } - - // TO DO: do we return true or false here?? - return true; - } else - { - // No queuing is being used. Just send the packet. - if (m_pcapEnabled) - { - m_promiscSnifferTrace (packet); - } - EthernetHeader ethHeader; - packet->RemoveHeader(ethHeader); - - m_TxBeginTrace (packet, m_address, to, protocolNumber); - Time txTime = Seconds (m_bps.CalculateTxTime (packet->GetSize ())); - // If we have a non-zero neighbor count then that means we are using contention and - // the data rate changes. - if (m_nbrCount) - { - if (m_fixedNbrListEnabled) + { + // No queuing is being used. Just send the packet. + if (m_pcapEnabled) { - txTime = txTime * 2; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << packet->GetSize ()); + m_promiscSnifferTrace (packet); } - else + EthernetHeader ethHeader; + packet->RemoveHeader (ethHeader); + + m_TxBeginTrace (packet, m_address, to, protocolNumber); + Time txTime = Seconds (m_bps.CalculateTxTime (packet->GetSize ())); + // If we have a non-zero neighbor count then that means we are using contention and + // the data rate changes. + if (m_nbrCount) { - txTime = txTime * m_nbrCount; - NS_LOG_DEBUG ("Node " << m_node->GetId() << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << packet->GetSize ()); + if (m_fixedNbrListEnabled) + { + txTime = txTime * 2; + NS_LOG_DEBUG ("Node " << m_node->GetId () << " txTime was increased to " << txTime << " because we have directonal neighbors. packet size is " << packet->GetSize ()); + } + else + { + txTime = txTime * m_nbrCount; + NS_LOG_DEBUG ("Node " << m_node->GetId () << " txTime was increased to " << txTime << " because we have " << m_nbrCount << " neighbors. packet size is " << packet->GetSize ()); + } } - } - m_channel->Send (packet, protocolNumber, to, from, this, txTime, destId); - return true; - } + m_channel->Send (packet, protocolNumber, to, from, this, txTime, destId); + return true; + } } -Ptr +Ptr SimpleWirelessNetDevice::GetNode (void) const { return m_node; } -void +void SimpleWirelessNetDevice::SetNode (Ptr node) { m_node = node; } -bool +bool SimpleWirelessNetDevice::NeedsArp (void) const { return true; } -void +void SimpleWirelessNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb) { m_rxCallback = cb; @@ -860,7 +866,7 @@ SimpleWirelessNetDevice::SetQueue (Ptr q) Ptr SimpleWirelessNetDevice::GetQueue (void) const -{ +{ NS_LOG_FUNCTION_NOARGS (); return m_queue; } @@ -868,10 +874,10 @@ SimpleWirelessNetDevice::GetQueue (void) const void SimpleWirelessNetDevice::EnablePcapAll (std::string filename) { - PcapHelper pcapHelper; - Ptr file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_EN10MB); - pcapHelper.HookDefaultSink (this, "PromiscSniffer", file); - m_pcapEnabled = true; + PcapHelper pcapHelper; + Ptr file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_EN10MB); + pcapHelper.HookDefaultSink (this, "PromiscSniffer", file); + m_pcapEnabled = true; } } // namespace ns3 diff --git a/model/simple-wireless-net-device.h b/model/simple-wireless-net-device.h index ea0729d..c459f67 100644 --- a/model/simple-wireless-net-device.h +++ b/model/simple-wireless-net-device.h @@ -48,7 +48,8 @@ class ErrorModel; // TimestampTag used to store a timestamp with a packet // when they are placed in the queue //******************************************************** -class TimestampTag : public Tag { +class TimestampTag : public Tag +{ public: static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; @@ -71,11 +72,12 @@ class TimestampTag : public Tag { //******************************************************** -// DestinationIdTag used to store a destination node id -// with a packet when they are placed in the queue. +// DestinationIdTag used to store a destination node id +// with a packet when they are placed in the queue. // This is used by directional networks. //******************************************************** -class DestinationIdTag : public Tag { +class DestinationIdTag : public Tag +{ public: static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; @@ -83,8 +85,8 @@ class DestinationIdTag : public Tag { virtual uint32_t GetSerializedSize (void) const; virtual void Serialize (TagBuffer i) const; virtual void Deserialize (TagBuffer i); - DestinationIdTag(); - + DestinationIdTag (); + /** * Constructs a DestinationIdTag with the given node id * @@ -110,10 +112,10 @@ class DestinationIdTag : public Tag { * \ingroup netdevice * * This device does not have a helper and assumes 48-bit mac addressing; - * the default address assigned to each device is zero, so you must + * the default address assigned to each device is zero, so you must * assign a real address to use it. There is also the possibility to * add an ErrorModel if you want to force losses on the device. - * + * * \brief simple net device for simple things and testing */ class SimpleWirelessNetDevice : public NetDevice @@ -134,8 +136,8 @@ class SimpleWirelessNetDevice : public NetDevice * \see ErrorModel * \param em Ptr to the ErrorModel. */ - void SetReceiveErrorModel(Ptr em); - + void SetReceiveErrorModel (Ptr em); + /** * Set the Data Rate used for transmission of packets. The data rate is * set in the Attach () method from the corresponding field in the channel @@ -145,17 +147,17 @@ class SimpleWirelessNetDevice : public NetDevice * @param bps the data rate at which this object operates */ void SetDataRate (DataRate bps); - - /** - * Attach a queue to the PointToPointNetDevice. - * - * The PointToPointNetDevice "owns" a queue that implements a queueing - * method such as DropTail or RED. - * - * @see Queue - * @see DropTailQueue - * @param queue Ptr to the new queue. - */ + + /** + * Attach a queue to the PointToPointNetDevice. + * + * The PointToPointNetDevice "owns" a queue that implements a queueing + * method such as DropTail or RED. + * + * @see Queue + * @see DropTailQueue + * @param queue Ptr to the new queue. + */ void SetQueue (Ptr queue); /** @@ -164,26 +166,26 @@ class SimpleWirelessNetDevice : public NetDevice * @returns Ptr to the queue. */ Ptr GetQueue (void) const; - + //****************************************** // Directional Neighbor functions - bool AddDirectionalNeighbors(std::map nodesToAdd); - bool AddDirectionalNeighbor(uint32_t nodeid, Mac48Address macAddr); - void DeleteDirectionalNeighbors(std::set nodeids); - void DeleteDirectionalNeighbor(uint32_t nodeid); - + bool AddDirectionalNeighbors (std::map nodesToAdd); + bool AddDirectionalNeighbor (uint32_t nodeid, Mac48Address macAddr); + void DeleteDirectionalNeighbors (std::set nodeids); + void DeleteDirectionalNeighbor (uint32_t nodeid); + //****************************************** // Fixed Contention functions - void ClearNbrCount(void); - void IncrementNbrCount(void); - int GetNbrCount(void); + void ClearNbrCount (void); + void IncrementNbrCount (void); + int GetNbrCount (void); - - void EnablePcapAll(std::string filename); + + void EnablePcapAll (std::string filename); // inherited from NetDevice base class. - virtual void SetIfIndex(const uint32_t index); - virtual uint32_t GetIfIndex(void) const; + virtual void SetIfIndex (const uint32_t index); + virtual uint32_t GetIfIndex (void) const; virtual Ptr GetChannel (void) const; virtual void SetAddress (Address address); virtual Address GetAddress (void) const; @@ -197,13 +199,13 @@ class SimpleWirelessNetDevice : public NetDevice virtual Address GetMulticast (Ipv4Address multicastGroup) const; virtual bool IsPointToPoint (void) const; virtual bool IsBridge (void) const; - virtual bool Send(Ptr packet, const Address& dest, uint16_t protocolNumber); - virtual bool SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); + virtual bool Send (Ptr packet, const Address& dest, uint16_t protocolNumber); + virtual bool SendFrom (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); virtual Ptr GetNode (void) const; virtual void SetNode (Ptr node); virtual bool NeedsArp (void) const; virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb); - virtual bool EnqueuePacket(Ptr packet, Mac48Address from, Mac48Address to, uint16_t protocolNumber, uint32_t destId); + virtual bool EnqueuePacket (Ptr packet, Mac48Address from, Mac48Address to, uint16_t protocolNumber, uint32_t destId); virtual Address GetMulticast (Ipv6Address addr) const; @@ -221,19 +223,19 @@ class SimpleWirelessNetDevice : public NetDevice uint32_t m_ifIndex; Mac48Address m_address; Ptr m_receiveErrorModel; - + Ptr m_currentPkt; - - /** - * Start Sending a Packet Down the Wire. - * - * The TransmitStart method is the method that is used internally in the - * NetDevice to begin the process of sending a packet out on - * the channel. The corresponding method is called on the channel to let - * it know that the physical device this class represents has virtually - * started sending signals. An event is scheduled for the time at which - * the bits have been completely transmitted. - */ + + /** + * Start Sending a Packet Down the Wire. + * + * The TransmitStart method is the method that is used internally in the + * NetDevice to begin the process of sending a packet out on + * the channel. The corresponding method is called on the channel to let + * it know that the physical device this class represents has virtually + * started sending signals. An event is scheduled for the time at which + * the bits have been completely transmitted. + */ void TransmitStart (Ptr); /** @@ -258,22 +260,22 @@ class SimpleWirelessNetDevice : public NetDevice */ TxMachineState m_txMachineState; - - /** - * The data rate that the Net Device uses to simulate packet transmission - * timing. - * @see class DataRate - */ + + /** + * The data rate that the Net Device uses to simulate packet transmission + * timing. + * @see class DataRate + */ DataRate m_bps; - - /** - * The Queue which this device uses as a packet source. - * Management of this Queue has been delegated to the device - * and it has the responsibility for deletion. - * @see class Queue - * @see class DropTailQueue - */ - Ptr m_queue; + + /** + * The Queue which this device uses as a packet source. + * Management of this Queue has been delegated to the device + * and it has the responsibility for deletion. + * @see class Queue + * @see class DropTailQueue + */ + Ptr m_queue; /** * The trace source fired when a packet begins the reception process from @@ -293,7 +295,7 @@ class SimpleWirelessNetDevice : public NetDevice /** * The trace source fired when the phy layer drops a packet it has received - * due to the error model being active. Although SimpleWirelessNetDevice doesn't + * due to the error model being active. Although SimpleWirelessNetDevice doesn't * really have a Phy model, we choose this trace source name for alignment * with other trace sources. * @@ -311,7 +313,7 @@ class SimpleWirelessNetDevice : public NetDevice * \see class CallBackTraceSource */ TracedCallback > m_promiscSnifferTrace; - + /** * The trace source fired when a packet begins the transmission process on * the medium. @@ -319,7 +321,7 @@ class SimpleWirelessNetDevice : public NetDevice * \see class CallBackTraceSource */ TracedCallback, Mac48Address, Mac48Address, uint16_t > m_TxBeginTrace; - + /** * The trace source fired when a packet is dequeued to be sent. * It does NOT track queue latency for packets that get dropped @@ -328,7 +330,7 @@ class SimpleWirelessNetDevice : public NetDevice * \see class CallBackTraceSource */ TracedCallback, Time> m_QueueLatencyTrace; - + /** * The trace source fired when packets come into the "top" of the device * at the L3/L2 transition, before being queued for transmission. @@ -336,7 +338,7 @@ class SimpleWirelessNetDevice : public NetDevice * \see class CallBackTraceSource */ TracedCallback > m_macTxTrace; - + /** * The trace source fired for packets successfully received by the device * immediately before being forwarded up to higher layers (at the L2/L3 @@ -346,14 +348,14 @@ class SimpleWirelessNetDevice : public NetDevice */ TracedCallback > m_macRxTrace; - + uint32_t m_pktRcvTotal; uint32_t m_pktRcvDrop; bool m_pcapEnabled; - + bool m_fixedNbrListEnabled; std::map mDirectionalNbrs; - + int m_nbrCount; }; From 47893a36a5b473b045950c151d8be9e124d86664 Mon Sep 17 00:00:00 2001 From: Wisheighz Nsunza Jnr Date: Fri, 28 Sep 2018 13:06:44 -0700 Subject: [PATCH 3/8] Update files to ns-3.29 API --- examples/directional_test.cc | 2 +- examples/fixed_contention_test.cc | 2 +- examples/queue_test.cc | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/directional_test.cc b/examples/directional_test.cc index cf106b8..76bb180 100644 --- a/examples/directional_test.cc +++ b/examples/directional_test.cc @@ -426,7 +426,7 @@ main (int argc, char *argv[]) Ptr dev = devices.Get (0); PointerValue val; dev->GetAttribute ("TxQueue", val); - Ptr queue = val.Get(); + Ptr> queue = val.Get>(); Ptr dropHead = DynamicCast (queue); std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets () << std::endl; diff --git a/examples/fixed_contention_test.cc b/examples/fixed_contention_test.cc index e292e95..a8d8e25 100644 --- a/examples/fixed_contention_test.cc +++ b/examples/fixed_contention_test.cc @@ -386,7 +386,7 @@ main (int argc, char *argv[]) Ptr dev = devices.Get (0); PointerValue val; dev->GetAttribute ("TxQueue", val); - Ptr queue = val.Get(); + Ptr> queue = val.Get>(); Ptr dropHead = DynamicCast (queue); std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets () << std::endl; diff --git a/examples/queue_test.cc b/examples/queue_test.cc index 65b0c97..8fc9ece 100644 --- a/examples/queue_test.cc +++ b/examples/queue_test.cc @@ -253,7 +253,7 @@ main (int argc, char *argv[]) { Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); simpleWireless->SetQueue (queue); } else if (queueType == "PriorityHead") @@ -274,8 +274,8 @@ main (int argc, char *argv[]) Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); - Ptr controlQueue = CreateObject (); - Ptr dataQueue = CreateObject (); + Ptr> controlQueue = CreateObject> (); + Ptr> dataQueue = CreateObject> (); Ptr queue = CreateObject (); queue->Initialize (); queue->SetControlQueue (controlQueue); From ef1436a2c7c61138a39126f86e379ffca8ef62dd Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sun, 30 Sep 2018 20:03:24 -0700 Subject: [PATCH 4/8] Additional updates to align with ns-3.29 --- examples/directional_test.cc | 7 +- examples/fixed_contention_test.cc | 7 +- examples/mixed_directional_network.cc | 10 +- examples/multiple_interface_example.cc | 8 +- examples/queue_test.cc | 24 ++- examples/wscript | 13 +- model/drop-head-queue.cc | 134 +------------- model/drop-head-queue.h | 128 +++++++++---- model/priority-queue.cc | 167 +---------------- model/priority-queue.h | 237 +++++++++++++++++++++++-- model/simple-wireless-channel.cc | 4 +- model/simple-wireless-channel.h | 4 +- model/simple-wireless-net-device.cc | 31 ++-- model/simple-wireless-net-device.h | 24 ++- 14 files changed, 393 insertions(+), 405 deletions(-) diff --git a/examples/directional_test.cc b/examples/directional_test.cc index 76bb180..e6a4a8c 100644 --- a/examples/directional_test.cc +++ b/examples/directional_test.cc @@ -243,9 +243,8 @@ main (int argc, char *argv[]) std::cout << "node id " << node->GetId () << " has macAddress of " << simpleWireless->GetAddress () << std::endl; // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless->SetQueue (queue); // Set up trace to pass node id on the RX end @@ -427,7 +426,7 @@ main (int argc, char *argv[]) PointerValue val; dev->GetAttribute ("TxQueue", val); Ptr> queue = val.Get>(); - Ptr dropHead = DynamicCast (queue); + Ptr> dropHead = DynamicCast> (queue); std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets () << std::endl; for (int i = 1; i < NUM_NODES; i++) diff --git a/examples/fixed_contention_test.cc b/examples/fixed_contention_test.cc index a8d8e25..6bf7b00 100644 --- a/examples/fixed_contention_test.cc +++ b/examples/fixed_contention_test.cc @@ -227,9 +227,8 @@ main (int argc, char *argv[]) simpleWireless->SetAddress (Mac48Address::Allocate ()); simpleWireless->SetDataRate ((DataRate (dataRate))); - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless->SetQueue (queue); // Set up trace to pass node id on the RX end @@ -387,7 +386,7 @@ main (int argc, char *argv[]) PointerValue val; dev->GetAttribute ("TxQueue", val); Ptr> queue = val.Get>(); - Ptr dropHead = DynamicCast (queue); + Ptr> dropHead = DynamicCast> (queue); std::cout << "Packets Dropped at Queue on Node 0: " << dropHead->GetTotalDroppedPackets () << std::endl; for (int i = 1; i < NUM_NODES; i++) diff --git a/examples/mixed_directional_network.cc b/examples/mixed_directional_network.cc index f76af88..9689c0e 100644 --- a/examples/mixed_directional_network.cc +++ b/examples/mixed_directional_network.cc @@ -135,9 +135,8 @@ main (int argc, char *argv[]) simpleWireless1->SetDataRate ((DataRate (dataRate))); // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless1->SetQueue (queue); node->AddDevice (simpleWireless1); @@ -170,9 +169,8 @@ main (int argc, char *argv[]) std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress () << std::endl; // Set queue type to use - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless2->SetQueue (queue); node->AddDevice (simpleWireless2); diff --git a/examples/multiple_interface_example.cc b/examples/multiple_interface_example.cc index 0169d31..409621e 100644 --- a/examples/multiple_interface_example.cc +++ b/examples/multiple_interface_example.cc @@ -129,8 +129,6 @@ main (int argc, char *argv[]) // *********************************************************************** // create first network - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); Config::SetDefault ("ns3::SimpleWirelessChannel::MaxRange", DoubleValue (100.0)); // channel @@ -151,7 +149,8 @@ main (int argc, char *argv[]) simpleWireless1->SetDataRate ((DataRate (dataRate))); // create queue type - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless1->SetQueue (queue); node->AddDevice (simpleWireless1); @@ -179,7 +178,8 @@ main (int argc, char *argv[]) std::cout << "node id " << id << " has macAddress of " << simpleWireless2->GetAddress () << std::endl; // create queue type - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless2->SetQueue (queue); if (id == 0) diff --git a/examples/queue_test.cc b/examples/queue_test.cc index 8fc9ece..242597e 100644 --- a/examples/queue_test.cc +++ b/examples/queue_test.cc @@ -244,26 +244,24 @@ main (int argc, char *argv[]) // Set queue type to use. Set nothing if NoQueue if (queueType == "DropHead") { - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr queue = CreateObject (); + Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless->SetQueue (queue); } else if (queueType == "DropTail") { - Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); Ptr> queue = CreateObject> (); + queue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); simpleWireless->SetQueue (queue); } else if (queueType == "PriorityHead") { Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); - Config::SetDefault ("ns3::DropHeadQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropHeadQueue::MaxPackets", UintegerValue (100)); - Ptr controlQueue = CreateObject (); - Ptr dataQueue = CreateObject (); - Ptr queue = CreateObject (); + Ptr> controlQueue = CreateObject> (); + controlQueue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); + Ptr> dataQueue = CreateObject> (); + dataQueue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); + Ptr> queue = CreateObject> (); queue->Initialize (); queue->SetControlQueue (controlQueue); queue->SetDataQueue (dataQueue); @@ -272,11 +270,11 @@ main (int argc, char *argv[]) else if (queueType == "PriorityTail") { Config::SetDefault ("ns3::PriorityQueue::ControlPacketClassifier", StringValue ("port 698")); - Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("QUEUE_MODE_PACKETS")); - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (100)); Ptr> controlQueue = CreateObject> (); + controlQueue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); Ptr> dataQueue = CreateObject> (); - Ptr queue = CreateObject (); + dataQueue->SetMaxSize (QueueSize (QueueSizeUnit::PACKETS, 100)); + Ptr> queue = CreateObject> (); queue->Initialize (); queue->SetControlQueue (controlQueue); queue->SetDataQueue (dataQueue); diff --git a/examples/wscript b/examples/wscript index a514ab7..59b1617 100644 --- a/examples/wscript +++ b/examples/wscript @@ -23,26 +23,27 @@ def build(bld): return; obj = bld.create_ns3_program('queue_test', - ['core', 'mobility', 'network', 'internet', 'olsr', 'simple-wireless']) + ['core', 'mobility', 'network', 'internet', 'olsr', 'applications', 'simple-wireless']) obj.source = 'queue_test.cc' + obj.env.append_value("LIB", ["pcap"]) obj = bld.create_ns3_program('directional_test', - ['core', 'mobility', 'network', 'internet', 'olsr', 'simple-wireless']) + ['core', 'mobility', 'network', 'internet', 'olsr', 'applications', 'simple-wireless']) obj.source = 'directional_test.cc' obj = bld.create_ns3_program('mixed_directional_network', - ['core', 'mobility', 'network', 'internet', 'olsr', 'simple-wireless']) + ['core', 'mobility', 'network', 'internet', 'olsr', 'applications', 'simple-wireless']) obj.source = 'mixed_directional_network.cc' obj = bld.create_ns3_program('multiple_interface_example', - ['core', 'mobility', 'network', 'internet', 'olsr', 'simple-wireless']) + ['core', 'mobility', 'network', 'internet', 'olsr', 'applications', 'simple-wireless']) obj.source = 'multiple_interface_example.cc' obj = bld.create_ns3_program('fixed_contention_test', - ['core', 'mobility', 'network', 'internet', 'olsr', 'simple-wireless']) + ['core', 'mobility', 'network', 'internet', 'olsr', 'applications', 'simple-wireless']) obj.source = 'fixed_contention_test.cc' obj = bld.create_ns3_program('error_model_test', - ['core', 'mobility', 'network', 'internet', 'olsr', 'simple-wireless']) + ['core', 'mobility', 'network', 'internet', 'olsr', 'applications', 'simple-wireless']) obj.source = 'error_model_test.cc' diff --git a/model/drop-head-queue.cc b/model/drop-head-queue.cc index 07a8547..44262a9 100644 --- a/model/drop-head-queue.cc +++ b/model/drop-head-queue.cc @@ -1,6 +1,5 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (C) 2015 Massachusetts Institute of Technology * Copyright (c) 2007 University of Washington * * This program is free software; you can redistribute it and/or modify @@ -17,143 +16,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ns3/log.h" -#include "ns3/enum.h" -#include "ns3/uinteger.h" #include "drop-head-queue.h" namespace ns3 { NS_LOG_COMPONENT_DEFINE ("DropHeadQueue"); -NS_OBJECT_ENSURE_REGISTERED (DropHeadQueue); - -TypeId DropHeadQueue::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::DropHeadQueue") - .SetParent () - .AddConstructor () - .AddAttribute ("Mode", - "Whether to use bytes (see MaxBytes) or packets (see MaxPackets) as the maximum queue size metric.", - EnumValue (QUEUE_MODE_PACKETS), - MakeEnumAccessor (&DropHeadQueue::SetMode), - MakeEnumChecker (QUEUE_MODE_BYTES, "QUEUE_MODE_BYTES", - QUEUE_MODE_PACKETS, "QUEUE_MODE_PACKETS")) - .AddAttribute ("MaxPackets", - "The maximum number of packets accepted by this DropHeadQueue.", - UintegerValue (100), - MakeUintegerAccessor (&DropHeadQueue::m_maxPackets), - MakeUintegerChecker ()) - .AddAttribute ("MaxBytes", - "The maximum number of bytes accepted by this DropHeadQueue.", - UintegerValue (100 * 65535), - MakeUintegerAccessor (&DropHeadQueue::m_maxBytes), - MakeUintegerChecker ()) - ; - - return tid; -} - -DropHeadQueue::DropHeadQueue () : - Queue (), - m_packets (), - m_bytesInQueue (0) -{ - NS_LOG_FUNCTION (this); -} - -DropHeadQueue::~DropHeadQueue () -{ - NS_LOG_FUNCTION (this); -} - -void -DropHeadQueue::SetMode (DropHeadQueue::QueueMode mode) -{ - NS_LOG_FUNCTION (this << mode); - m_mode = mode; -} - -DropHeadQueue::QueueMode -DropHeadQueue::GetMode (void) -{ - NS_LOG_FUNCTION (this); - return m_mode; -} - -bool -DropHeadQueue::DoEnqueue (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - - if (m_mode == QUEUE_MODE_PACKETS && (m_packets.size () >= m_maxPackets)) - { - NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt"); - Ptr head_packet = Dequeue (); - Drop (head_packet); - } - - if (m_mode == QUEUE_MODE_BYTES) - { - // Drop packets from head of queue until enough bytes is available - while (m_bytesInQueue + p->GetSize () >= m_maxBytes) - { - NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- droppping pkt"); - Ptr head_packet = Dequeue (); - Drop (head_packet); - } - } - - m_bytesInQueue += p->GetSize (); - m_packets.push (p); - - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - - return true; -} - -Ptr -DropHeadQueue::DoDequeue (void) -{ - NS_LOG_FUNCTION (this); - - if (m_packets.empty ()) - { - NS_LOG_LOGIC ("Queue empty"); - return 0; - } - - Ptr p = m_packets.front (); - m_packets.pop (); - m_bytesInQueue -= p->GetSize (); - - NS_LOG_LOGIC ("Popped " << p); - - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - - return p; -} - -Ptr -DropHeadQueue::DoPeek (void) const -{ - NS_LOG_FUNCTION (this); - - if (m_packets.empty ()) - { - NS_LOG_LOGIC ("Queue empty"); - return 0; - } - - Ptr p = m_packets.front (); - - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - - return p; -} +NS_OBJECT_TEMPLATE_CLASS_DEFINE (DropHeadQueue,Packet); } // namespace ns3 - diff --git a/model/drop-head-queue.h b/model/drop-head-queue.h index d11c4d4..08d9ccb 100644 --- a/model/drop-head-queue.h +++ b/model/drop-head-queue.h @@ -1,6 +1,5 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (C) 2015 Massachusetts Institute of Technology * Copyright (c) 2007 University of Washington * * This program is free software; you can redistribute it and/or modify @@ -17,23 +16,20 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef DROPHEAD_H -#define DROPHEAD_H +#ifndef DROP_HEAD_QUEUE_H +#define DROP_HEAD_QUEUE_H -#include -#include "ns3/packet.h" #include "ns3/queue.h" namespace ns3 { -class TraceContainer; - /** * \ingroup queue * - * \brief A FIFO packet queue that drops head-end packets on overflow + * \brief A FIFO packet queue that drops packets at the head of the queue on overflow */ -class DropHeadQueue : public Queue +template +class DropHeadQueue : public Queue { public: /** @@ -44,39 +40,103 @@ class DropHeadQueue : public Queue /** * \brief DropHeadQueue Constructor * - * Creates a drophead queue with a maximum size of 100 packets by default + * Creates a droptail queue with a maximum size of 100 packets by default */ DropHeadQueue (); virtual ~DropHeadQueue (); - /** - * Set the operating mode of this device. - * - * \param mode The operating mode of this device. - * - */ - void SetMode (DropHeadQueue::QueueMode mode); - - /** - * Get the encapsulation mode of this device. - * - * \returns The encapsulation mode of this device. - */ - DropHeadQueue::QueueMode GetMode (void); + virtual bool Enqueue (Ptr item); + virtual Ptr Dequeue (void); + virtual Ptr Remove (void); + virtual Ptr Peek (void) const; private: - virtual bool DoEnqueue (Ptr p); - virtual Ptr DoDequeue (void); - virtual Ptr DoPeek (void) const; - - std::queue > m_packets; //!< the packets in the queue - uint32_t m_maxPackets; //!< max packets in the queue - uint32_t m_maxBytes; //!< max bytes in the queue - uint32_t m_bytesInQueue; //!< actual bytes in the queue - QueueMode m_mode; //!< queue mode (packets or bytes limited) + using Queue::Head; + using Queue::Tail; + using Queue::DoEnqueue; + using Queue::DoDequeue; + using Queue::DoRemove; + using Queue::DoPeek; + + NS_LOG_TEMPLATE_DECLARE; //!< redefinition of the log component }; + +/** + * Implementation of the templates declared above. + */ + +template +TypeId +DropHeadQueue::GetTypeId (void) +{ + static TypeId tid = TypeId (("ns3::DropHeadQueue<" + GetTypeParamName > () + ">").c_str ()) + .SetParent > () + .SetGroupName ("Network") + .template AddConstructor > () + ; + return tid; +} + +template +DropHeadQueue::DropHeadQueue () : + Queue (), + NS_LOG_TEMPLATE_DEFINE ("DropHeadQueue") +{ + NS_LOG_FUNCTION (this); +} + +template +DropHeadQueue::~DropHeadQueue () +{ + NS_LOG_FUNCTION (this); +} + +template +bool +DropHeadQueue::Enqueue (Ptr item) +{ + NS_LOG_FUNCTION (this << item); + + return DoEnqueue (Tail (), item); +} + +template +Ptr +DropHeadQueue::Dequeue (void) +{ + NS_LOG_FUNCTION (this); + + Ptr item = DoDequeue (Head ()); + + NS_LOG_LOGIC ("Popped " << item); + + return item; +} + +template +Ptr +DropHeadQueue::Remove (void) +{ + NS_LOG_FUNCTION (this); + + Ptr item = DoRemove (Head ()); + + NS_LOG_LOGIC ("Removed " << item); + + return item; +} + +template +Ptr +DropHeadQueue::Peek (void) const +{ + NS_LOG_FUNCTION (this); + + return DoPeek (Head ()); +} + } // namespace ns3 -#endif /* DROPHEAD_H */ +#endif /* DROP_HEAD_QUEUE_H */ diff --git a/model/priority-queue.cc b/model/priority-queue.cc index 72a7305..0eb6148 100644 --- a/model/priority-queue.cc +++ b/model/priority-queue.cc @@ -17,177 +17,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ns3/log.h" -#include "ns3/enum.h" -#include "ns3/string.h" -#include "ns3/pointer.h" -#include "ns3/uinteger.h" #include "priority-queue.h" namespace ns3 { NS_LOG_COMPONENT_DEFINE ("PriorityQueue"); -NS_OBJECT_ENSURE_REGISTERED (PriorityQueue); - -TypeId PriorityQueue::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::PriorityQueue") - .SetParent () - .AddConstructor () - - .AddAttribute ("ControlQueue", - "A queue to use as the transmit queue in the device.", - PointerValue (), - MakePointerAccessor (&PriorityQueue::m_controlQueue), - MakePointerChecker ()) - .AddAttribute ("DataQueue", - "A queue to use as the transmit queue in the device.", - PointerValue (), - MakePointerAccessor (&PriorityQueue::m_dataQueue), - MakePointerChecker ()) - .AddAttribute ("ControlPacketClassifier", - "Pcap style filter to classify control packets", - StringValue (), - MakeStringAccessor (&PriorityQueue::m_classifier), - MakeStringChecker ()) - ; - - return tid; -} - -PriorityQueue::PriorityQueue () : - Queue () -{ - NS_LOG_FUNCTION (this); - - m_pcapHandle = pcap_open_dead (DLT_EN10MB, 1500); - NS_ASSERT_MSG (m_pcapHandle, "failed to open pcap handle"); -} - -PriorityQueue::~PriorityQueue () -{ - NS_LOG_FUNCTION (this); - - m_controlQueue = 0; - m_dataQueue = 0; - - pcap_close (m_pcapHandle); -} - -void -PriorityQueue::Initialize () -{ - NS_LOG_FUNCTION (this); - - int ret = pcap_compile (m_pcapHandle, &m_bpf, - m_classifier.c_str (), 1, PCAP_NETMASK_UNKNOWN); - NS_ASSERT_MSG (ret == 0, "failed to compile control packet classifer"); -} - -void -PriorityQueue::SetControlQueue (Ptr q) -{ - NS_LOG_FUNCTION (this << q); - m_controlQueue = q; -} - -void -PriorityQueue::SetDataQueue (Ptr q) -{ - NS_LOG_FUNCTION (this << q); - m_dataQueue = q; -} - -Ptr -PriorityQueue::GetControlQueue (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_controlQueue; -} - -Ptr -PriorityQueue::GetDataQueue (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_dataQueue; -} - -PriorityQueue::PacketClass -PriorityQueue::Classify (Ptr p) -{ - pcap_pkthdr pcapPkthdr; - pcapPkthdr.caplen = p->GetSize (); - pcapPkthdr.len = p->GetSize (); - uint8_t *data = new uint8_t[p->GetSize ()]; - p->CopyData (data, p->GetSize ()); - int ret = pcap_offline_filter (&m_bpf, &pcapPkthdr, data); - delete [] data; - - if (ret == 0) - { - NS_LOG_DEBUG ("Packet is data packet"); - return PACKET_CLASS_DATA; - } - else - { - NS_LOG_DEBUG ("Packet is control packet"); - return PACKET_CLASS_CONTROL; - } -} - -bool -PriorityQueue::DoEnqueue (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - - PacketClass packetClass = Classify (p); - - if (packetClass == PACKET_CLASS_CONTROL) - { - return m_controlQueue->Enqueue (p); - } - else - { - return m_dataQueue->Enqueue (p); - } -} - -Ptr -PriorityQueue::DoDequeue (void) -{ - NS_LOG_FUNCTION (this); - - Ptr p = 0; - if (!m_controlQueue->IsEmpty ()) - { - p = m_controlQueue->Dequeue (); - } - else - { - p = m_dataQueue->Dequeue (); - } - - return p; -} - -Ptr -PriorityQueue::DoPeek (void) const -{ - NS_LOG_FUNCTION (this); - - Ptr p = 0; - if (!m_controlQueue->IsEmpty ()) - { - p = m_controlQueue->Peek (); - } - else - { - p = m_dataQueue->Peek (); - } - - return p; -} +NS_OBJECT_TEMPLATE_CLASS_DEFINE (PriorityQueue,Packet); } // namespace ns3 - diff --git a/model/priority-queue.h b/model/priority-queue.h index 0489b7d..31831f5 100644 --- a/model/priority-queue.h +++ b/model/priority-queue.h @@ -17,25 +17,28 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PRIORITY_H -#define PRIORITY_H +#ifndef PRIORITY_QUEUE_H +#define PRIORITY_QUEUE_H -#include "ns3/packet.h" +#include "ns3/log.h" +#include "ns3/string.h" +#include "ns3/pointer.h" #include "ns3/queue.h" +#include "ns3/packet.h" #include + #undef DLT_IEEE802_11_RADIO // Avoid namespace collision with ns3::YansWifiPhyHelper::DLT_IEEE802_11_RADIO namespace ns3 { -class TraceContainer; - /** * \ingroup queue * * \brief A strict priority queue with two subqueues, one for control packets and one for data */ -class PriorityQueue : public Queue +template +class PriorityQueue : public Queue { public: /** @@ -67,7 +70,7 @@ class PriorityQueue : public Queue * * \param queue Ptr to the new queue. */ - void SetDataQueue (Ptr q); + void SetDataQueue (Ptr> q); /** * Attach a queue to hold control packets to the PriorityQueue. @@ -77,21 +80,21 @@ class PriorityQueue : public Queue * * \param queue Ptr to the new queue. */ - void SetControlQueue (Ptr q); + void SetControlQueue (Ptr> q); /** * Get a copy of the attached Queue that holds control packets. * * \returns Ptr to the queue. */ - Ptr GetControlQueue (void) const; + Ptr> GetControlQueue (void) const; /** * Get a copy of the attached Queue that holds data packets. * * \returns Ptr to the queue. */ - Ptr GetDataQueue (void) const; + Ptr> GetDataQueue (void) const; /** * \brief Enumeration of the modes supported in the class. @@ -103,20 +106,222 @@ class PriorityQueue : public Queue PACKET_CLASS_DATA, /**< Packet classifier matched packet to control type */ }; + virtual bool Enqueue (Ptr item); + virtual Ptr Dequeue (void); + virtual Ptr Remove (void); + virtual Ptr Peek (void) const; + private: - virtual bool DoEnqueue (Ptr p); - virtual Ptr DoDequeue (void); - virtual Ptr DoPeek (void) const; + PacketClass Classify (Ptr p); - Ptr m_controlQueue; //!< queue for control traffic - Ptr m_dataQueue; //!< queue for data traffic + Ptr> m_controlQueue; //!< queue for control traffic + Ptr> m_dataQueue; //!< queue for data traffic std::string m_classifier; //!< classfier for control packets pcap_t * m_pcapHandle; //!< handle for libpcap struct bpf_program m_bpf; //!< compiled classifier for control packets + + NS_LOG_TEMPLATE_DECLARE; //!< redefinition of the log component }; +/** + * Implementation of the templates declared above. + */ + +template +TypeId +PriorityQueue::GetTypeId (void) +{ + static TypeId tid = TypeId (("ns3::PriorityQueue" + GetTypeParamName > () + ">").c_str ()) + .SetParent> () + .template AddConstructor > () + .AddAttribute ("ControlQueue", + "A queue to use as the transmit queue in the device.", + PointerValue (), + MakePointerAccessor (&PriorityQueue::m_controlQueue), + MakePointerChecker> ()) + .AddAttribute ("DataQueue", + "A queue to use as the transmit queue in the device.", + PointerValue (), + MakePointerAccessor (&PriorityQueue::m_dataQueue), + MakePointerChecker> ()) + .AddAttribute ("ControlPacketClassifier", + "Pcap style filter to classify control packets", + StringValue (), + MakeStringAccessor (&PriorityQueue::m_classifier), + MakeStringChecker ()) + ; + return tid; +} + +template +PriorityQueue::PriorityQueue () : + Queue (), + NS_LOG_TEMPLATE_DEFINE ("PriorityQueue") +{ + NS_LOG_FUNCTION (this); + + m_pcapHandle = pcap_open_dead (DLT_EN10MB, 1500); + NS_ASSERT_MSG (m_pcapHandle, "failed to open pcap handle"); +} + +template +PriorityQueue::~PriorityQueue () +{ + NS_LOG_FUNCTION (this); + + m_controlQueue = 0; + m_dataQueue = 0; + + pcap_close (m_pcapHandle); +} + +template +void +PriorityQueue::Initialize () +{ + NS_LOG_FUNCTION (this); + + int ret = pcap_compile (m_pcapHandle, &m_bpf, + m_classifier.c_str (), 1, PCAP_NETMASK_UNKNOWN); + NS_ASSERT_MSG (ret == 0, "failed to compile control packet classifer"); +} + +template +void +PriorityQueue::SetControlQueue (Ptr> q) +{ + NS_LOG_FUNCTION (this << q); + m_controlQueue = q; +} + +template +void +PriorityQueue::SetDataQueue (Ptr> q) +{ + NS_LOG_FUNCTION (this << q); + m_dataQueue = q; +} + +template +Ptr> +PriorityQueue::GetControlQueue (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_controlQueue; +} + +template +Ptr> +PriorityQueue::GetDataQueue (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_dataQueue; +} + +template +typename PriorityQueue::PacketClass +PriorityQueue::Classify (Ptr p) +{ + pcap_pkthdr pcapPkthdr; + pcapPkthdr.caplen = p->GetSize (); + pcapPkthdr.len = p->GetSize (); + uint8_t *data = new uint8_t[p->GetSize ()]; + p->CopyData (data, p->GetSize ()); + int ret = pcap_offline_filter (&m_bpf, &pcapPkthdr, data); + delete [] data; + + if (ret == 0) + { + NS_LOG_DEBUG ("Packet is data packet"); + return PACKET_CLASS_DATA; + } + else + { + NS_LOG_DEBUG ("Packet is control packet"); + return PACKET_CLASS_CONTROL; + } +} + +template +bool +PriorityQueue::Enqueue (Ptr item) +{ + NS_LOG_FUNCTION (this << item); + + Ptr p= DynamicCast (item); + NS_ABORT_MSG_UNLESS (p, "Class defined for Packet type only"); + + PacketClass packetClass = Classify (p); + + if (packetClass == PACKET_CLASS_CONTROL) + { + return m_controlQueue->Enqueue (item); + } + else + { + return m_dataQueue->Enqueue (item); + } +} + +template +Ptr +PriorityQueue::Dequeue (void) +{ + NS_LOG_FUNCTION (this); + + Ptr item = 0; + if (!m_controlQueue->IsEmpty ()) + { + item = m_controlQueue->Dequeue (); + } + else + { + item = m_dataQueue->Dequeue (); + } + + return item; +} + +template +Ptr +PriorityQueue::Remove (void) +{ + NS_LOG_FUNCTION (this); + + Ptr item = 0; + if (!m_controlQueue->IsEmpty ()) + { + item = m_controlQueue->Remove (); + } + else + { + item = m_dataQueue->Remove (); + } + + return item; +} + +template +Ptr +PriorityQueue::Peek (void) const +{ + NS_LOG_FUNCTION (this); + + Ptr item = 0; + if (!m_controlQueue->IsEmpty ()) + { + item = m_controlQueue->Peek (); + } + else + { + item = m_dataQueue->Peek (); + } + + return item; +} + } // namespace ns3 -#endif /* PRIORITY_H */ +#endif diff --git a/model/simple-wireless-channel.cc b/model/simple-wireless-channel.cc index 2d2e154..9a558db 100644 --- a/model/simple-wireless-channel.cc +++ b/model/simple-wireless-channel.cc @@ -190,14 +190,14 @@ SimpleWirelessChannel::Add (Ptr device) m_devices.push_back (device); } -uint32_t +std::size_t SimpleWirelessChannel::GetNDevices (void) const { return m_devices.size (); } Ptr -SimpleWirelessChannel::GetDevice (uint32_t i) const +SimpleWirelessChannel::GetDevice (std::size_t i) const { return m_devices[i]; } diff --git a/model/simple-wireless-channel.h b/model/simple-wireless-channel.h index fe09992..7ca46b7 100644 --- a/model/simple-wireless-channel.h +++ b/model/simple-wireless-channel.h @@ -111,8 +111,8 @@ class SimpleWirelessChannel : public Channel void Add (Ptr device); // inherited from ns3::Channel - virtual uint32_t GetNDevices (void) const; - virtual Ptr GetDevice (uint32_t i) const; + virtual std::size_t GetNDevices (void) const; + virtual Ptr GetDevice (std::size_t i) const; void setErrorModelType (ErrorModelType type); void setErrorRate (double error); diff --git a/model/simple-wireless-net-device.cc b/model/simple-wireless-net-device.cc index a6a6d7e..8c3bd70 100644 --- a/model/simple-wireless-net-device.cc +++ b/model/simple-wireless-net-device.cc @@ -174,7 +174,7 @@ SimpleWirelessNetDevice::GetTypeId (void) "A queue to use as the transmit queue in the device.", PointerValue (), MakePointerAccessor (&SimpleWirelessNetDevice::m_queue), - MakePointerChecker ()) + MakePointerChecker > ()) .AddAttribute ("FixedNeighborListEnabled", "Enabled or Disabled", BooleanValue (false), @@ -182,35 +182,42 @@ SimpleWirelessNetDevice::GetTypeId (void) MakeBooleanChecker ()) .AddTraceSource ("PhyTxBegin", "Trace source indicating a packet has begun transmitting", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_TxBeginTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_TxBeginTrace), + "ns3::Packet::TracedCallback") .AddTraceSource ("PhyRxDrop", "Trace source indicating a packet has been dropped by the device during reception", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxDropTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxDropTrace), + "ns3::Packet::TracedCallback") .AddTraceSource ("PhyRxBegin", "Trace source indicating a packet " "has begun being received from the channel medium " "by the device", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxBeginTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxBeginTrace), + "ns3::Packet::TracedCallback") .AddTraceSource ("PhyRxEnd", "Trace source indicating a packet " "has been completely received from the channel medium " "by the device", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxEndTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxEndTrace), + "ns3::Packet::TracedCallback") // Trace sources designed to simulate a packet sniffer facility (tcpdump). .AddTraceSource ("PromiscSniffer", "Trace source simulating a promiscuous packet sniffer attached to the device", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_promiscSnifferTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_promiscSnifferTrace), + "ns3::Packet::TracedCallback") .AddTraceSource ("QueueLatency", "Trace source to report the latency of a packet in the queue. Datatype returned is Time.", MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_QueueLatencyTrace)) .AddTraceSource ("MacTx", "A packet has been received from higher layers and is being processed in preparation for " "queueing for transmission.", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macTxTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macTxTrace), + "ns3::Packet::TracedCallback") .AddTraceSource ("MacRx", "A packet has been received by this device, has been passed up from the physical layer " "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macRxTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_macRxTrace), + "ns3::Packet::TracedCallback") ; return tid; } @@ -522,7 +529,7 @@ SimpleWirelessNetDevice::TransmitStart (Ptr p) p->RemovePacketTag (destIdTag); uint32_t destId = destIdTag.GetDestinationId (); - Time txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ())); + Time txTime = m_bps.CalculateBytesTxTime (p->GetSize ()); // If we have a non-zero neighbor count then that means we are using contention and // the data rate changes. Note that when using contention, we will always have at least @@ -783,7 +790,7 @@ SimpleWirelessNetDevice::EnqueuePacket (Ptr packet, Mac48Address from, M packet->RemoveHeader (ethHeader); m_TxBeginTrace (packet, m_address, to, protocolNumber); - Time txTime = Seconds (m_bps.CalculateTxTime (packet->GetSize ())); + Time txTime = m_bps.CalculateBytesTxTime (packet->GetSize ()); // If we have a non-zero neighbor count then that means we are using contention and // the data rate changes. if (m_nbrCount) @@ -858,13 +865,13 @@ SimpleWirelessNetDevice::SetDataRate (DataRate bps) } void -SimpleWirelessNetDevice::SetQueue (Ptr q) +SimpleWirelessNetDevice::SetQueue (Ptr > q) { NS_LOG_FUNCTION (this << q); m_queue = q; } -Ptr +Ptr > SimpleWirelessNetDevice::GetQueue (void) const { NS_LOG_FUNCTION_NOARGS (); diff --git a/model/simple-wireless-net-device.h b/model/simple-wireless-net-device.h index c459f67..b53a036 100644 --- a/model/simple-wireless-net-device.h +++ b/model/simple-wireless-net-device.h @@ -158,14 +158,14 @@ class SimpleWirelessNetDevice : public NetDevice * @see DropTailQueue * @param queue Ptr to the new queue. */ - void SetQueue (Ptr queue); + void SetQueue (Ptr > queue); /** * Get a copy of the attached Queue. * * @returns Ptr to the queue. */ - Ptr GetQueue (void) const; + Ptr > GetQueue (void) const; //****************************************** // Directional Neighbor functions @@ -212,6 +212,24 @@ class SimpleWirelessNetDevice : public NetDevice virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb); virtual bool SupportsSendFrom (void) const; + /** + * TracedCallback signature for packet events + * + * \param [in] p Packet pointer + * \param [in] from The sender address + * \param [in] to The receiver address + * \param [in] proto The protocol number + */ + typedef void (*PacketEventTracedCallback)(Ptr p, Mac48Address from, Mac48Address to, uint16_t proto); + + /** + * TracedCallback signature for queue latency reports + * + * \param [in] p Packet pointer + * \param [in] latency The observed latency + */ + typedef void (*QueueLatencyTracedCallback)(Ptr p, Time latency); + protected: virtual void DoDispose (void); private: @@ -275,7 +293,7 @@ class SimpleWirelessNetDevice : public NetDevice * @see class Queue * @see class DropTailQueue */ - Ptr m_queue; + Ptr > m_queue; /** * The trace source fired when a packet begins the reception process from From 69cff8b0e5f36cc7e694a10d8fccff87805a9a1f Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 8 Oct 2018 12:39:16 -0700 Subject: [PATCH 5/8] Move README to markdown file --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 5cec393f3705a151f436d5059237cd366e3ef4eb Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 8 Oct 2018 12:40:36 -0700 Subject: [PATCH 6/8] Remove obsolete 'All rights reserved' and add UW copyright --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 82f08a7..67a3936 100644 --- a/README.md +++ b/README.md @@ -124,8 +124,8 @@ NOTE: It is assumed that DCE will be installed at ~/dce Distribution Statement ---------------------- + Copyright (C) 2010 University of Washington Copyright (C) 2015 Massachusetts Institute of Technology - All rights reserved. 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 From e020afc7e6b11a8573b3f7e19ca3afb069f31c02 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 8 Oct 2018 13:06:54 -0700 Subject: [PATCH 7/8] Convert README text to markdown --- README.md | 107 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 67a3936..1b707de 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,21 @@ -ll-simple-wireless has the following contents: -============================================== -ll-simple-wireless/: +## Simple wireless module for ns-3 + +### Contents + +`simple-wireless` has the following contents: + +``` +simple-wireless/: /doc /examples /model wscript README -ll-simple-wireless/doc: +simple-wireless/doc: simple-wireless.rst -ll-simple-wireless/examples: +simple-wireless/examples: directional_test.cc error_model_test.cc fixed_contention_test.cc @@ -19,7 +24,7 @@ ll-simple-wireless/examples: queue_test.cc wscript -ll-simple-wireless/model: +simple-wireless/model: drop-head-queue.cc drop-head-queue.h priority-queue.cc @@ -28,29 +33,23 @@ ll-simple-wireless/model: simple-wireless-channel.h simple-wireless-net-device.cc simple-wireless-net-device.h +``` +** Please refer to the file simple-wireless.rst in the /doc folder for more information about this model.** -*** Please refer to the file simple-wireless.rst in the /doc folder for more information about this model. - -Installation Instructions -============================================================ -(assumes NS3 is already installed; see below for NS3/DCE installation instructions) +### Installation Instructions -1. Modify the NS3 wscript file to include simple-wireless in the build +(assumes `ns-3` is already installed; see below for NS3/DCE installation instructions) - For example, if using DCE add the following line at ~line 96 in dce/source/ns-3-dce/wscript - ns3waf.check_modules(conf, ['simple-wireless'], mandatory = False) +These installation instructions have been updated for the `ns-3.29` release. -2. Install the simple wireless in NS3 source using one of these methods: - a) Copy the files directly to the NS3 directory: /src/simple-wireless - OR - b) Use a softlink to your location of ll-simple-wireless to create the NS3 directory /src/simple-wireless +1. Install the simple wireless in `ns-3` source using one of these methods: + 1. Copy the files directly to the `src` or `contrib` directory: `src/simple-wireless` or `contrib/simple-wireless` (either works the same way), or + 2. Use a softlink to your location of `simple-wireless` to create the `ns-3` directory `src/simple-wireless` or `contrib/simple-wireless`, or + 3. Download using `bake` - NOTE: the directory from the tar file is named ll_simple_wireless but it is installed in NS3 as simple-wireless - -3. Add the simple-wireless as a module in the wscript used to build your NS3 scenario. - - For example: +2. Add the `simple-wireless` as a module in the wscript used to build your `ns-3` scenario. For example: +``` def configure(conf): ns3waf.check_modules(conf, ['core', 'internet', 'simple-wireless'], mandatory = True) @@ -59,16 +58,20 @@ Installation Instructions target='bin/my_test_script', cxxflags=['-std=c++0x'], source=[ my_test_script.cc'] ) +``` + +3. Rebuild `ns-3` being sure to enable examples if you want to run the example models provided with the Simple Wireless model -4. Rebuild NS3 being sure to enable examples if you want to run the example models provided with the Simple Wireless model +### Miscellaneous Notes -Miscellaneous Notes -=========================================================== -* The Simple Wireless model has been run with NS3.22/DCE1.5, NS3.21/DCE1.4 and NS3.20/DCE1.3 +* The Simple Wireless model available here is compatible with `ns-3.29`. +* The Simple Wireless model available at MIT-LL github site has been run with NS3.22/DCE1.5, NS3.21/DCE1.4 and NS3.20/DCE1.3 * The PriorityQueue uses libpcap to classify control packets so this must be installed to use priority queues. -Installation Instructions for NS3/DCE -============================================================ +### Installation Instructions for NS3/DCE + +**Note:** The following instructions pertain to the older v1.0 release. + The Simple Wireless model works in NS3.20/DCE1.3, NS3.21/DCE1.4 and NS3.22/DCE1.5. If you have any of these versions currently installed you do not need to install a different version. The instructions below are for installing NS3.22 and DCE1.5 release but it is not necessary to install @@ -77,40 +80,55 @@ these if you have an earlier, compatible version already installed. NOTE: It is assumed that DCE will be installed at ~/dce 1. Install Bake from your home directory +``` hg clone http://code.nsnam.org/bake bake +``` -2. Set path variables - Add the following lines to .profile: +2. Set path variables. Add the following lines to .profile: +``` BAKE_HOME="$HOME/bake" PATH="$PATH:$BAKE_HOME" PYTHONPATH="/usr/lib/python2.7:$BAKE_HOME" +``` + +3. Execute the .profile: - Execute the .profile: +``` . .profile - -3. Increase file descriptor limit to 2048 - To check the current value: $ ulimit –n - To change the current value: $ ulimit –n 2048 +``` + +4. Increase file descriptor limit to 2048 + * To check the current value: `$ ulimit –n` + * To change the current value: `$ ulimit –n 2048` -4. Create a directory for DCE +5. Create a directory for DCE +``` mkdir dce +``` -5. Configure, download and build DCE 1.5 (note: this automatically includes ns3.22) +6. Configure, download and build DCE 1.5 (note: this automatically includes ns3.22) +``` cd dce bake.py configure -e dce-ns3-1.5 bake.py download [See note below] bake.py build +``` + During download and build, you may run into missing packages. If so, install them using: - During download and build, you may run into missing packages. If so, install them using +``` sudo apt-get install xxxx (where xxxx is the name of the missing package) +``` Then after installing re-run the download or build command before proceeding to the next step. If the gccxml package is missing, the build may complain about pybindgen instead. Install gccxml and the pybindgen problem will probably go away. To diagnose a build failure, you may need to use the –vvv flag to get more information: +``` bake.py build -vvv - +``` NOTE: Some of the package names may not match what the dce install says is missing. Examples: + +``` DCE name Actual Install Name -------------------- ------------------- pybindgen-0.17.0.868 bzr @@ -118,12 +136,12 @@ NOTE: It is assumed that DCE will be installed at ~/dce lib_debug libc6-dbg pygraphviz python-pygraphviz pygoocanvas python-pygoocanvas +``` -********************************************************************************************************************************** -Distribution Statement ----------------------- +### Distribution Statement +``` Copyright (C) 2010 University of Washington Copyright (C) 2015 Massachusetts Institute of Technology @@ -139,5 +157,4 @@ Distribution Statement 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 - -********************************************************************************************************************************** +``` From f79585e5b3096c9f1b024ebc257fbcae898afb2b Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 8 Oct 2018 14:04:37 -0700 Subject: [PATCH 8/8] Add missing update to align with ns-3.29 --- model/simple-wireless-net-device.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/model/simple-wireless-net-device.cc b/model/simple-wireless-net-device.cc index 8c3bd70..d115a0d 100644 --- a/model/simple-wireless-net-device.cc +++ b/model/simple-wireless-net-device.cc @@ -183,23 +183,23 @@ SimpleWirelessNetDevice::GetTypeId (void) .AddTraceSource ("PhyTxBegin", "Trace source indicating a packet has begun transmitting", MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_TxBeginTrace), - "ns3::Packet::TracedCallback") + "ns3::SimpleWirelessNetDevice::PacketEventTracedCallback") .AddTraceSource ("PhyRxDrop", "Trace source indicating a packet has been dropped by the device during reception", MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxDropTrace), - "ns3::Packet::TracedCallback") + "ns3::SimpleWirelessNetDevice::PacketEventTracedCallback") .AddTraceSource ("PhyRxBegin", "Trace source indicating a packet " "has begun being received from the channel medium " "by the device", MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxBeginTrace), - "ns3::Packet::TracedCallback") + "ns3::SimpleWirelessNetDevice::PacketEventTracedCallback") .AddTraceSource ("PhyRxEnd", "Trace source indicating a packet " "has been completely received from the channel medium " "by the device", MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_phyRxEndTrace), - "ns3::Packet::TracedCallback") + "ns3::SimpleWirelessNetDevice::PacketEventTracedCallback") // Trace sources designed to simulate a packet sniffer facility (tcpdump). .AddTraceSource ("PromiscSniffer", "Trace source simulating a promiscuous packet sniffer attached to the device", @@ -207,7 +207,8 @@ SimpleWirelessNetDevice::GetTypeId (void) "ns3::Packet::TracedCallback") .AddTraceSource ("QueueLatency", "Trace source to report the latency of a packet in the queue. Datatype returned is Time.", - MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_QueueLatencyTrace)) + MakeTraceSourceAccessor (&SimpleWirelessNetDevice::m_QueueLatencyTrace), + "ns3::SimpleWirelessNetDevice::QueueLatencyTracedCallback") .AddTraceSource ("MacTx", "A packet has been received from higher layers and is being processed in preparation for " "queueing for transmission.",