Source code for cohydra.channel.wifi

"""Wireless channel."""
import ipaddress
import logging
import os

from enum import Enum, unique
from ns import core, internet, network as ns_net, wifi, wave, propagation

from .channel import Channel
from ..interface import Interface

logger = logging.getLogger(__name__)

[docs]class WiFiChannel(Channel): """ A WiFiChannel is a physical (but of course wireless) connection between two or more wireless devices. Further information can be found reading the `ns-3 source here <https://www.nsnam.org/doxygen/wifi-phy_8cc_source.html>`_. Parameters ---------- channel : int The WiFi channel to use. This will be **ignored** if frequency is set. frequency : int The frequency of the wireless channel in MHz. channel_width : int The width of the channel in MHz. Valid values are :code:`5`, :code:`10`, :code:`20`, :code:`22`, :code:`40`, :code:`80`, :code:`160`. antennas : int The number of antennas / spatial streams to use. tx_power : float The sending power in dBm. standard : :class:`.WiFiStandard` The WiFi standard to use. data_rate : :class:`.WiFiDataRate` The WiFi data rate to use. Please make sure to pick a valid data rate for your :code:`standard`. """
[docs] @unique class WiFiStandard(Enum): """All available WiFi standards. See here for further information: https://en.wikipedia.org/wiki/IEEE_802.11. """ #: The first WiFi standard from 1999. WIFI_802_11a = wifi.WIFI_PHY_STANDARD_80211a #: Standard with maximum raw data rate of 11 Mbit/s. WIFI_802_11b = wifi.WIFI_PHY_STANDARD_80211b #: Standard with maximum raw bitrate of 54 Mbit/s in 2.4GHz band. WIFI_802_11g = wifi.WIFI_PHY_STANDARD_80211g #: Standard from 2009 in 2.4GHz band. WIFI_802_11n = wifi.WIFI_PHY_STANDARD_80211n_2_4GHZ #: Standard from 2009 in 5GHz band. WIFI_802_11n_5G = wifi.WIFI_PHY_STANDARD_80211n_5GHZ #: Standard from 2013. WIFI_802_11ac = wifi.WIFI_PHY_STANDARD_80211ac #: "WiFi 6". WIFI_802_11ax = wifi.WIFI_PHY_STANDARD_80211ax_2_4GHZ ## Wireless Access in Vehicular Environments (WAVE). WIFI_802_11p = wifi.WIFI_PHY_STANDARD_80211_10MHZ
[docs] @unique class WiFiDataRate(Enum): """All available WiFi data rates. Choosing the correct and best data rate depends on the standard you are using. The data rate list is incomplete. Please consider reading the ns-3 source `here <https://gitlab.com/nsnam/ns-3-dev/blob/master/src/wifi/model/wifi-phy.cc>`_. You can pass another valid string to the channel, too. """ #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_6Mbps = "OfdmRate6Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_9Mbps = "OfdmRate9Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_12Mbps = "OfdmRate12Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_18Mbps = "OfdmRate18Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_24Mbps = "OfdmRate24Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_36Mbps = "OfdmRate36Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_48Mbps = "OfdmRate48Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11a`. OFDM_RATE_54Mbps = "OfdmRate54Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11b`, :attr:`.WiFiStandard.WIFI_802_11g`, #: :attr:`.WiFiStandard.WIFI_802_11ac` or :attr:`.WiFiStandard.WIFI_802_11ax`. DSSS_RATE_1Mbps = "DsssRate1Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11b`, :attr:`.WiFiStandard.WIFI_802_11g`, #: :attr:`.WiFiStandard.WIFI_802_11ac` or :attr:`.WiFiStandard.WIFI_802_11ax`. DSSS_RATE_2Mbps = "DsssRate2Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11b`, :attr:`.WiFiStandard.WIFI_802_11g`, #: :attr:`.WiFiStandard.WIFI_802_11ac` or :attr:`.WiFiStandard.WIFI_802_11ax`. DSSS_RATE_5_5Mbps = "DsssRate5_5Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11b`, :attr:`.WiFiStandard.WIFI_802_11g`, #: :attr:`.WiFiStandard.WIFI_802_11ac` or :attr:`.WiFiStandard.WIFI_802_11ax`. DSSS_RATE_11Mbps = "DsssRate11Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_6Mbps = "ErpOfdmRate6Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_9Mbps = "ErpOfdmRate9Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_12Mbps = "ErpOfdmRate12Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_18Mbps = "ErpOfdmRate18Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_24Mbps = "ErpOfdmRate24Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_36Mbps = "ErpOfdmRate36Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_48Mbps = "ErpOfdmRate48Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11g`, :attr:`.WiFiStandard.WIFI_802_11ac` or #: :attr:`.WiFiStandard.WIFI_802_11ax`. ERP_OFDM_RATE_54Mbps = "ErpOfdmRate54Mbps" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_3Mbps = "OfdmRate3MbpsBW10MHz" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_4_5Mbps = "OfdmRate4_5MbpsBW10MHz" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_6Mbps = "OfdmRate6MbpsBW10MHz" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_9Mbps = "OfdmRate9MbpsBW10MHz" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_12Mbps = "OfdmRate12MbpsBW10MHz" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_18Mbps = "OfdmRate18MbpsBW10MHz" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_24Mbps = "OfdmRate24MbpsBW10MHz" #: Use with :attr:`.WiFiStandard.WIFI_802_11p`. OFDM_RATE_BW_27Mbps = "OfdmRate27MbpsBW10MHz"
def __init__(self, network, nodes, frequency=None, channel=1, channel_width=40, antennas=1, tx_power=20.0, standard: WiFiStandard = WiFiStandard.WIFI_802_11b, data_rate: WiFiDataRate = WiFiDataRate.DSSS_RATE_11Mbps): super().__init__(network, nodes) #: The channel to use. self.channel = channel #: The frequency to use. #: #: This could collide with other WiFi channels. self.frequency = frequency #: The width of the channel in MHz. self.channel_width = channel_width #: The number of antennas to use. self.antennas = antennas #: The sending power in dBm. self.tx_power = tx_power #: The WiFi standard to use. self.standard = standard #: The data rate to use. self.data_rate = data_rate logger.debug("Setting up physical layer of WiFi.") self.wifi_phy_helper = wifi.YansWifiPhyHelper.Default() self.wifi_phy_helper.Set("ChannelWidth", core.UintegerValue(self.channel_width)) if self.frequency: self.wifi_phy_helper.Set("Frequency", core.UintegerValue(self.frequency)) else: self.wifi_phy_helper.Set("ChannelNumber", core.UintegerValue(self.channel)) self.wifi_phy_helper.Set("Antennas", core.UintegerValue(self.antennas)) self.wifi_phy_helper.Set("MaxSupportedTxSpatialStreams", core.UintegerValue(self.antennas)) self.wifi_phy_helper.Set("MaxSupportedRxSpatialStreams", core.UintegerValue(self.antennas)) self.wifi_phy_helper.Set("TxPowerStart", core.DoubleValue(self.tx_power)) self.wifi_phy_helper.Set("TxPowerEnd", core.DoubleValue(self.tx_power)) # Enable monitoring of radio headers. self.wifi_phy_helper.SetPcapDataLinkType(wifi.WifiPhyHelper.DLT_IEEE802_11_RADIO) wifi_channel = wifi.YansWifiChannel() self.propagation_delay_model = propagation.ConstantSpeedPropagationDelayModel() wifi_channel.SetAttribute("PropagationDelayModel", core.PointerValue(self.propagation_delay_model)) if self.standard == WiFiChannel.WiFiStandard.WIFI_802_11p: # Loss Model, parameter values from Boockmeyer, A. (2020): # "Hatebefi: Hybrid Application Testbed for Fault Injection" loss_model = propagation.ThreeLogDistancePropagationLossModel() loss_model.SetAttribute("Distance0", core.DoubleValue(27.3)) loss_model.SetAttribute("Distance1", core.DoubleValue(68.4)) loss_model.SetAttribute("Distance2", core.DoubleValue(80.7)) loss_model.SetAttribute("Exponent0", core.DoubleValue(1.332671627050236)) loss_model.SetAttribute("Exponent1", core.DoubleValue(2.6812446718062612)) loss_model.SetAttribute("Exponent2", core.DoubleValue(3.5145944762444183)) loss_model.SetAttribute("ReferenceLoss", core.DoubleValue(83.54330702928374)) wifi_channel.SetAttribute("PropagationLossModel", core.PointerValue(loss_model)) else: loss_model = propagation.LogDistancePropagationLossModel() wifi_channel.SetAttribute("PropagationLossModel", core.PointerValue(loss_model)) self.wifi_phy_helper.SetChannel(wifi_channel) #: Helper for creating the WiFi channel. self.wifi = None #: All ns-3 devices on this channel. self.devices_container = None #: Helper for creating MAC layers. self.wifi_mac_helper = None if self.standard != WiFiChannel.WiFiStandard.WIFI_802_11p: self.wifi = wifi.WifiHelper() self.wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", "DataMode", core.StringValue(self.data_rate.value), "ControlMode", core.StringValue(self.data_rate.value)) self.wifi.SetStandard(self.standard.value) self.wifi_mac_helper = wifi.WifiMacHelper() # Adhoc network between multiple nodes (no access point). self.wifi_mac_helper.SetType("ns3::AdhocWifiMac") else: self.wifi = wave.Wifi80211pHelper.Default() self.wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", "DataMode", core.StringValue(self.data_rate.value), "ControlMode", core.StringValue(self.data_rate.value), "NonUnicastMode", core.StringValue(self.data_rate.value)) self.wifi_mac_helper = wave.NqosWaveMacHelper.Default() # Install on all connected nodes. logger.debug("Installing the WiFi channel to %d nodes. Mode is %s (data) / %s (control).", len(nodes), self.standard, self.data_rate) #: All ns-3 devices on this channel. self.devices_container = self.wifi.Install(self.wifi_phy_helper, self.wifi_mac_helper, self.ns3_nodes_container) logger.info('Setting IP addresses on nodes.') stack_helper = internet.InternetStackHelper() for i, node in enumerate(nodes): ns3_device = self.devices_container.Get(i) address = None if node.wants_ip_stack(): if node.ns3_node.GetObject(internet.Ipv4.GetTypeId()) is None: logger.info('Installing IP stack on %s', node.name) stack_helper.Install(node.ns3_node) device_container = ns_net.NetDeviceContainer(ns3_device) ip_address = self.network.address_helper.Assign(device_container).GetAddress(0) netmask = network.network.prefixlen address = ipaddress.ip_interface(f'{ip_address}/{netmask}') interface = Interface(node=node, ns3_device=ns3_device, address=address) ns3_device.GetMac().SetAddress(ns_net.Mac48Address(interface.mac_address)) node.add_interface(interface) self.interfaces.append(interface)
[docs] def prepare(self, simulation): for interface in self.interfaces: pcap_log_path = os.path.join(simulation.log_directory, interface.pcap_file_name) self.wifi_phy_helper.EnablePcap(pcap_log_path, interface.ns3_device, True, True)