1 | # -*- coding: utf-8 -*- |
---|
2 | """ |
---|
3 | ------------------------------------------------------------------------------ |
---|
4 | Mango 802.11 Reference Design Experiments Framework - Ad hoc (IBSS) Node |
---|
5 | ------------------------------------------------------------------------------ |
---|
6 | License: Copyright 2019 Mango Communications, Inc. All rights reserved. |
---|
7 | Use and distribution subject to terms in LICENSE.txt |
---|
8 | ------------------------------------------------------------------------------ |
---|
9 | |
---|
10 | """ |
---|
11 | |
---|
12 | import wlan_exp.node as node |
---|
13 | import wlan_exp.cmds as cmds |
---|
14 | |
---|
15 | |
---|
16 | __all__ = ['WlanExpNodeIBSS'] |
---|
17 | |
---|
18 | |
---|
19 | class WlanExpNodeIBSS(node.WlanExpNode): |
---|
20 | """wlan_exp Node class for the 802.11 Reference Design IBSS MAC project |
---|
21 | |
---|
22 | Args: |
---|
23 | network_config (transport.NetworkConfiguration) : Network configuration of the node |
---|
24 | """ |
---|
25 | |
---|
26 | #------------------------------------------------------------------------- |
---|
27 | # Node Commands |
---|
28 | #------------------------------------------------------------------------- |
---|
29 | |
---|
30 | def get_txrx_counts(self, device_list=None): |
---|
31 | """Get the counts from the node. |
---|
32 | |
---|
33 | .. note:: This function has the same implementation as WlanExpNode but |
---|
34 | different default values. |
---|
35 | |
---|
36 | Args: |
---|
37 | device_list (list of WlanExpNode, WlanExpNode, WlanDevice, optional): List of devices |
---|
38 | for which to get counts. See note below for more information. |
---|
39 | return_zeroed_counts_if_none(bool, optional): If no counts exist on the node for |
---|
40 | the specified device(s), return a zeroed counts dictionary with proper timestamps |
---|
41 | instead of None. |
---|
42 | |
---|
43 | Returns: |
---|
44 | counts_dictionary (list of dictionaries, dictionary): Counts for the device(s) specified. |
---|
45 | |
---|
46 | |
---|
47 | The dictionaries returned by this method have the following fields: |
---|
48 | |
---|
49 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
50 | | Field | Description | |
---|
51 | +=============================+=====================================================================================================+ |
---|
52 | | retrieval_timestamp | Value of System Time in microseconds when structure retrieved from the node | |
---|
53 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
54 | | mac_addr | MAC address of remote node whose statics are recorded here | |
---|
55 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
56 | | associated | Boolean indicating whether remote node is currently associated with this node | |
---|
57 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
58 | | data_num_rx_bytes | Total number of bytes received in DATA packets from remote node | |
---|
59 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
60 | | data_num_tx_bytes_success | Total number of bytes successfully transmitted in DATA packets to remote node | |
---|
61 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
62 | | data_num_tx_bytes_total | Total number of bytes transmitted (successfully or not) in DATA packets to remote node | |
---|
63 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
64 | | data_num_rx_packets | Total number of DATA packets received from remote node | |
---|
65 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
66 | | data_num_tx_packets_success | Total number of DATA packets successfully transmitted to remote node | |
---|
67 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
68 | | data_num_tx_packets_total | Total number of DATA packets transmitted (successfully or not) to remote node | |
---|
69 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
70 | | data_num_tx_attempts | Total number of low-level attempts of DATA packets to remote node (includes re-transmissions) | |
---|
71 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
72 | | mgmt_num_rx_bytes | Total number of bytes received in management packets from remote node | |
---|
73 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
74 | | mgmt_num_tx_bytes_success | Total number of bytes successfully transmitted in management packets to remote node | |
---|
75 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
76 | | mgmt_num_tx_bytes_total | Total number of bytes transmitted (successfully or not) in management packets to remote node | |
---|
77 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
78 | | mgmt_num_rx_packets | Total number of management packets received from remote node | |
---|
79 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
80 | | mgmt_num_tx_packets_success | Total number of management packets successfully transmitted to remote node | |
---|
81 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
82 | | mgmt_num_tx_packets_total | Total number of management packets transmitted (successfully or not) to remote node | |
---|
83 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
84 | | mgmt_num_tx_attempts | Total number of low-level attempts of management packets to remote node (includes re-transmissions)| |
---|
85 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
86 | | latest_txrx_timestamp | System Time value of last transmission / reception | |
---|
87 | +-----------------------------+-----------------------------------------------------------------------------------------------------+ |
---|
88 | |
---|
89 | |
---|
90 | If the device_list is a single device, then a single dictionary or |
---|
91 | None is returned. If the device_list is a list of devices, then a |
---|
92 | list of dictionaries will be returned in the same order as the devices |
---|
93 | in the list. If any of the staistics are not there, None will be |
---|
94 | inserted in the list. If the device_list is not specified, then all |
---|
95 | the counts on the node will be returned. |
---|
96 | """ |
---|
97 | return super(WlanExpNodeIBSS, self).get_txrx_counts(device_list) |
---|
98 | |
---|
99 | |
---|
100 | def configure_bss(self, bssid=False, ssid=None, channel=None, beacon_interval=False, ht_capable=None): |
---|
101 | """Configure the BSS information of the node |
---|
102 | |
---|
103 | Each node is either a member of no BSS (colloquially "unassociated") |
---|
104 | or a member of one BSS. A node requires a minimum valid set of BSS |
---|
105 | information to be a member of a BSS. The minimum valid set of BSS |
---|
106 | information for an IBSS node is: |
---|
107 | |
---|
108 | #. BSSID: 48-bit MAC address |
---|
109 | #. Channel: Logical channel for Tx/Rx by BSS members |
---|
110 | #. SSID: Variable length string (ie the name of the network) |
---|
111 | #. Beacon Interval: Interval (in TUs) for beacons |
---|
112 | |
---|
113 | If a node is not a member of a BSS (i.e. ``n.get_network_info()`` returns |
---|
114 | ``None``), then the node requires all parameters of a minimum valid |
---|
115 | set of BSS information be specified (i.e. BSSID, Channel, SSID, and |
---|
116 | Beacon Interval). |
---|
117 | |
---|
118 | For an IBSS node, the BSSID must be locally administered. To create a |
---|
119 | locally administered BSSID, a utility method is provided in util.py: |
---|
120 | |
---|
121 | ``bssid = util.create_locally_administered_bssid(node.wlan_mac_address)`` |
---|
122 | |
---|
123 | See https://warpproject.org/trac/wiki/802.11/wlan_exp/bss |
---|
124 | for more documentation on BSS information / configuration. |
---|
125 | |
---|
126 | |
---|
127 | Args: |
---|
128 | bssid (int, str): 48-bit ID of the BSS either as a integer or |
---|
129 | colon delimited string of the form ``'01:23:45:67:89:ab'``. The |
---|
130 | ``bssid`` must be a valid locally administered BSSID. Use |
---|
131 | wlan_exp.util.create_locally_administered_bssid() to generate a valid |
---|
132 | locally administered BSSID based on the node's MAC address. |
---|
133 | ssid (str): SSID string (Must be 32 characters or less) |
---|
134 | channel (int): Channel number on which the BSS operates |
---|
135 | beacon_interval (int): Integer number of beacon Time Units in [10, 65534] |
---|
136 | (http://en.wikipedia.org/wiki/TU_(Time_Unit); a TU is 1024 microseconds); |
---|
137 | A value of None will disable beacons; A value of False will not |
---|
138 | update the current beacon interval. |
---|
139 | ht_capable (bool): Is the PHY mode HTMF (True) or NONHT (False)? |
---|
140 | """ |
---|
141 | import wlan_exp.util as util |
---|
142 | |
---|
143 | if (self.is_scanning() is True) and (bssid is None): |
---|
144 | print('Warning: network scan is still running when BSS was set to None. Use stop_active_scan if needed.') |
---|
145 | |
---|
146 | if bssid is not False: |
---|
147 | if bssid is not None: |
---|
148 | # Remeber the bssid argument, used in error checking below |
---|
149 | self.bssid = bssid |
---|
150 | if not util.is_locally_administered_bssid(bssid): |
---|
151 | msg = "IBSS BSSIDs must be 'locally administered'. Use \n" |
---|
152 | msg += " util.create_locally_administered_bssid() to \n" |
---|
153 | msg += " create a 'locally adminstered' BSSID." |
---|
154 | raise AttributeError(msg) |
---|
155 | |
---|
156 | resp_args = self.send_cmd(cmds.NodeConfigBSS(bssid=bssid, ssid=ssid, channel=channel, |
---|
157 | beacon_interval=beacon_interval, ht_capable=ht_capable)) |
---|
158 | |
---|
159 | # Process response arguments |
---|
160 | if (resp_args is not False): |
---|
161 | status = resp_args[0] |
---|
162 | msg = "ERROR:\n" |
---|
163 | ret_val = True |
---|
164 | |
---|
165 | # Check status |
---|
166 | if (status & cmds.ERROR_CONFIG_BSS_BSSID_INVALID): |
---|
167 | if type(self.bssid) in [int, long]: |
---|
168 | import wlan_exp.util as util |
---|
169 | self.bssid = util.mac_addr_to_str(self.bssid) |
---|
170 | msg += " BSSID {0} was invalid.\n".format(self.bssid) |
---|
171 | ret_val = False |
---|
172 | |
---|
173 | if (status & cmds.ERROR_CONFIG_BSS_BSSID_INSUFFICIENT_ARGUMENTS): |
---|
174 | msg += " Insufficient arguments to create BSS. Must provide:\n" |
---|
175 | if (bssid is False): |
---|
176 | msg += " BSSID\n" |
---|
177 | if (ssid is None): |
---|
178 | msg += " SSID\n" |
---|
179 | if (channel is None): |
---|
180 | msg += " CHANNEL\n" |
---|
181 | if (beacon_interval is False): |
---|
182 | msg += " BEACON_INTERVAL\n" |
---|
183 | ret_val = False |
---|
184 | |
---|
185 | if (status & cmds.ERROR_CONFIG_BSS_CHANNEL_INVALID): |
---|
186 | msg += " Channel {0} was invalid.\n".format(channel) |
---|
187 | ret_val = False |
---|
188 | |
---|
189 | if (status & cmds.ERROR_CONFIG_BSS_BEACON_INTERVAL_INVALID): |
---|
190 | msg += " Beacon interval {0} was invalid.\n".format(beacon_interval) |
---|
191 | ret_val = False |
---|
192 | |
---|
193 | if (status & cmds.ERROR_CONFIG_BSS_HT_CAPABLE_INVALID): |
---|
194 | msg += " HT capable {0} was invalid.\n".format(ht_capable) |
---|
195 | ret_val = False |
---|
196 | |
---|
197 | if not ret_val: |
---|
198 | print(msg) |
---|
199 | |
---|
200 | |
---|
201 | #------------------------------------------------------------------------- |
---|
202 | # Internal Node methods |
---|
203 | #------------------------------------------------------------------------- |
---|
204 | def _check_allowed_rate(self, mcs, phy_mode, verbose=False): |
---|
205 | """Check that rate parameters are allowed |
---|
206 | |
---|
207 | Args: |
---|
208 | mcs (int): Modulation and coding scheme (MCS) index |
---|
209 | phy_mode (str, int): PHY mode (from util.phy_modes) |
---|
210 | |
---|
211 | Returns: |
---|
212 | valid (bool): Are all parameters valid? |
---|
213 | """ |
---|
214 | # TODO: implement IBSS-specific rate checking here |
---|
215 | # Allow all supported rates for now |
---|
216 | |
---|
217 | return self._check_supported_rate(mcs, phy_mode, verbose) |
---|
218 | |
---|
219 | |
---|
220 | # End class |
---|