source: ReferenceDesigns/w3_802.11/python/wlan_exp/ltg.py

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

1.8.0 release wlan-exp

File size: 19.4 KB
Line 
1# -*- coding: utf-8 -*-
2"""
3------------------------------------------------------------------------------
4Mango 802.11 Reference Design Experiments Framework
5    - Local Traffic Generation (LTG)
6------------------------------------------------------------------------------
7License:   Copyright 2019 Mango Communications, Inc. All rights reserved.
8           Use and distribution subject to terms in LICENSE.txt
9------------------------------------------------------------------------------
10
11This module provides definitions for Local Traffic Generation (LTG) on
12wlan_exp nodes.
13
14It is assumed that users will extend these classes to create their own
15LTG flow configurations.  When an LTG component is serialized, it follows
16the following structure:
17
18+------------+------------+---------------------------------+
19| Word       | Bits       | Function                        |
20+============+============+=================================+
21| [0]        |  [31:16]   | Type                            |
22+------------+------------+---------------------------------+
23| [0]        |  [15:0]    | Length (number of 32 bit words) |
24+------------+------------+---------------------------------+
25| [1:length]              | Parameters                      |
26+------------+------------+---------------------------------+
27
28When a LTG flow configuration is serialized, the schedule is serialized
29first and then the payload.
30"""
31
32from wlan_exp.info import InfoStruct
33import wlan_exp.util as util
34
35__all__ = ['Schedule', 'SchedulePeriodic', 'ScheduleUniformRandom',
36           'Payload', 'PayloadFixed', 'PayloadUniformRandom', 'PayloadControlResponse',
37           'FlowConfig', 'FlowConfigCBR', 'FlowConfigCTS', 'FlowConfigRandomRandom']
38
39
40# LTG Schedule IDs - must match corresponding values in wlan_mac_ltg.h
41LTG_SCHED_TYPE_PERIODIC                = 1
42LTG_SCHED_TYPE_UNIFORM_RAND            = 2
43
44
45# LTG Payload IDs - must match corresponding values in wlan_mac_ltg.h
46LTG_PYLD_TYPE_FIXED                    = 1
47LTG_PYLD_TYPE_UNIFORM_RAND             = 2
48LTG_PYLD_TYPE_ALL_ASSOC_FIXED          = 3
49LTG_PYLD_TYPE_CTRL_RESP                = 4
50
51# LTG Payload Min/Max
52#
53#   Currently, the minimum payload size is determined by the size of the LTG
54# header in the payload (as of 0.96, the LTG header contains the LLC header,
55# a 64-bit unique sequence number and a 32-bit LTG ID).  Currently, the maximum
56# payload size is 1500 bytes.  This is a relatively arbitrary amount chosen
57# because 1) in 0.96 the 802.11 phy cannot transmit more than 1600 bytes total
58# per packet; 2) 1500 bytes is about the size of a standard Ethernet MTU.  If
59# sizes outside the range are requested, the functions will print a warning and
60# adjust the value to the appropriate boundary.
61#
62LTG_PYLD_MIN                           = 20
63LTG_PYLD_MAX                           = 1500
64
65
66# LTG action constants - must match corresponding values in wlan_mac_ltg.h
67LTG_REMOVE_ALL                         = 0xFFFFFFFF
68LTG_START_ALL                          = 0xFFFFFFFF
69LTG_STOP_ALL                           = 0xFFFFFFFF
70
71#-----------------------------------------------------------------------------
72# LTG Schedules
73#-----------------------------------------------------------------------------
74class Schedule(InfoStruct):
75    """Base class for LTG Schedules."""
76    ltg_type = None
77
78    def __init__(self, field_defs):
79        super(Schedule, self).__init__(field_sets=None, field_defs=field_defs)
80
81    def enforce_min_resolution(self, resolution):
82        """Updates time intervals in the schedule configuration for the minimum interval
83        implemented by the node. Interval/duration values will be rounded down
84        to the nearest multiple of the node's LTG polling interval.
85
86        Subclasses of the Schedule class must implement their own verson of this method.
87
88        Args: resolution (int):  Resolution of the schedule
89        """
90        raise NotImplementedError
91
92class SchedulePeriodic(Schedule):
93    """LTG Schedule that will generate a payload every 'interval' seconds, stopping
94    after 'duration' seconds. Both arguments are float seconds. These values are
95    converted to microseconds for the command message to the node.
96
97    Args:
98
99    interval (float): Interval between packets in float seconds; actual packet
100        creation interval will be quantized to the LTG polling interval in CPU
101        High (typically 64 usec) usec.
102
103    duration (float, optional):    Duration of the traffic flow in float
104        seconds
105    """
106
107    # Must match _ltg_sched_periodic_params_otw typedef
108    struct_fields = [
109        ('interval', 'I', 'uint32', 'Interval between packet creation, in microseconds'),
110        ('duration', 'Q', 'uint64', 'Duration for traffic flow, in microseconds'),
111    ]
112
113    def __init__(self, interval, duration=None):
114        super(SchedulePeriodic, self).__init__(field_defs=self.struct_fields)
115
116        self.ltg_type = LTG_SCHED_TYPE_PERIODIC
117       
118        # Convert argument from float seconds to integer microseconds
119        self['interval'] = int(float(interval) * 10**6)
120
121        if duration is None:
122            # LTG schedule runs forever by default
123            self['duration'] = 0
124        else:
125            # Convert argument from float seconds to integer microseconds
126            self['duration'] = int(float(duration) * 10**6)
127
128    def enforce_min_resolution(self, resolution):
129        """Enforce the minimum resolution on the Schedule.
130
131        Args:
132            resolution (int):  Resolution of the schedule
133        """
134        temp_interval = (self['interval'] // resolution) * resolution
135        if (temp_interval != self['interval']):
136            # Set to True to print warning message when adjusting interval
137            if (False):
138                msg  = "WARNING:  Cannot schedule LTG with interval: {0} us\n".format(self['interval'])
139                msg += "    Minimum LTG resolution is {0} us.\n".format(resolution)
140                msg += "    Adjusting interval to {0} us".format(temp_interval)
141                print(msg)
142            self['interval'] = temp_interval
143
144# End Class WlanExpLTGSchedPeriodic
145
146
147class ScheduleUniformRandom(Schedule):
148    """LTG Schedule that will generate a payload a uniformly random time
149    between min_interval and max_interval microseconds.
150
151    Args:
152        min_interval (float):          Minimum interval between packets (in float seconds);
153                                       actual packet creation interval will be quantized
154                                       to the interval of the fast timer in CPU High.
155                                       Currently this interval is 64 usec.
156        max_interval (float):          Maximum interval between packets (in float seconds);
157                                       actual packet creation interval will be quantized
158                                       to the interval of the fast timer in CPU High.
159                                       Currently this interval is 64 usec.
160        duration (float, optional):    Duration of the traffic flow (in float seconds)
161    """
162    # Must match _ltg_sched_uniform_rand_params_otw typedef
163    struct_fields = [
164        ('min_interval', 'I', 'uint32', 'Minimum interval between packet creation, in microseconds'),
165        ('max_interval', 'I', 'uint32', 'Maximum interval between packet creation, in microseconds'),
166        ('duration', 'Q', 'uint64', 'Duration for traffic flow, in microseconds'),
167    ]
168
169    def __init__(self, min_interval, max_interval, duration=None):
170        super(ScheduleUniformRandom, self).__init__(field_defs=self.struct_fields)
171
172        self.ltg_type     = LTG_PYLD_TYPE_UNIFORM_RAND
173
174        # Convert intervals from float seconds to integer usec
175        self['min_interval'] = int(float(min_interval) * 10**6)
176        self['max_interval'] = int(float(max_interval) * 10**6)
177
178        if duration is None:
179            # Default duration runs forever
180            self['duration'] = 0
181        else:
182            self['duration'] = int(float(duration) * 10**6)
183
184    def enforce_min_resolution(self, resolution):
185        """Enforce the minimum resolution on the Schedule.
186
187        Args:
188            resolution (int):  Resolution of the scheduler in usec
189        """
190        # Apply the scheduler resolution to all interval fields
191        for f in ['min_interval', 'max_interval']:
192            temp_interval = (self[f] // resolution) * resolution
193            if (temp_interval != self[f]):
194                if (False):
195                    msg  = "WARNING:  Cannot schedule LTG with {0} = {1} usec\n".format(f, self[f])
196                    msg += "    Minimum LTG resolution is {0} usec.\n".format(resolution)
197                    msg += "    Adjusting {0} to {1} usec".format(f, temp_interval)
198                    print(msg)
199            self[f] = temp_interval
200
201#-----------------------------------------------------------------------------
202# LTG Payloads
203#-----------------------------------------------------------------------------
204class Payload(InfoStruct):
205    """Base class for LTG Payloads."""
206    ltg_type = None
207
208    def __init__(self, field_defs):
209        # InfoStruct constructor accepts either pre-defined fields in Info.py via 'field_sets'
210        #  or caller-specified fields via 'field_defs'
211        super(Payload, self).__init__(field_sets=None, field_defs=field_defs)
212
213    def validate_length(self, length):
214        """Contrains a requested length to the min/max supported LTG payload lengths
215        """
216        msg  = "WARNING:  Adjusting LTG Payload length from {0} ".format(length)
217
218        if (length < LTG_PYLD_MIN):
219            msg += "to {0} (min).".format(LTG_PYLD_MIN)
220            print(msg)
221            return LTG_PYLD_MIN
222
223        if (length > LTG_PYLD_MAX):
224            msg += "to {0} (max).".format(LTG_PYLD_MAX)
225            print(msg)
226            return LTG_PYLD_MAX
227
228        return length
229
230class PayloadFixed(Payload):
231    """LTG payload that will generate a fixed payload of the given length.
232
233    Args:
234        dest_addr (int):   Destination MAC address
235        length (int):      Minimum length of the LTG payload (in bytes)
236
237    """
238    # Must match ltg_pyld_fixed typedef
239    struct_fields = [
240        ('type',      'I',  'uint32', 'LTG Payload spec type'),
241        ('dest_addr', '6s', '6uint8', 'MAC address for destination of LTG flow'),
242        ('length',    'H',  'uint16', 'Length of payload in bytes for LTG packets'),
243    ]
244
245    def __init__(self, dest_addr, length):
246        super(PayloadFixed, self).__init__(field_defs=self.struct_fields)
247
248        self['type'] = LTG_PYLD_TYPE_FIXED
249        self['dest_addr'] = util.mac_addr_to_byte_str(dest_addr)
250        self['length'] = self.validate_length(length)
251
252class PayloadControlResponse(Payload):
253    """LTG payload that will generate an ACK or CTS.
254
255    Args:
256        dest_addr (int):   Destination MAC address
257        subtype (int): 0 for CTS, 1 for ACK
258        duration (int): duration/ID value (ignored in ACK)
259
260    """
261    # Must match ltg_pyld_ctrl_resp typedef
262    struct_fields = [
263        ('type',      'I',  'uint32', 'LTG Payload spec type'),
264        ('dest_addr', '6s', '6uint8', 'MAC address for destination of LTG flow'),
265        ('subtype',   'H',  'uint16', 'Subtype, 0 for CTS, 1 for ACK'),
266        ('duration',  'H',  'uint16', 'DURATION value for MAC header, ignored for ACKs'),
267    ]
268
269    def __init__(self, dest_addr, subtype, duration):
270        super(PayloadControlResponse, self).__init__(field_defs=self.struct_fields)
271
272        self['type'] = LTG_PYLD_TYPE_CTRL_RESP
273        self['dest_addr'] = util.mac_addr_to_byte_str(dest_addr)
274        self['subtype'] = subtype
275        self['duration'] = duration
276
277class PayloadUniformRandom(Payload):
278    """LTG payload that will generate a payload with uniformly random size
279    between min_length and max_length bytes.
280
281    Args:
282        dest_addr (int):       Destination MAC address
283        min_length (int):      Minimum length of the LTG payload (in bytes)
284        max_length (int):      Maximum length of the LTG payload (in bytes)
285    """
286
287    # Must match ltg_pyld_uniform_rand typedef
288    struct_fields = [
289        ('type',      'I',  'uint32', 'LTG Payload spec type'),
290        ('dest_addr', '6s', '6uint8', 'MAC address for destination of LTG flow'),
291        ('min_length', 'H', 'uint16', 'Minimum LTG payload length, in bytes'),
292        ('max_length', 'H', 'uint16', 'Maximum LTG payload length, in bytes'),
293    ]
294
295    def __init__(self, dest_addr, min_length, max_length):
296        super(PayloadUniformRandom, self).__init__(field_defs=self.struct_fields)
297
298        self['type'] = LTG_PYLD_TYPE_UNIFORM_RAND
299        self['dest_addr'] = util.mac_addr_to_byte_str(dest_addr)
300        self['min_length'] = self.validate_length(min_length)
301        self['max_length'] = self.validate_length(max_length)
302
303class PayloadAllAssocFixed(Payload):
304    """LTG payload that will generate a fixed payload of the given length
305    to all associated deivces.
306
307    Args:
308        length (int):      Length of the LTG payload (in bytes)
309    """
310    # Must match ltg_pyld_all_assoc_fixed_t typedef
311    struct_fields = [
312        ('type',   'I', 'uint32', 'LTG Payload spec type'),
313        ('length', 'H', 'uint16', 'LTG payload length, in bytes'),
314    ]
315
316    def __init__(self, length):
317        super(PayloadAllAssocFixed, self).__init__(field_defs=self.struct_fields)
318
319        self['type']   = LTG_PYLD_TYPE_ALL_ASSOC_FIXED
320        self['length'] = self.validate_length(length)
321
322#-----------------------------------------------------------------------------
323# LTG Flow Configurations
324#-----------------------------------------------------------------------------
325class FlowConfig(object):
326    """Base class for LTG Flow Configurations."""
327    ltg_schedule = None
328    ltg_payload  = None
329
330    def serialize(self):
331        """Converts the FlowConfig object to a byte array suitable for inclusion
332        in a wlan_exp command payload
333        """
334
335        # Concatenate and serialize the schedule and payload InfoStructs
336        r = self.ltg_schedule + self.ltg_payload
337        return r.serialize()
338
339    def enforce_min_resolution(self, resolution):
340        """Enforce the minimum resolution on time intervals in the LTG Schedule.
341
342        Args:
343            resolution (int):  Minimum time interval supported by hardware, in usec
344        """
345        self.ltg_schedule.enforce_min_resolution(resolution)
346
347
348class FlowConfigCBR(FlowConfig):
349    """Class to implement a Constant Bit Rate LTG flow configuration to a given device.
350
351    Args:
352        dest_addr (int):      Destination MAC address
353        payload_length (int): Length of the LTG payload (in bytes)
354        interval (float):     Interval between packets (in float seconds);
355                              actual packet creation interval will be quantized
356                              to the interval of the fast timer in CPU High.
357                              Currently this interval is 64 usec.
358        duration (float):     Duration of the traffic flow (in float seconds)
359    """
360    def __init__(self, dest_addr, payload_length, interval, duration=None):
361        self.ltg_schedule = SchedulePeriodic(interval, duration)
362        self.ltg_payload  = PayloadFixed(dest_addr, payload_length)
363
364# End Class FlowConfigCBR
365
366class FlowConfigCTS(FlowConfig):
367    """Class to implement a CTS flow configuration to a given device.
368
369    Args:
370        dest_addr (int):      Destination MAC address
371        interval (float):     Interval between packets (in float seconds);
372                              actual packet creation interval will be quantized
373                              to the interval of the fast timer in CPU High.
374                              Currently this interval is 64 usec.
375        duration (float):     Duration of the traffic flow (in float seconds)
376        duration_id (int):    Value to be included in CTS Duration/ID field
377    """
378    def __init__(self, dest_addr, interval, duration=None, duration_id=None):
379        self.ltg_schedule = SchedulePeriodic(interval, duration)
380        self.ltg_payload  = PayloadControlResponse(dest_addr, 0, duration_id) #The 0 represents a CTS
381
382# End Class FlowConfigCTS
383
384class FlowConfigACK(FlowConfig):
385    """Class to implement a ACK flow configuration to a given device.
386
387    Args:
388        dest_addr (int):      Destination MAC address
389        interval (float):     Interval between packets (in float seconds);
390                              actual packet creation interval will be quantized
391                              to the interval of the fast timer in CPU High.
392                              Currently this interval is 64 usec.
393        duration (float):     Duration of the traffic flow (in float seconds)
394    """
395    def __init__(self, dest_addr, interval, duration=None):
396        self.ltg_schedule = SchedulePeriodic(interval, duration)
397        self.ltg_payload  = PayloadControlResponse(dest_addr, 1, 0) #The 1 represents a CTS
398
399# End Class FlowConfigCTS
400
401
402class FlowConfigAllAssocCBR(FlowConfig):
403    """Class to implement a Constant Bit Rate LTG flow configuration to all associated
404    devices.
405
406    Args:
407        payload_length (int): Length of the LTG payload (in bytes)
408        interval (float):     Interval between packets (in float seconds);
409                              actual packet creation interval will be quantized
410                              to the interval of the fast timer in CPU High.
411                              Currently this interval is 64 usec.
412        duration (float):     Duration of the traffic flow (in float seconds)
413    """
414    def __init__(self, payload_length, interval, duration=None):
415        self.ltg_schedule = SchedulePeriodic(interval, duration)
416        self.ltg_payload  = PayloadAllAssocFixed(payload_length)
417
418# End Class FlowConfigAllAssocCBR
419
420class FlowConfigRandomRandom(FlowConfig):
421    """Class to implement an LTG flow configuration with random period and random
422    sized payload to a given device.
423
424    Args:
425        dest_addr (int):               Destination MAC address
426        min_payload_length (int):      Minimum length of the LTG payload (in bytes)
427        max_payload_length (int):      Maximum length of the LTG payload (in bytes)
428        min_interval (float):          Minimum interval between packets (in float seconds);
429                                       actual packet creation interval will be quantized
430                                       to the interval of the fast timer in CPU High.
431                                       Currently this interval is 64 usec.
432        max_interval (float):          Maximum interval between packets (in float seconds)
433                                       actual packet creation interval will be quantized
434                                       to the interval of the fast timer in CPU High.
435                                       Currently this interval is 64 usec.
436        duration (float, optional):    Duration of the traffic flow (in float seconds)
437    """
438    def __init__(self, dest_addr, min_payload_length, max_payload_length, min_interval, max_interval, duration=None):
439        self.ltg_schedule = ScheduleUniformRandom(min_interval, max_interval, duration)
440        self.ltg_payload  = PayloadUniformRandom(dest_addr, min_payload_length, max_payload_length)
441
442# End Class FlowConfigRandom
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
Note: See TracBrowser for help on using the repository browser.