1 | """ |
---|
2 | ------------------------------------------------------------------------------ |
---|
3 | Mango 802.11 Reference Design Experiments Framework - Programmable Attenuator |
---|
4 | ------------------------------------------------------------------------------ |
---|
5 | License: Copyright 2014-2019, Mango Communications. All rights reserved. |
---|
6 | Distributed under the WARP license (http://warpproject.org/license) |
---|
7 | ------------------------------------------------------------------------------ |
---|
8 | This script uses the 802.11 ref design and wlan_exp to measure throughput |
---|
9 | between an AP and an associated STA using the AP's local traffic generator |
---|
10 | (LTG) and a programmable attenuator. |
---|
11 | |
---|
12 | Hardware Setup: |
---|
13 | - Requires two WARP v3 nodes |
---|
14 | - One node configured as AP using 802.11 Reference Design v1.5 or later |
---|
15 | - One node configured as STA using 802.11 Reference Design v1.5 or later |
---|
16 | - PC NIC and ETH B on WARP v3 nodes connected to common Ethernet switch |
---|
17 | - An Aeroflex USB 4205 Series programmable attenuator connected via USB |
---|
18 | |
---|
19 | Required Script Changes: |
---|
20 | - Set NETWORK to the IP address of your host PC NIC network (eg X.Y.Z.0 for IP X.Y.Z.W) |
---|
21 | - Set NODE_SERIAL_LIST to the serial numbers of your WARP nodes |
---|
22 | |
---|
23 | Description: |
---|
24 | This script initializes two WARP v3 nodes, one AP and one STA. It will use |
---|
25 | wlan_exp commands to set up associations between the AP and STA. After |
---|
26 | initalizing the nodes, the script then sets the attenuation value, initiates a |
---|
27 | traffic flow from the AP to the STA, and measures throughput by counting the |
---|
28 | number of bytes received successfully at the STA. This process repeats for |
---|
29 | each attenuation value. |
---|
30 | ------------------------------------------------------------------------------ |
---|
31 | """ |
---|
32 | import sys |
---|
33 | import time |
---|
34 | import wlan_exp.config as config |
---|
35 | import wlan_exp.util as util |
---|
36 | import wlan_exp.ltg as ltg |
---|
37 | |
---|
38 | import numpy as np |
---|
39 | |
---|
40 | from wlan_exp.prog_atten import ProgAttenController |
---|
41 | |
---|
42 | #------------------------------------------------------------------------- |
---|
43 | # Global experiment variables |
---|
44 | # |
---|
45 | |
---|
46 | # Change these values to match your experiment / network setup |
---|
47 | NETWORK = '10.0.0.0' |
---|
48 | USE_JUMBO_ETH_FRAMES = False |
---|
49 | NODE_SERIAL_LIST = ['W3-a-00001', 'W3-a-00002'] |
---|
50 | |
---|
51 | # Set the per-trial duration (in seconds) |
---|
52 | TRIAL_TIME = 5 |
---|
53 | |
---|
54 | # BSS parameters |
---|
55 | SSID = "WARP Prog Atten Ex" |
---|
56 | CHANNEL = 1 |
---|
57 | BEACON_INTERVAL = 100 |
---|
58 | |
---|
59 | |
---|
60 | #------------------------------------------------------------------------- |
---|
61 | # Initialization |
---|
62 | # |
---|
63 | print("\nInitializing experiment\n") |
---|
64 | |
---|
65 | pa = ProgAttenController() |
---|
66 | |
---|
67 | # Create an object that describes the network configuration of the host PC |
---|
68 | network_config = config.WlanExpNetworkConfiguration(network=NETWORK, |
---|
69 | jumbo_frame_support=USE_JUMBO_ETH_FRAMES) |
---|
70 | |
---|
71 | # Create an object that describes the WARP v3 nodes that will be used in this experiment |
---|
72 | nodes_config = config.WlanExpNodesConfiguration(network_config=network_config, |
---|
73 | serial_numbers=NODE_SERIAL_LIST) |
---|
74 | |
---|
75 | # Initialize the Nodes |
---|
76 | # This command will fail if either WARP v3 node does not respond |
---|
77 | nodes = util.init_nodes(nodes_config, network_config) |
---|
78 | |
---|
79 | # Extract the different types of nodes from the list of initialized nodes |
---|
80 | # - This will work for both 'DCF' and 'NOMAC' mac_low projects |
---|
81 | n_ap_l = util.filter_nodes(nodes=nodes, mac_high='AP', serial_number=NODE_SERIAL_LIST) |
---|
82 | n_sta_l = util.filter_nodes(nodes=nodes, mac_high='STA', serial_number=NODE_SERIAL_LIST) |
---|
83 | |
---|
84 | # Check that setup is valid |
---|
85 | if (((len(n_ap_l) == 1) and (len(n_sta_l) == 1))): |
---|
86 | # Extract the two nodes from the lists for easier referencing below |
---|
87 | n_ap = n_ap_l[0] |
---|
88 | n_sta = n_sta_l[0] |
---|
89 | else: |
---|
90 | print("ERROR: Node configurations did not match requirements of script.\n") |
---|
91 | print(" Ensure two nodes are ready, one using the AP design, one using the STA design\n") |
---|
92 | sys.exit(0) |
---|
93 | |
---|
94 | |
---|
95 | |
---|
96 | #------------------------------------------------------------------------- |
---|
97 | # Setup |
---|
98 | # |
---|
99 | print("\nExperimental Setup:") |
---|
100 | |
---|
101 | # Configure the AP to reject authentication requests from wireless clients |
---|
102 | # - Uncomment this line to block any wireless associations during the experiment |
---|
103 | # n_ap.set_authentication_address_filter(allow='NONE') |
---|
104 | |
---|
105 | # Set association state |
---|
106 | # - Configure AP BSS |
---|
107 | # - Create Associatiion between AP and STA |
---|
108 | n_ap.configure_bss(ssid=SSID, channel=CHANNEL, beacon_interval=BEACON_INTERVAL) |
---|
109 | n_ap.add_association(n_sta) |
---|
110 | |
---|
111 | # Set the rate of both nodes to 18 Mbps (mcs = 3, phy_mode = 'NONHT') |
---|
112 | mcs = 3 |
---|
113 | phy_mode = util.phy_modes['NONHT'] |
---|
114 | rate_info = util.get_rate_info(mcs, phy_mode) |
---|
115 | |
---|
116 | # Put each node in a known, good state |
---|
117 | for node in nodes: |
---|
118 | node.set_tx_rate_unicast(mcs, phy_mode, curr_assoc=True, new_assoc=True) |
---|
119 | node.reset(log=True, txrx_counts=True, ltg=True, tx_queues=True) # Do not reset associations/network_info |
---|
120 | |
---|
121 | # Get some additional information about the experiment |
---|
122 | network_info = node.get_network_info() |
---|
123 | channel = network_info['channel'] |
---|
124 | |
---|
125 | print("\n{0}:".format(node.name)) |
---|
126 | print(" Channel = {0}".format(util.channel_info_to_str(util.get_channel_info(channel)))) |
---|
127 | print(" Rate = {0}".format(util.rate_info_to_str(rate_info))) |
---|
128 | |
---|
129 | print("") |
---|
130 | |
---|
131 | # Check that the nodes are part of the same BSS. Otherwise, the LTGs below will fail. |
---|
132 | if not util.check_bss_membership([n_ap, n_sta]): |
---|
133 | print("\nERROR: Nodes are not part of the same BSS.") |
---|
134 | util.check_bss_membership([n_ap, n_sta], verbose=True) |
---|
135 | print("Ensure that both nodes are part of the same BSS.") |
---|
136 | sys.exit(0) |
---|
137 | |
---|
138 | |
---|
139 | #------------------------------------------------------------------------- |
---|
140 | # Run Experiments |
---|
141 | # |
---|
142 | print("\nRun Experiment:") |
---|
143 | |
---|
144 | # Experiments: |
---|
145 | # 1) AP -> STA throughput for each attenuation value |
---|
146 | # |
---|
147 | |
---|
148 | attens = np.arange(49,56,0.5) |
---|
149 | xputs = [0]*len(attens) |
---|
150 | |
---|
151 | ap_ltg_id = n_ap.ltg_configure(ltg.FlowConfigCBR(dest_addr=n_sta.wlan_mac_address, |
---|
152 | payload_length=1400, |
---|
153 | interval=0), auto_start=False) |
---|
154 | |
---|
155 | for idx,atten in enumerate(attens): |
---|
156 | pa.set_atten(atten) |
---|
157 | time.sleep(0.100) |
---|
158 | |
---|
159 | n_ap.ltg_start(ap_ltg_id) |
---|
160 | |
---|
161 | # Record the initial Tx/Rx counts |
---|
162 | sta_rx_counts_start = n_sta.get_txrx_counts(n_ap) |
---|
163 | ap_rx_counts_start = n_ap.get_txrx_counts(n_sta) |
---|
164 | |
---|
165 | # Wait for the TRIAL_TIME |
---|
166 | time.sleep(TRIAL_TIME) |
---|
167 | |
---|
168 | # Record the ending Tx/Rx counts |
---|
169 | sta_rx_counts_end = n_sta.get_txrx_counts(n_ap) |
---|
170 | ap_rx_counts_end = n_ap.get_txrx_counts(n_sta) |
---|
171 | |
---|
172 | n_ap.ltg_stop(ap_ltg_id) |
---|
173 | n_ap.queue_tx_data_purge_all() |
---|
174 | |
---|
175 | sta_num_bits = float((sta_rx_counts_end['data_num_rx_bytes'] - sta_rx_counts_start['data_num_rx_bytes']) * 8) |
---|
176 | sta_time_span = float(sta_rx_counts_end['retrieval_timestamp'] - sta_rx_counts_start['retrieval_timestamp']) |
---|
177 | sta_xput = sta_num_bits / sta_time_span |
---|
178 | xputs[idx] = sta_xput |
---|
179 | |
---|
180 | print('{0} db \t {1} Mbps'.format(atten, sta_xput)) |
---|
181 | |
---|
182 | pa.close() |
---|
183 | |
---|
184 | |
---|