blob: c7928f77536de4cb5074eead51216bacc4acf533 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package wifi
import (
"context"
"fmt"
"reflect"
"github.com/google/gopacket/layers"
"chromiumos/tast/remote/bundles/cros/wifi/wifiutil"
"chromiumos/tast/remote/network/ip"
"chromiumos/tast/remote/wificell"
"chromiumos/tast/remote/wificell/hostapd"
"chromiumos/tast/remote/wificell/pcap"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: ConnectScan,
Desc: "Verifies that the 802.11 probe frames with expected SSIDs are seen over-the-air when connecting to WiFi",
Contacts: []string{
"chromeos-wifi-champs@google.com", // WiFi oncall rotation; or http://b/new?component=893827
},
Attr: []string{"group:wificell", "wificell_func"},
ServiceDeps: []string{wificell.TFServiceName},
Fixture: "wificellFixtWithCapture",
Params: []testing.Param{
{
Name: "hidden",
Val: []hostapd.Option{
// Use 2.4G band as some devices sets no_IR on 5GHz channels. See http://b/173633813.
hostapd.Channel(1),
hostapd.Mode(hostapd.Mode80211nPure),
hostapd.HTCaps(hostapd.HTCapHT40),
hostapd.Hidden(),
},
},
{
Name: "visible",
Val: []hostapd.Option{
hostapd.Channel(1), // We have visible_vht for 5G band, use 2.4G band here.
hostapd.Mode(hostapd.Mode80211nPure),
hostapd.HTCaps(hostapd.HTCapHT40),
},
},
{
// For coverage of 5G and VHT setting.
Name: "visible_vht",
Val: []hostapd.Option{
hostapd.Channel(149),
hostapd.Mode(hostapd.Mode80211acPure),
hostapd.VHTChWidth(hostapd.VHTChWidth80),
hostapd.VHTCenterChannel(155),
hostapd.VHTCaps(hostapd.VHTCapSGI80),
hostapd.HTCaps(hostapd.HTCapHT40Plus),
},
},
},
})
}
func ConnectScan(ctx context.Context, s *testing.State) {
tf := s.FixtValue().(*wificell.TestFixture)
ctx, restore, err := tf.WifiClient().DisableMACRandomize(ctx)
if err != nil {
s.Fatal("Failed to disable MAC randomization: ", err)
}
defer func() {
if err := restore(); err != nil {
s.Error("Failed to restore MAC randomization: ", err)
}
}()
// Get the MAC address of WiFi interface.
iface, err := tf.ClientInterface(ctx)
if err != nil {
s.Fatal("Failed to get WiFi interface of DUT: ", err)
}
ipr := ip.NewRemoteRunner(s.DUT().Conn())
mac, err := ipr.MAC(ctx, iface)
if err != nil {
s.Fatal("Failed to get MAC of WiFi interface: ", err)
}
apOps := s.Param().([]hostapd.Option)
pcapPath, apConf, err := wifiutil.ConnectAndCollectPcap(ctx, tf, apOps)
if err != nil {
s.Fatal("Failed to collect packet: ", err)
}
s.Log("Start analyzing pcap")
filters := []pcap.Filter{
pcap.Dot11FCSValid(),
pcap.TransmitterAddress(mac),
pcap.TypeFilter(layers.LayerTypeDot11MgmtProbeReq, nil),
}
packets, err := pcap.ReadPackets(pcapPath, filters...)
if err != nil {
s.Fatal("Failed to read packets: ", err)
}
s.Logf("Total %d probe requests found", len(packets))
ssidSet := make(map[string]struct{})
for _, p := range packets {
layer := p.Layer(layers.LayerTypeDot11MgmtProbeReq)
if layer == nil {
s.Fatal("Found packet without PrboeReq layer")
}
ssid, err := pcap.ParseProbeReqSSID(layer.(*layers.Dot11MgmtProbeReq))
if err != nil {
continue
}
ssidSet[ssid] = struct{}{}
}
expectedSSIDs := map[string]struct{}{
"": {},
apConf.SSID: {},
}
if apConf.Hidden {
// For hidden network, we expect both SSIDs.
if !reflect.DeepEqual(ssidSet, expectedSSIDs) {
formatMapKeys := func(m map[string]struct{}) string {
var keys []string
for k := range m {
keys = append(keys, k)
}
return fmt.Sprintf("%q", keys)
}
s.Fatalf("Got set of SSIDs %s, want %s", formatMapKeys(ssidSet), formatMapKeys(expectedSSIDs))
}
} else {
// For visible network, we expect wildcard SSID, but it is not guaranteed.
for ssid := range ssidSet {
if _, ok := expectedSSIDs[ssid]; !ok {
s.Errorf("Found unexpected SSID=%q", ssid)
}
}
}
}