Skip to content

Instantly share code, notes, and snippets.

@buihaduong
Created July 17, 2020 13:32
Show Gist options
  • Save buihaduong/78a515c09d77f3d226cd833c855466d3 to your computer and use it in GitHub Desktop.
Save buihaduong/78a515c09d77f3d226cd833c855466d3 to your computer and use it in GitHub Desktop.
Simple wireless LAN network simulation using ns-3. Based on wifi-simple-adhoc-grid.cc example.
# -*- Mode: Python; -*-
# /*
# * Copyright (c) 2009 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
# *
# * Based on wifi-simple-adhoc-grid.cc example
# * Ported to Python by Bui Ha Duong
# */
'''
// This program configures a wireless network of n nodes (default 3 nodes) on an
// 802.11b physical layer, with
// 802.11b NICs in adhoc mode, and by default, sends one packet of 1000
// (application) bytes to node 0.
//
// The default layout is like this
//
// n0 n1 n2
//
// the layout is affected by the parameters given to GridPositionAllocator;
// by default, numNodes is 3 and GridWidth is set equal to numNodes.
//
// There are a number of command-line options available to control
// the default behavior. The list of available command-line options
// can be listed with the following command:
// ./waf --pyrun "wifi-simple-adhoc.py --help"
//
// Note that all ns-3 attributes (not just the ones exposed in the below
// script) can be changed at command line; see the ns-3 documentation.
//
// For instance, for this configuration, the physical layer will
// stop successfully receiving packets when distance increases beyond
// 650m.
// To see this effect, try running:
//
// ./waf --pyrun "wifi-simple-adhoc.py --distance=650"
// ./waf --pyrun "wifi-simple-adhoc.py --distance=1000"
// ./waf --pyrun "wifi-simple-adhoc.py --distance=1500"
//
// The source node and sink node can be changed like this:
//
// ./waf --pyrun "wifi-simple-adhoc.py --sourceNode=20 --sinkNode=10"
//
// This script can also be helpful to put the Wifi layer into verbose
// logging mode; this command will turn on all wifi logging:
//
// ./waf --pyrun "wifi-simple-adhoc.py --verbose=1"
//
// By default, trace file writing is off-- to enable it, try:
// ./waf --pyrun "wifi-simple-adhoc.py --tracing=1"
//
// When you are done tracing, you will notice many pcap trace files
// in your directory. If you have tcpdump installed, you can try this:
//
// tcpdump -r wifi-simple-adhoc-0-0.pcap -nn -tt
//
// grep Udp wifi-simple-adhoc.tr | grep -v olsr
'''
from __future__ import print_function
import ns.core
import ns.network
import ns.mobility
import ns.config_store
import ns.wifi
import ns.internet
import ns.applications
import ns.olsr
import ns.flow_monitor
import sys
def ReceivePacket(socket):
while socket.Recv():
print ("Received one packet!")
def GenerateTraffic(socket, pktSize, pktCount, pktInterval):
if pktCount > 0:
socket.Send(ns.network.Packet(pktSize))
ns.core.Simulator.Schedule(pktInterval, GenerateTraffic, socket, pktSize, pktCount-1, pktInterval)
print ("Sending one packet!")
else:
socket.Close()
def print_stats(os, st):
print (" Tx Bytes: ", st.txBytes, file=os)
print (" Rx Bytes: ", st.rxBytes, file=os)
print (" Tx Packets: ", st.txPackets, file=os)
print (" Rx Packets: ", st.rxPackets, file=os)
print (" Lost Packets: ", st.lostPackets, file=os)
if st.rxPackets > 0:
print (" Mean{Delay}: ", (st.delaySum.GetSeconds() / st.rxPackets), file=os)
# print (" Mean{Jitter}: ", (st.jitterSum.GetSeconds() / (st.rxPackets-1)), file=os)
print (" Mean{Hop Count}: ", float(st.timesForwarded) / st.rxPackets + 1, file=os)
def main(argv):
cmd = ns.core.CommandLine()
cmd.phyMode = "DsssRate1Mbps"
cmd.distance = 500 # m
cmd.packetSize = 1000 # bytes
cmd.numPackets = 1
cmd.numNodes = 3 # by default, 3 nodes
cmd.sinkNode = 0
cmd.sourceNode = cmd.numNodes - 1
cmd.interval = 1.0 # seconds
cmd.verbose = False
cmd.tracing = False
cmd.AddValue ("phyMode", "Wifi Phy mode")
cmd.AddValue ("distance", "distance (m)")
cmd.AddValue ("packetSize", "size of application packet sent")
cmd.AddValue ("numPackets", "number of packets generated")
cmd.AddValue ("interval", "interval (seconds) between packets")
cmd.AddValue ("verbose", "turn on all WifiNetDevice log components")
cmd.AddValue ("tracing", "turn on ascii and pcap tracing")
cmd.AddValue ("numNodes", "number of nodes")
cmd.AddValue ("sinkNode", "Receiver node number")
cmd.AddValue ("sourceNode", "Sender node number")
cmd.Parse(sys.argv)
phyMode = cmd.phyMode
distance = int (cmd.distance)
packetSize = int (cmd.packetSize)
numPackets = int (cmd.numPackets)
numNodes = int (cmd.numNodes)
sinkNode = int (cmd.sinkNode)
sourceNode = numNodes - 1
interval = float (cmd.interval)
verbose = cmd.verbose
tracing = cmd.tracing
# Convert to time object
interPacketInterval = ns.core.Seconds(interval)
# disable fragmentation for frames below 2200 bytes
ns.core.Config.SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", ns.core.StringValue ("2200"))
# turn off RTS/CTS for frames below 2200 bytes
ns.core.Config.SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", ns.core.StringValue ("2200"))
# Fix non-unicast data rate to be the same as that of unicast
ns.core.Config.SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode", ns.core.StringValue (phyMode))
# 1. Create nodes
nodes = ns.network.NodeContainer()
nodes.Create (numNodes)
# 2. Set position for nodes
mobility = ns.mobility.MobilityHelper()
mobility.SetPositionAllocator("ns3::GridPositionAllocator",
"MinX", ns.core.DoubleValue (0.0),
"MinY", ns.core.DoubleValue (0.0),
"DeltaX", ns.core.DoubleValue (distance),
"DeltaY", ns.core.DoubleValue (distance),
"GridWidth", ns.core.UintegerValue (numNodes),
"LayoutType", ns.core.StringValue ("RowFirst"))
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel")
mobility.Install (nodes)
# 3. Create & setup wifi channel
wifiChannel = ns.wifi.YansWifiChannelHelper()
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel")
wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel")
# 4. Install wireless devices
wifi = ns.wifi.WifiHelper()
wifi.SetStandard(ns.wifi.WIFI_PHY_STANDARD_80211b)
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode", ns.core.StringValue (phyMode),
"ControlMode", ns.core.StringValue (phyMode))
if verbose:
wifi.EnableLogComponents()
wifiPhy = ns.wifi.YansWifiPhyHelper.Default()
wifiPhy.SetChannel (wifiChannel.Create())
# set it to zero; otherwise, gain will be added
wifiPhy.Set ("RxGain", ns.core.DoubleValue(-10))
# ns-3 supports RadioTap and Prism tracing extensions for 802.11b
wifiPhy.SetPcapDataLinkType (ns.wifi.YansWifiPhyHelper.DLT_IEEE802_11_RADIO)
wifiMac = ns.wifi.WifiMacHelper()
# use ad-hoc MAC
wifiMac.SetType("ns3::AdhocWifiMac")
devices = wifi.Install (wifiPhy, wifiMac, nodes)
# Enable OLSR
olsr = ns.olsr.OlsrHelper()
staticRouting = ns.internet.Ipv4StaticRoutingHelper()
listRouting = ns.internet.Ipv4ListRoutingHelper()
listRouting.Add (staticRouting, 0)
listRouting.Add (olsr, 10)
# 6. Install TCP/IP stack & assign IP addresses
internet = ns.internet.InternetStackHelper()
internet.SetRoutingHelper(listRouting)
internet.Install(nodes)
internet.Reset()
ipv4 = ns.internet.Ipv4AddressHelper()
ipv4.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0"))
interfaces = ipv4.Assign (devices)
# 7. Install applications
appSource = ns.network.NodeList.GetNode(sourceNode)
appSink = ns.network.NodeList.GetNode(sinkNode)
sink = ns.network.Socket.CreateSocket(appSink, ns.core.TypeId.LookupByName("ns3::UdpSocketFactory"))
sink.Bind(ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), 4477))
sink.SetRecvCallback(ReceivePacket)
source = ns.network.Socket.CreateSocket(appSource, ns.core.TypeId.LookupByName("ns3::UdpSocketFactory"))
source.Connect(ns.network.InetSocketAddress(interfaces.GetAddress(sinkNode), 4477))
if tracing:
ascii = ns.network.AsciiTraceHelper()
wifiPhy.EnableAsciiAll(ascii.CreateFileStream ("wifi-simple-adhoc.tr"))
wifiPhy.EnablePcap ("wifi-simple-adhoc", devices)
# Give OLSR time to converge-- 30 seconds perhaps
ns.core.Simulator.Schedule(ns.core.Seconds(30),
GenerateTraffic, source, packetSize, numPackets, interPacketInterval)
# 8. Install FlowMonitor on all nodes
flowmon_helper = ns.flow_monitor.FlowMonitorHelper()
monitor = flowmon_helper.InstallAll()
monitor = flowmon_helper.GetMonitor()
monitor.SetAttribute("DelayBinWidth", ns.core.DoubleValue(0.001))
monitor.SetAttribute("JitterBinWidth", ns.core.DoubleValue(0.001))
monitor.SetAttribute("PacketSizeBinWidth", ns.core.DoubleValue(20))
# 9. Run simulation for 44 seconds
ns.core.Simulator.Stop(ns.core.Seconds(44.0))
ns.core.Simulator.Run()
# 10. Print per flow statistics
monitor.CheckForLostPackets()
classifier = flowmon_helper.GetClassifier()
for flow_id, flow_stats in monitor.GetFlowStats():
t = classifier.FindFlow(flow_id)
proto = {6: 'TCP', 17: 'UDP'} [t.protocol]
print ("FlowID: %i (%s %s/%s --> %s/%i)" % \
(flow_id, proto, t.sourceAddress, t.sourcePort, t.destinationAddress, t.destinationPort))
print_stats(sys.stdout, flow_stats)
# 11. Cleanup
ns.core.Simulator.Destroy()
if __name__ == "__main__":
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment