def setup_experiment():
    print("\nExperimental Setup:")
    
    # Set the rate of both nodes to 26 Mbps (mcs = 3, phy_mode = 'HTMF')
    mcs       = 3
    phy_mode  = util.phy_modes['HTMF']
    rate_info = util.get_rate_info(mcs, phy_mode)
    
    # Put each node in a known, good state
    for node in nodes:
        node.set_tx_rate_unicast(mcs, phy_mode, curr_assoc=True, new_assoc=True)
        node.log_configure(log_full_payloads=False)
        node.reset(log=True, txrx_counts=True, ltg=True, queue_data=True) # Do not reset associations/bss_info
        node.configure_bss(channel=CHANNEL)
    
    # Add the current time to all the nodes
    util.broadcast_cmd_write_time_to_logs(network_config)
Beispiel #2
0
        #  - the PHY mode matches phy_mode in the above loop
        #  - the MCS matches the mcs in the above loop
        tx_low_idx = ((log_tx_low['phy_mode'] == TX_CONSTS.phy_mode[phy_mode])
                      & (log_tx_low['mcs'] == mcs))

        # Extract arrays for each PHY mode
        tx_low_entries = log_tx_low[tx_low_idx]

        # Calculate retransmissions
        #    Any packet whose "attempt_number" is larger than 1 is a retransmission
        retrans = np.sum(tx_low_entries['attempt_number'] > 1)
        total_retrans += retrans

        # Print info
        try:
            rate_info = wlan_exp_util.get_rate_info(mcs, phy_mode)
            rate_str = wlan_exp_util.rate_info_to_str(rate_info)
            print("{0:30} {1:15} {2:15}".format(rate_str, len(tx_low_entries),
                                                retrans))
        except:
            # Do nothing with unsupported PHY modes
            pass

print("\nTotal Retransmissions: {0:d}".format(total_retrans))

###############################################################################
# Example 2: Calculate total number of packets and bytes transmitted to each
#            distinct MAC address for each of the MAC addresses in the header
#

# Skip this example if the log doesn't contain TX events
Beispiel #3
0
print("\nExperimental Setup:")

# Configure the AP to reject authentication requests from wireless clients
#    - Uncomment this line to block any wireless associations during the experiment
# n_ap.set_authentication_address_filter(allow='NONE')

# Set association state
#     - Configure AP BSS
#     - Create Associatiion between AP and STA
n_ap.configure_bss(ssid=SSID, channel=CHANNEL, beacon_interval=BEACON_INTERVAL)
n_ap.add_association(n_sta)

# Set the rate of both nodes to 18 Mbps (mcs = 3, phy_mode = 'NONHT')
mcs = 3
phy_mode = util.phy_modes['NONHT']
rate_info = util.get_rate_info(mcs, phy_mode)

# Put each node in a known, good state
for node in nodes:
    node.set_tx_rate_unicast(mcs, phy_mode, curr_assoc=True, new_assoc=True)
    node.reset(log=True, txrx_counts=True, ltg=True,
               queue_data=True)  # Do not reset associations/bss_info

    # Get some additional information about the experiment
    bss_info = node.get_bss_info()
    channel = bss_info['channel']

    print("\n{0}:".format(node.name))
    print("    Channel  = {0}".format(
        util.channel_info_to_str(util.get_channel_info(channel))))
    print("    Rate     = {0}".format(util.rate_info_to_str(rate_info)))
    print("ERROR: Node configurations did not match requirements of script.\n")
    print("    Ensure two nodes are ready, either:\n")
    print("        1) one using the AP design, one using the STA design, or\n")
    print("        2) two using the IBSS design\n")
    sys.exit(0)

#-------------------------------------------------------------------------
#  Setup
#

print("\nExperimental Setup:")

# Set the rate of both nodes to 26 Mbps (mcs = 3, phy_mode = 'HTMF')
mcs       = 3
phy_mode  = util.phy_modes['HTMF']
rate_info = util.get_rate_info(mcs, phy_mode)

# Put each node in a known, good state
for node in [node1, node2]:
    node.set_tx_rate_unicast(mcs, phy_mode, curr_assoc=True, new_assoc=True)
    node.reset(log=True, txrx_counts=True, ltg=True, queue_data=True) # Do not reset associations/bss_info
    bss_info = node.get_bss_info()

    msg = ""
    if (node == node1):
        msg += "\nNode 1: \n"
    if (node == node2):
        msg += "\nNode 2: \n"

    msg += "    Description = {0}\n".format(node.description)
    msg += "    Channel     = {0}\n".format(util.channel_info_to_str(util.get_channel_info(bss_info['channel'])))
