aboutsummaryrefslogtreecommitdiffstats
path: root/vicn/resource/ns3/emulated_wifi_channel.py
diff options
context:
space:
mode:
Diffstat (limited to 'vicn/resource/ns3/emulated_wifi_channel.py')
-rw-r--r--vicn/resource/ns3/emulated_wifi_channel.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/vicn/resource/ns3/emulated_wifi_channel.py b/vicn/resource/ns3/emulated_wifi_channel.py
new file mode 100644
index 00000000..088d4444
--- /dev/null
+++ b/vicn/resource/ns3/emulated_wifi_channel.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2017 Cisco and/or its affiliates.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from vicn.resource.ns3.emulated_channel import EmulatedChannel
+from vicn.resource.linux.net_device import NetDevice
+from vicn.core.address_mgr import AddressManager
+from vicn.core.resource_mgr import wait_resources
+from vicn.core.task import async_task, run_task
+
+class EmulatedWiFiChannel(EmulatedChannel):
+ """EmulatedWiFiChannel Resource
+
+ This resource uses the ns3 simulator to emulate an 80211n wireless channel.
+ It assume no interference between base stations, and thus the emulated
+ channel corresponds to a single base station.
+ """
+ __package_names__ = ['wifi-emulator']
+ __app_name__ = 'wifi_emulator'
+
+ #---------------------------------------------------------------------------
+ # Attribute handlers
+ #---------------------------------------------------------------------------
+
+ async def _add_station(self, station):
+ from vicn.resource.lxd.lxc_container import LxcContainer
+ from vicn.resource.linux.veth_pair import VethPair
+ from vicn.resource.linux.tap_device import TapChannel
+ from vicn.resource.linux.macvlan import MacVlan
+
+ interfaces = list()
+ if not station.managed:
+ sta_if = None
+ else:
+ if isinstance(station, LxcContainer):
+ host = NetDevice(node = station.node,
+ device_name='vhh-' + station.name + '-' + self.name,
+ managed = False)
+ sta_if = VethPair(node = station,
+ name = 'vh-' + station.name + '-' + self.name,
+ device_name = 'vh-' + station.name + '-' + self.name,
+ host = host,
+ owner = self)
+ bridged_sta = sta_if.host
+ else:
+ raise NotImplementedError
+
+ if sta_if:
+ self._sta_ifs[station] = sta_if
+ self._sta_bridged[station] = bridged_sta
+ interfaces.append(sta_if)
+ self._state.manager.commit_resource(sta_if)
+
+ sta_tap = TapChannel(node = self.node,
+ owner = self,
+ device_name = 'tap-' + station.name + '-' + self.name,
+ up = True,
+ promiscuous = True,
+ station_name = station.name,
+ channel_name = self.name)
+ self._sta_taps[station] = sta_tap
+ interfaces.append(sta_tap)
+ self._state.manager.commit_resource(sta_tap)
+
+ # Wait for interfaces to be setup
+ await wait_resources(interfaces)
+
+ # Add interfaces to bridge
+ # One vlan per station is needed to avoid broadcast loops
+ vlan = AddressManager().get('vlan', sta_tap)
+ # sta_tap choosen because always there
+ if sta_if:
+ sta_if.set('channel', self)
+
+ task = self.node.bridge._remove_interface(bridged_sta)
+ await run_task(task, self._state.manager)
+ task = self.node.bridge._add_interface(bridged_sta,
+ vlan = vlan)
+ await run_task(task, self._state.manager)
+
+ task = self.node.bridge._add_interface(sta_tap, vlan = vlan)
+ await run_task(task, self._state.manager)
+
+
+ def _get_cmdline_params(self, ):
+
+ # sta-macs and sta-list for unmanaged stations
+ sta_list = list() # list of identifiers
+ sta_macs = list() # list of macs
+ sta_taps = list()
+ for station in self.stations:
+ if not station.managed:
+ interface = [i for i in station.interfaces if i.channel == self]
+ assert len(interface) == 1
+ interface = interface[0]
+
+ sta_list.append(interface.name)
+ sta_macs.append(interface.mac_address)
+ else:
+ identifier = self._sta_ifs[station]._state.uuid._uuid
+ sta_list.append(identifier)
+
+ mac = self._sta_ifs[station].mac_address
+ sta_macs.append(mac)
+
+ tap = self._sta_taps[station].device_name
+ sta_taps.append(tap)
+
+ params = {
+ # Name of the tap between NS3 and the base station
+ 'bs-tap' : self._ap_tap.device_name,
+ # Number of stations
+ 'n-sta' : len(self._sta_taps),
+ # List of the stations of the simulation # identifiers
+ 'sta-list' : ','.join(sta_list),
+ # List of the taps between NS3 and the mobile stations
+ 'sta-taps' : ','.join(sta_taps),
+ # List of the macs of the mobile stations
+ 'sta-macs' : ','.join(sta_macs),
+ # X position of the Base Station
+ 'bs-x' : 0, #self.ap.x,
+ # Y position of the Base Station
+ 'bs-y' : 0, #self.ap.y,
+ # Experiment ID
+ 'experiment-id' : 'vicn',
+ # Index of the base station
+ 'bs-name' : self._ap_tap.device_name,
+ # Base station MAC address
+ 'bs-mac' : self._ap_if.mac_address,
+ # Control port for dynamically managing the stations movement
+ 'control-port' : self.control_port,
+ }
+
+ return ' '.join(['--{}={}'.format(k, v) for k, v in params.items()])