source: ReferenceDesigns/w3_802.11/python/examples/throughput_two_nodes.py

Last change on this file was 6320, checked in by chunter, 5 years ago

1.8.0 release wlan-exp

File size: 11.2 KB
Line 
1"""
2------------------------------------------------------------------------------
3Mango 802.11 Reference Design Experiments Framework - Two Node Throughput
4------------------------------------------------------------------------------
5License:   Copyright 2014-2019, Mango Communications. All rights reserved.
6           Distributed under the WARP license (http://warpproject.org/license)
7------------------------------------------------------------------------------
8This script uses the 802.11 ref design and wlan_exp to measure throughput
9between an AP and an associated STA using the AP's local traffic generator
10(LTG).
11
12Hardware Setup:
13  - Requires two WARP v3 nodes
14    - One node configured as AP using 802.11 Reference Design v1.7 or later
15    - One node configured as STA using 802.11 Reference Design v1.7 or later
16    - Two nodes configured as IBSS using 802.11 Reference Design v1.7 or later
17  - PC NIC and ETH B on WARP v3 nodes connected to common Ethernet switch
18
19Required 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
23Description:
24  This script initializes two WARP v3 nodes, one AP and one STA or two IBSS.
25It will use wlan_exp commands to set up the network for the experiment.  The
26script then , sets the Tx rate for the nodes; initiates a traffic flow from
27the node 1 to node 2 and measures throughput by counting the number of bytes
28received successfully at node 2. This process repeats for node 2 -> node 1 and
29head-to-head traffic flows.
30------------------------------------------------------------------------------
31"""
32import sys
33import time
34import wlan_exp.config as config
35import wlan_exp.util as util
36import wlan_exp.ltg as ltg
37
38#-------------------------------------------------------------------------
39#  Global experiment variables
40#
41
42# Change these values to match your experiment / network setup
43NETWORK              = '10.0.0.0'
44USE_JUMBO_ETH_FRAMES = False
45NODE_SERIAL_LIST     = ['W3-a-00001', 'W3-a-00002']
46
47# BSS parameters
48SSID                 = "WARP Xput Example"
49CHANNEL              = 1
50BEACON_INTERVAL      = 100
51
52# Set the per-trial duration (in seconds)
53TRIAL_TIME           = 10
54
55#-------------------------------------------------------------------------
56#  Initialization
57#
58print("\nInitializing experiment\n")
59
60# Create an object that describes the network configuration of the host PC
61network_config = config.WlanExpNetworkConfiguration(network=NETWORK,
62                                                    jumbo_frame_support=USE_JUMBO_ETH_FRAMES)
63
64# Create an object that describes the WARP v3 nodes that will be used in this experiment
65nodes_config   = config.WlanExpNodesConfiguration(network_config=network_config,
66                                                  serial_numbers=NODE_SERIAL_LIST)
67
68# Initialize the Nodes
69#   This command will fail if either WARP v3 node does not respond
70nodes = util.init_nodes(nodes_config, network_config)
71
72# Reset all (optional)
73# for node in nodes:
74#     node.reset_all()
75
76# Extract the different types of nodes from the list of initialized nodes
77#     - This will work for both 'DCF' and 'NOMAC' mac_low projects
78n_ap_l   = util.filter_nodes(nodes=nodes, mac_high='AP',   serial_number=NODE_SERIAL_LIST, warn=False)
79n_sta_l  = util.filter_nodes(nodes=nodes, mac_high='STA',  serial_number=NODE_SERIAL_LIST, warn=False)
80n_ibss_l = util.filter_nodes(nodes=nodes, mac_high='IBSS', serial_number=NODE_SERIAL_LIST, warn=False)
81
82
83# Check that setup is valid:
84#     1) AP and STA
85#     2) Two IBSS nodes
86if len(n_ap_l) == 1 and len(n_sta_l) == 1:
87    # Setup the two nodes
88    node1 = n_ap_l[0]
89    node2 = n_sta_l[0]
90
91    # Configure the AP to reject authentication requests from wireless clients
92    #    - Uncomment this line to block any wireless associations during the experiment
93    # node1.set_authentication_address_filter(allow='NONE')
94
95    # Configure AP BSS
96    node1.configure_bss(ssid=SSID, channel=CHANNEL, beacon_interval=BEACON_INTERVAL)
97
98    # Establish the association between nodes
99    #     - This will change the STA to the appropriate channel
100    node1.add_association(node2)
101   
102elif len(n_ibss_l) == 2:
103    # Setup the two nodes
104    node1 = n_ibss_l[0]
105    node2 = n_ibss_l[1]
106
107    # Create the BSS_INFO describing the ad-hoc network
108    bssid    = util.create_locally_administered_bssid(node1.wlan_mac_address)
109
110    # Add both nodes to the new IBSS
111    node1.configure_bss(bssid=bssid, ssid=SSID, channel=CHANNEL, beacon_interval=BEACON_INTERVAL)
112    node2.configure_bss(bssid=bssid, ssid=SSID, channel=CHANNEL, beacon_interval=BEACON_INTERVAL)
113
114else:
115    print("ERROR: Node configurations did not match requirements of script.\n")
116    print("    Ensure two nodes are ready, either:\n")
117    print("        1) one using the AP design, one using the STA design, or\n")
118    print("        2) two using the IBSS design\n")
119    sys.exit(0)
120
121#-------------------------------------------------------------------------
122#  Setup
123#
124
125print("\nExperimental Setup:")
126
127# Set the rate of both nodes to 26 Mbps (mcs = 3, phy_mode = 'HTMF')
128mcs       = 3
129phy_mode  = util.phy_modes['HTMF']
130rate_info = util.get_rate_info(mcs, phy_mode)
131
132# Put each node in a known, good state
133for node in [node1, node2]:
134    node.enable_ethernet_portal(enable=False)
135    node.set_tx_rate_data(mcs, phy_mode, device_list='ALL_UNICAST')
136    node.reset(log=True, txrx_counts=True, ltg=True, tx_queues=True) # Do not reset associations/bss_info
137    network_info = node.get_network_info()
138
139    msg = ""
140    if (node == node1):
141        msg += "\nNode 1: \n"
142    if (node == node2):
143        msg += "\nNode 2: \n"
144
145    msg += "    Description = {0}\n".format(node.description)
146    msg += "    Channel     = {0}\n".format(util.channel_info_to_str(util.get_channel_info(network_info['channel'])))
147    msg += "    Rate        = {0}\n".format(util.rate_info_to_str(rate_info))
148    print(msg)
149
150print("")
151
152# Check that the nodes are part of the same BSS.  Otherwise, the LTGs below will fail.
153if not util.check_bss_membership([node1, node2]):
154    print("\nERROR: Nodes are not part of the same BSS.")
155    util.check_bss_membership([node1, node2], verbose=True)
156    print("Ensure that both nodes are part of the same BSS.")
157    sys.exit(0)
158
159#-------------------------------------------------------------------------
160#  Run Experiments
161#
162print("\nRun Experiment:")
163
164# Experiments:
165#   1) Node1 -> Node2 throughput
166#   2) Node2 -> Node1 throughput
167#   3) Head-to-head throughput
168#
169# This experiment is basically the same for each iteration.  Therefore, the
170# main control variables for each iteration have been placed into the
171# dictionary below to make readability easier by not having repeated code.
172#
173experiment_params = [{'node1_ltg_en' : True,  'node2_ltg_en' : False, 'desc' : 'Node 1 -> Node 2'},
174                     {'node1_ltg_en' : False, 'node2_ltg_en' : True,  'desc' : 'Node 2 -> Node 1'},
175                     {'node1_ltg_en' : True,  'node2_ltg_en' : True,  'desc' : 'Head-to-Head'}]
176
177
178#-------------------------------------------------------------------------
179#  Experiment:  Compute throughput from node counts
180#
181for experiment in experiment_params:
182
183    print("\nTesting {0} throughput for rate {1} ...".format(experiment['desc'], util.rate_info_to_str(rate_info)))
184
185    # Start a flow from the AP's local traffic generator (LTG) to the STA
186    #    Set the flow to 1400 byte payloads, fully backlogged (0 usec between new pkts), run forever
187    #    Start the flow immediately
188    if (experiment['node1_ltg_en']):
189        node1_ltg_id  = node1.ltg_configure(ltg.FlowConfigCBR(dest_addr=node2.wlan_mac_address,
190                                                              payload_length=1400, 
191                                                              interval=0), auto_start=True)
192
193    # Start a flow from the STA's local traffic generator (LTG) to the AP
194    #    Set the flow to 1400 byte payloads, fully backlogged (0 usec between new pkts), run forever
195    #    Start the flow immediately
196    if (experiment['node2_ltg_en']):
197        node2_ltg_id  = node2.ltg_configure(ltg.FlowConfigCBR(dest_addr=node1.wlan_mac_address,
198                                                              payload_length=1400, 
199                                                              interval=0), auto_start=True)
200
201    # Record the initial Tx/Rx counts
202    #     - This example is interested in received throughput not transmitted
203    #       throughput.  Therefore, it must use the received (RX) counts and
204    #       not the transmitted (TX) counts for the experiment.  To use the
205    #       RX counts, it must first get them from the receiving node.  For
206    #       example, to see the packets received from Node 1 at Node 2, get
207    #       the TX/RX counts from Node 2 for Node 1.  This is opposite of TX
208    #       counts which must be extracted from the transmitting node.  For
209    #       example, to see the packets transmitted from Node 1 to Node 2, get
210    #       the TX/RX counts from Node 1 for Node 2. 
211    #
212    node2_txrx_counts_for_node1_start = node2.get_txrx_counts(node1)
213    node1_txrx_counts_for_node2_start = node1.get_txrx_counts(node2)
214
215    # Wait for the TRIAL_TIME
216    time.sleep(TRIAL_TIME)
217
218    # Record the ending Tx/Rx counts
219    node2_txrx_counts_for_node1_end = node2.get_txrx_counts(node1)
220    node1_txrx_counts_for_node2_end = node1.get_txrx_counts(node2)
221
222    # Stop the AP LTG flow and purge any remaining transmissions in the queue so that nodes are in a known, good state
223    if (experiment['node1_ltg_en']):
224        node1.ltg_stop(node1_ltg_id)
225        node1.ltg_remove(node1_ltg_id)
226        node1.queue_tx_data_purge_all()
227
228    # Stop the STA LTG flow and purge any remaining transmissions in the queue so that nodes are in a known, good state
229    if (experiment['node2_ltg_en']):
230        node2.ltg_stop(node2_ltg_id)
231        node2.ltg_remove(node2_ltg_id)
232        node2.queue_tx_data_purge_all()
233
234    # Compute the throughput
235    #     - Timestamps are in microseconds; bits/usec == Mbits/sec
236    #     - In Python 3.x, the division operator is always floating point.  In order to be compatible with all versions
237    #       of python, cast operands to floats to ensure floating point division
238    #
239    node1_to_node2_num_bits  = float((node2_txrx_counts_for_node1_end['data_num_rx_bytes'] - node2_txrx_counts_for_node1_start['data_num_rx_bytes']) * 8)
240    node1_to_node2_time_span = float(node2_txrx_counts_for_node1_end['retrieval_timestamp'] - node2_txrx_counts_for_node1_start['retrieval_timestamp'])
241    node1_to_node2_xput      = node1_to_node2_num_bits / node1_to_node2_time_span
242    print("    Node 1 -> Node 2:  Rate = {0:>4.1f} Mbps   Throughput = {1:>5.2f} Mbps".format(rate_info['phy_rate'], node1_to_node2_xput))
243
244    node2_to_node1_num_bits  = float((node1_txrx_counts_for_node2_end['data_num_rx_bytes'] - node1_txrx_counts_for_node2_start['data_num_rx_bytes']) * 8)
245    node2_to_node1_time_span = float(node1_txrx_counts_for_node2_end['retrieval_timestamp'] - node1_txrx_counts_for_node2_start['retrieval_timestamp'])
246    node2_to_node1_xput      = node2_to_node1_num_bits / node2_to_node1_time_span
247    print("    Node 2 -> Node 1:  Rate = {0:>4.1f} Mbps   Throughput = {1:>5.2f} Mbps".format(rate_info['phy_rate'], node2_to_node1_xput))
248
249for node in [node1, node2]:
250    node.enable_ethernet_portal(enable=True)
Note: See TracBrowser for help on using the repository browser.