| #!/usr/bin/python |
| import time |
| import autochannel |
| import wgdata |
| from wvtest import wvtest |
| |
| |
| @wvtest.wvtest |
| def OverlapsTest(): |
| wvtest.WVPASSGE(autochannel.Overlaps20(2412, 2411), 2) # partial overlap |
| wvtest.WVPASSEQ(autochannel.Overlaps20(2412, 2412), 1) # clean overlap |
| wvtest.WVPASS(autochannel.Overlaps20(2412, 2393)) |
| wvtest.WVFAIL(autochannel.Overlaps20(2412, 2392)) |
| wvtest.WVPASS(autochannel.Overlaps20(2412, 2412)) |
| wvtest.WVPASS(autochannel.Overlaps20(2412, 2417)) |
| wvtest.WVPASS(autochannel.Overlaps20(2412, 2422)) |
| wvtest.WVPASS(autochannel.Overlaps20(2412, 2427)) |
| wvtest.WVPASS(autochannel.Overlaps20(2412, 2431)) |
| wvtest.WVFAIL(autochannel.Overlaps20(2412, 2432)) |
| |
| wvtest.WVPASS(autochannel.Overlaps40(2412, 2432)) |
| wvtest.WVPASS(autochannel.Overlaps40(2412, 2451)) |
| |
| # This one is non-obvious! Because on 2.4 GHz, 40 MHz wide channels are so |
| # flexible, any 40 MHz channel overlaps with any other 40 MHz channel, even |
| # if the primary channels are >= 40 MHz apart. For example, imagine an |
| # AP on (2412,2432) and another on (2432,2452). They will definitely |
| # interfere with each other. |
| # |
| # To narrow this down, we cheat. Overlaps40 treats the first parameter |
| # as a verbatim 20 MHz channel, and searches for the second parameter |
| # as part of a channel group. |
| wvtest.WVFAIL(autochannel.Overlaps40(2412, 2452)) |
| |
| # On the other hand, on 5 GHz, 40 MHz channel pairs are better defined, |
| # so there are far fewer risky combinations. |
| wvtest.WVFAIL(autochannel.Overlaps40(5745, 5725)) |
| wvtest.WVPASS(autochannel.Overlaps40(5745, 5765)) |
| wvtest.WVPASS(autochannel.Overlaps40(5745, 5784)) |
| wvtest.WVFAIL(autochannel.Overlaps40(5745, 5785)) |
| |
| # There are no 80 MHz channels on 2.4 GHz, so it's always the same answer |
| # as for 40 MHz. |
| wvtest.WVPASS(autochannel.Overlaps80(2412, 2432)) |
| wvtest.WVFAIL(autochannel.Overlaps80(2412, 2452)) |
| wvtest.WVFAIL(autochannel.Overlaps80(2412, 2462)) |
| |
| # On 5 GHz, 80 MHz pairs exist and are well-defined. |
| wvtest.WVFAIL(autochannel.Overlaps80(5745, 5725)) |
| wvtest.WVPASS(autochannel.Overlaps80(5745, 5765)) |
| wvtest.WVPASS(autochannel.Overlaps80(5745, 5784)) |
| wvtest.WVPASS(autochannel.Overlaps80(5745, 5785)) |
| |
| |
| @wvtest.wvtest |
| def LegalCombosTest(): |
| r = list(autochannel.LegalCombos(allowed_freqs=[], |
| candidates=autochannel.C_ALL)) |
| wvtest.WVPASSEQ(r, []) |
| r = list(autochannel.LegalCombos(allowed_freqs=[2432], |
| candidates=autochannel.C_ALL)) |
| wvtest.WVPASSEQ(r, [(2432,)]) |
| r = list(autochannel.LegalCombos(allowed_freqs=[2412, 2432, 2452], |
| candidates=autochannel.C_ALL)) |
| wvtest.WVPASSEQ(r, [(2412, 2432), (2412,), (2432,), (2432, 2452,), (2452,)]) |
| r = list(autochannel.LegalCombos(allowed_freqs=[2412, 2432, 2452], |
| candidates=autochannel.C_24MAIN)) |
| wvtest.WVPASSEQ(r, [(2412, 2432), (2412,), (2432,)]) |
| r = list(autochannel.LegalCombos(allowed_freqs=range(5745, 5826, 20), |
| candidates=autochannel.C_ALL)) |
| wvtest.WVPASSEQ(r, [(5745, 5765, 5785, 5805), |
| (5745, 5765), |
| (5785, 5805), |
| (5745,), |
| (5765,), |
| (5785,), |
| (5805,), |
| (5825,)]) |
| |
| |
| def GenState(bssfreqs, surveys): |
| me = wgdata.Me(now=0, |
| uptime_ms=0, |
| consensus_key='', |
| mac='', |
| flags=0) |
| bss_list = [wgdata.BSS(is_ours=False, mac='', freq=freq, rssi=-40, |
| flags=0, last_seen=time.time(), cap=0, phy=0, |
| reg='US') |
| for freq in bssfreqs] |
| survey_list = [wgdata.Channel(freq=freq, noise_dbm=0, |
| observed_ms=observed_ms, busy_ms=busy_ms) |
| for freq, observed_ms, busy_ms in surveys] |
| return wgdata.State(me=me, seen_bss=bss_list, channel_survey=survey_list, |
| assoc=[], arp=[]) |
| |
| |
| @wvtest.wvtest |
| def AutoChannelTest(): |
| combos = list(autochannel.LegalCombos(range(2412, 2500, 5), |
| autochannel.C_24ANY)) |
| combos_20 = [i for i in combos if len(i) == 1] |
| |
| # With no other APs and all idle channels, every channel is equally likely. |
| results = set() |
| for i in range(10000): |
| results.add(autochannel.SoloChooseChannel( |
| GenState([], []), combos, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=None).primary_freq) |
| if len(results) == 11: |
| break |
| wvtest.WVPASSGE(len(results), 11) |
| |
| # Every channel is equally likely, but with hysteresis, we pick the |
| # same channel every time. |
| result1 = autochannel.SoloChooseChannel( |
| GenState([], []), combos, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=None).primary_freq |
| results = set() |
| for i in range(100): |
| results.add(autochannel.SoloChooseChannel( |
| GenState([], []), combos, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=result1).primary_freq) |
| print results |
| wvtest.WVPASSEQ(len(results), 1) |
| |
| result1 = autochannel.SoloChooseChannel( |
| GenState([], []), combos, use_primary_spreading=False, |
| use_active_time=True, hysteresis_freq=None).primary_freq |
| results = set() |
| for i in range(100): |
| results.add(autochannel.SoloChooseChannel( |
| GenState([], []), combos, use_primary_spreading=False, |
| use_active_time=True, hysteresis_freq=result1).primary_freq) |
| print results |
| wvtest.WVPASSEQ(len(results), 1) |
| |
| # With a single AP at 2432, the system should try for a 40 MHz channel |
| # that either doesn't include 2432 (impossible) or aligns so it |
| # at least doesn't partially overlap with 2432. That means one of the |
| # two channels should be 2432. And we want it to *not* be the primary |
| # channel, so that 20 MHz traffic is non-interfering. |
| r = autochannel.SoloChooseChannel( |
| GenState([2432], []), combos, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASSNE(r.primary_freq, 2432) |
| wvtest.WVPASSEQ(len(r.group), 2) |
| wvtest.WVPASS(r.primary_freq in [2412, 2452]) |
| wvtest.WVPASSEQ(r.count_80, 1) |
| |
| # With use_primary_spreading=False, the logic above should all work the |
| # same, but now it should choose 2432 as the primary every time. |
| r = autochannel.SoloChooseChannel( |
| GenState([2432], []), combos, use_primary_spreading=False, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASSEQ(r.primary_freq, 2432) |
| wvtest.WVPASSEQ(len(r.group), 2) |
| wvtest.WVPASSEQ(r.count_80, 1) |
| |
| # A bad scenario: two existing APs too close together in the middle of the |
| # spectrum. There's no way to get a 40 MHz channel without some kind of |
| # partial overlap. With use_primary_spreading=True, at least the primary |
| # channel will be clear. |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2437], []), combos, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASS(r.primary_freq in [2412, 2457, 2462]) |
| # TODO(apenwarr): really we should switch to 20 MHz wide in this case. |
| # Anything to avoid a partial overlap. But we don't yet. |
| # wvtest.WVPASSEQ(len(r.group), 1) |
| wvtest.WVPASSGT(r.count_80, 1) |
| wvtest.WVPASSGT(r.count_40, 1) |
| wvtest.WVPASSEQ(r.count_20, 0) |
| |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2437], []), combos, use_primary_spreading=False, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASS(r.primary_freq in [2432, 2437]) |
| wvtest.WVPASSGT(r.count_80, 1) |
| wvtest.WVPASSGT(r.count_40, 1) |
| wvtest.WVPASSGT(r.count_20, 1) |
| |
| # When we force to a 20 MHz channel, it should not have any overlap, |
| # regardless of use_primary_spreading. |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2437], []), combos_20, use_primary_spreading=False, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASS(r.primary_freq in [2412, 2457, 2462]) |
| wvtest.WVPASSEQ(r.count_20, 0) |
| |
| # If there are two APs on 2432, it's better to partially overlap with |
| # those than with the one AP on 2437. |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2432, 2437], []), combos, use_primary_spreading=False, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASSEQ(r.primary_freq, 2432) |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2432, 2437], []), combos, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASSEQ(r.primary_freq, 2412) |
| # Even when we force 20 MHz channels, only 2412 is the right match. |
| # The system considers 2412+2432, 2417+2437, 2432+2452, and 2437+2457 are |
| # all in use, some of them twice. 2412 has the fewest *partial* overlaps. |
| # (This can be improved if we teach waveguide about HT40+ vs HT40-.) |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2432, 2437], []), combos_20, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASS(r.primary_freq in [2412, 2452, 2457, 2462]) |
| |
| # Check that a busy channel overrides other logic. |
| # With 2412 ruled out, 2452 is the next best match. |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2432, 2437], [(2412, 1000, 100)]), |
| combos_20, use_primary_spreading=True, |
| use_active_time=True, hysteresis_freq=None) |
| print r |
| wvtest.WVPASSEQ(r.primary_freq, 2452) |
| |
| # Make sure use_active_time=False causes us to ignore busy channels. |
| r = autochannel.SoloChooseChannel( |
| GenState([2432, 2432, 2437], [(2412, 1000, 100)]), |
| combos_20, use_primary_spreading=True, |
| use_active_time=False, hysteresis_freq=None) |
| print r |
| wvtest.WVPASSEQ(r.primary_freq, 2412) |
| |
| if __name__ == '__main__': |
| wvtest.wvtest_main() |