Beispiel #5
0
def calc_tx_time(mcs, phy_mode, payload_length, phy_samp_rate):
    """Calculates the duration of an 802.11 transmission given its rate and 
    payload length.

    Args:
        mcs (int or list of ints):             Modulation and coding scheme (MCS) index
        phy_mode (str, int or list of strs or ints):   PHY mode (from util.phy_modes)
        payload_length (int or list of ints):  Nnumber of bytes in the payload
        phy_sample_rate (int or list of ints): PHY sample rate; only (10, 20, 40) are valid

    This method accounts only for PHY overhead (preamble, SIGNAL field, etc.). 
    It does *not* account for MAC overhead. The payload_length argument must 
    include any MAC fields (typically a 24-byte MAC header plus 4 byte FCS).

    All 4 arguments are required. The dimensions of the 4 arguments must match. To calculate
    the duration of a single packet, call this method with scalaer integer arguments. To 
    calculate the duration of many packets, call this method with iterables (typically
    Numpy arrays) of integer values. When calling this method with arrays the lengths
    of the 4 arrays must be equal.
    """
    import numpy as np
    import wlan_exp.util as util    
    
    # Check for valid phy_samp_rate values
    if(not np.all( (phy_samp_rate == 10) + (phy_samp_rate == 20) + (phy_samp_rate == 40) )):
        raise AttributeError('Invalid phy_samp_rate - all phy_samp_rate values must be 10, 20 or 40')

    # Convert samp rates to lut indexes
    #  Integer division by 15 is shortcut to map (10, 20, 40) to (0, 1, 2)
    samp_rate_idx = (phy_samp_rate // 15)

    # Lookup tables of waveform section durations in microseconds, indexed by samp_rate
    lut_T_PREAMBLE = (8, 16, 32)
    lut_T_SIG = (2, 4, 8)
    lut_T_SYM = (2, 4, 8)
    lut_T_EXT = (6, 6, 6)

    T_PREAMBLE = np.choose(samp_rate_idx, lut_T_PREAMBLE)
    T_SIG = np.choose(samp_rate_idx, lut_T_SIG)
    T_SYM = np.choose(samp_rate_idx, lut_T_SYM)
    T_EXT = np.choose(samp_rate_idx, lut_T_EXT)

    # (mcs, phy_mode) encodes number of data bits per symbol
    try:
        # LUT implementation (~2 sec for 150K entries)
        #   - Construct NDBPS lookup table to be used during processing
        # 
        # TODO:  This implementation is dependent on the MCS range that is 
        #     not defined in wlan_exp.util.  This function will need to be 
        #     updated if more MCS values are defined.
        ndbps_lut = {}
        
        for m in range(0, 8):
            phy_mode_lut = {}
            
            for p in util.phy_modes.values():
                try:
                    phy_mode_lut[p] = util.get_rate_info(m, p, 20)['NDBPS']
                except:
                    # Do nothing for undefined values
                    pass
                    
            ndbps_lut[m] = phy_mode_lut

        ndbps = np.array([ndbps_lut[m][p] for i, (m, p) in enumerate(zip(mcs, phy_mode))])
        
                
        # Naive implementation (~7 sec for 150K entries)
        #   - Get rate info for each entry to extract NDBPS
        # ndbps = np.array([util.get_rate_info(m, p, phy_samp_rate)['NDBPS'] for i, (m, p) in enumerate(zip(mcs, phy_mode))])
    except TypeError:
        ndbps = util.get_rate_info(mcs, phy_mode, phy_samp_rate)['NDBPS']

    # Compute the number of symbols in DATA field
    #  - 16 = LEN_SERVICE (2 bytes)
    #  - 6  = LEN_TAIL (6 bits)
    #  - np.ceil() infers any PAD bits

    num_data_syms = np.ceil((16.0 + 6.0 + 8*payload_length) / ndbps)

    # HTMF waveforms have 4 extra preamble symbols
    #  HT-SIG1, HT-SIG2, HT-STF, HT-LTF
    num_ht_preamble_syms = 4 * (phy_mode == util.phy_modes['HTMF'])

    T_TOT = T_PREAMBLE + T_SIG + (T_SYM * num_ht_preamble_syms) + (T_SYM * num_data_syms) + T_EXT

    return T_TOT
    tx_entries = log_tx[tx_idx]
    rx_entries = log_rx[rx_idx]

    # Extract arrays of just the MCS indexes
    tx_entries_mcs = tx_entries['mcs']
    rx_entries_mcs = rx_entries['mcs']

    # Initialize an array to count number of packets per MCS index
    #   MAC uses MCS indexes 0:7 to encode OFDM rates
    tx_entries_mcs_counts = np.bincount(tx_entries_mcs, minlength=8)
    rx_entries_mcs_counts = np.bincount(rx_entries_mcs, minlength=8)

    # Print counts per PHY rate
    for i, (tx_c, rx_c) in enumerate(zip(tx_entries_mcs_counts, rx_entries_mcs_counts)):
        try:
            rate_info = wlan_exp_util.get_rate_info(i, phy_mode)
            rate_str  = wlan_exp_util.rate_info_to_str(rate_info)
            print("  {0:30}    {1:10} {2:10}".format(rate_str, tx_c, rx_c))
        except:
            # Do nothing with unsupported PHY modes
            pass


###############################################################################
# Example 2: Calculate total number of packets and bytes transmitted to each
#            distinct MAC address for each of the MAC addresses in the header

# Skip this example if the log doesn't contain TX events
if('TX_HIGH' in log_np.keys()):
    # Extract all OFDM transmissions
    log_tx = log_np['TX_HIGH']
Beispiel #7
0
def calc_tx_time(mcs, phy_mode, payload_length, phy_samp_rate):
    """Calculates the duration of an 802.11 transmission given its rate and 
    payload length. Returns duration of PHY transmission in microseconds.

    Args:
        mcs (int or list of ints):             Modulation and coding scheme (MCS) index
        phy_mode (str, int or list of strs or ints):   PHY mode (from util.phy_modes)
        payload_length (int or list of ints):  Nnumber of bytes in the payload
        phy_sample_rate (int or list of ints): PHY sample rate; only (10, 20, 40) are valid

    This method accounts only for PHY overhead (preamble, SIGNAL field, etc.). 
    It does *not* account for MAC overhead. The payload_length argument must 
    include any MAC fields (typically a 24-byte MAC header plus 4 byte FCS).

    All 4 arguments are required. The dimensions of the 4 arguments must match. To calculate
    the duration of a single packet, call this method with scalaer integer arguments. To 
    calculate the duration of many packets, call this method with iterables (typically
    Numpy arrays) of integer values. When calling this method with arrays the lengths
    of the 4 arrays must be equal.
    """
    import numpy as np
    import wlan_exp.util as util

    # Check for valid phy_samp_rate values
    if (not np.all((phy_samp_rate == 10) + (phy_samp_rate == 20) +
                   (phy_samp_rate == 40))):
        raise AttributeError(
            'Invalid phy_samp_rate - all phy_samp_rate values must be 10, 20 or 40'
        )

    # Convert samp rates to lut indexes
    #  Integer division by 15 is shortcut to map (10, 20, 40) to (0, 1, 2)
    samp_rate_idx = (phy_samp_rate // 15)

    # Lookup tables of waveform section durations in microseconds, indexed by samp_rate
    lut_T_PREAMBLE = (8, 16, 32)
    lut_T_SIG = (2, 4, 8)
    lut_T_SYM = (2, 4, 8)
    lut_T_EXT = (6, 6, 6)

    T_PREAMBLE = np.choose(samp_rate_idx, lut_T_PREAMBLE)
    T_SIG = np.choose(samp_rate_idx, lut_T_SIG)
    T_SYM = np.choose(samp_rate_idx, lut_T_SYM)
    T_EXT = np.choose(samp_rate_idx, lut_T_EXT)

    # (mcs, phy_mode) encodes number of data bits per symbol
    try:
        # LUT implementation (~2 sec for 150K entries)
        #   - Construct NDBPS lookup table to be used during processing
        #
        # TODO:  This implementation is dependent on the MCS range that is
        #     not defined in wlan_exp.util.  This function will need to be
        #     updated if more MCS values are defined.
        ndbps_lut = {}

        for m in range(0, 8):
            phy_mode_lut = {}

            for p in util.phy_modes.values():
                try:
                    phy_mode_lut[p] = util.get_rate_info(m, p, 20)['NDBPS']
                except:
                    # Do nothing for undefined values
                    pass

            ndbps_lut[m] = phy_mode_lut

        ndbps = np.array(
            [ndbps_lut[m][p] for i, (m, p) in enumerate(zip(mcs, phy_mode))])

        # Naive implementation (~7 sec for 150K entries)
        #   - Get rate info for each entry to extract NDBPS
        # ndbps = np.array([util.get_rate_info(m, p, phy_samp_rate)['NDBPS'] for i, (m, p) in enumerate(zip(mcs, phy_mode))])
    except TypeError:
        ndbps = util.get_rate_info(mcs, phy_mode, phy_samp_rate)['NDBPS']

    # Compute the number of symbols in DATA field
    #  - 16 = LEN_SERVICE (2 bytes)
    #  - 6  = LEN_TAIL (6 bits)
    #  - np.ceil() infers any PAD bits

    num_data_syms = np.ceil((16.0 + 6.0 + 8 * payload_length) / ndbps)

    # HTMF waveforms have 4 extra preamble symbols
    #  HT-SIG1, HT-SIG2, HT-STF, HT-LTF
    num_ht_preamble_syms = 4 * (phy_mode == util.phy_modes['HTMF'])

    T_TOT = T_PREAMBLE + T_SIG + (T_SYM * num_ht_preamble_syms) + (
        T_SYM * num_data_syms) + T_EXT

    return T_TOT