blob: e90828dd0569d92553a6a9b578f388b53c7c02a6 [file] [log] [blame]
// Copyright 2021 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"
"strconv"
"time"
"chromiumos/tast/common/network/ping"
"chromiumos/tast/common/wifi/security/wpa"
"chromiumos/tast/common/wifi/security/wpaeap"
"chromiumos/tast/ctxutil"
"chromiumos/tast/remote/bundles/cros/wifi/wifiutil"
remoteping "chromiumos/tast/remote/network/ping"
"chromiumos/tast/remote/wificell"
"chromiumos/tast/remote/wificell/hostapd"
"chromiumos/tast/remote/wificell/verifier"
"chromiumos/tast/testing"
"chromiumos/tast/testing/hwdep"
)
type pingParam struct {
opts []ping.Option
// Max packets lost per roaming round.
maxLoss int
}
func init() {
testing.AddTest(&testing.Test{
Func: RoamContPing,
Desc: "Send ping every 10ms and check how many packets are lost on average during roaming",
Contacts: []string{
"jck@semihalf.com", // Test author
"chromeos-wifi-champs@google.com", // WiFi oncall rotation; or http://b/new?component=893827
},
Attr: []string{"group:wificell", "wificell_perf", "wificell_unstable"},
ServiceDeps: []string{wificell.TFServiceName},
HardwareDeps: hwdep.D(hwdep.Wifi80211ac()),
Fixture: "wificellFixtWithCapture",
Timeout: time.Minute * 5, // The average test time doubled.
Vars: []string{"wifi.RoamContPing.rounds"},
Params: []testing.Param{{
Name: "none",
Val: wifiutil.ContParam{
Rounds: 50,
ApOpts: [2][]hostapd.Option{{hostapd.Channel(1), hostapd.Mode(hostapd.Mode80211g)},
{hostapd.Channel(157), hostapd.Mode(hostapd.Mode80211acPure), hostapd.HTCaps(hostapd.HTCapHT40Plus), hostapd.VHTCaps(hostapd.VHTCapSGI80),
hostapd.VHTChWidth(hostapd.VHTChWidth80), hostapd.VHTCenterChannel(155)}},
Param: pingParam{
opts: []ping.Option{ping.Count(1000), ping.Interval(0.01)},
// With 10ms ping interval, abnormal time without service would be 25 packets = 250ms.
maxLoss: 25,
},
},
}, {
Name: "psk",
Val: wifiutil.ContParam{
Rounds: 50,
ApOpts: [2][]hostapd.Option{{hostapd.Channel(1), hostapd.Mode(hostapd.Mode80211g)},
{hostapd.Channel(157), hostapd.Mode(hostapd.Mode80211acPure), hostapd.HTCaps(hostapd.HTCapHT40Plus), hostapd.VHTCaps(hostapd.VHTCapSGI80),
hostapd.VHTChWidth(hostapd.VHTChWidth80), hostapd.VHTCenterChannel(155)}},
SecConfFac: wpa.NewConfigFactory("chromeos", wpa.Mode(wpa.ModePureWPA2), wpa.Ciphers2(wpa.CipherCCMP)),
Param: pingParam{
opts: []ping.Option{ping.Count(1000), ping.Interval(0.01)},
maxLoss: 25,
},
},
}, {
Name: "ft_psk",
Val: wifiutil.ContParam{
Rounds: 50,
ApOpts: [2][]hostapd.Option{{hostapd.Channel(1), hostapd.Mode(hostapd.Mode80211g)},
{hostapd.Channel(157), hostapd.Mode(hostapd.Mode80211acPure), hostapd.HTCaps(hostapd.HTCapHT40Plus), hostapd.VHTCaps(hostapd.VHTCapSGI80),
hostapd.VHTChWidth(hostapd.VHTChWidth80), hostapd.VHTCenterChannel(155)}},
SecConfFac: wpa.NewConfigFactory("chromeos", wpa.Mode(wpa.ModePureWPA2), wpa.Ciphers2(wpa.CipherCCMP), wpa.FTMode(wpa.FTModePure)),
EnableFT: true,
Param: pingParam{
opts: []ping.Option{ping.Count(1000), ping.Interval(0.01)},
maxLoss: 25,
},
},
}, {
Name: "eap",
Val: wifiutil.ContParam{
Rounds: 50,
ApOpts: [2][]hostapd.Option{{hostapd.Channel(1), hostapd.Mode(hostapd.Mode80211g)},
{hostapd.Channel(157), hostapd.Mode(hostapd.Mode80211acPure), hostapd.HTCaps(hostapd.HTCapHT40Plus), hostapd.VHTCaps(hostapd.VHTCapSGI80),
hostapd.VHTChWidth(hostapd.VHTChWidth80), hostapd.VHTCenterChannel(155)}},
SecConfFac: wpaeap.NewConfigFactory(
wifiutil.Cert1.CACred.Cert, wifiutil.Cert1.ServerCred,
wpaeap.ClientCACert(wifiutil.Cert1.CACred.Cert), wpaeap.ClientCred(wifiutil.Cert1.ClientCred),
wpaeap.Mode(wpa.ModePureWPA2),
),
Param: pingParam{
opts: []ping.Option{ping.Count(1000), ping.Interval(0.01)},
maxLoss: 25,
},
},
}, {
Name: "ft_eap",
Val: wifiutil.ContParam{
Rounds: 50,
ApOpts: [2][]hostapd.Option{{hostapd.Channel(1), hostapd.Mode(hostapd.Mode80211g)},
{hostapd.Channel(157), hostapd.Mode(hostapd.Mode80211acPure), hostapd.HTCaps(hostapd.HTCapHT40Plus), hostapd.VHTCaps(hostapd.VHTCapSGI80),
hostapd.VHTChWidth(hostapd.VHTChWidth80), hostapd.VHTCenterChannel(155)}},
SecConfFac: wpaeap.NewConfigFactory(
wifiutil.Cert1.CACred.Cert, wifiutil.Cert1.ServerCred,
wpaeap.ClientCACert(wifiutil.Cert1.CACred.Cert), wpaeap.ClientCred(wifiutil.Cert1.ClientCred),
wpaeap.Mode(wpa.ModePureWPA2), wpaeap.FTMode(wpa.FTModePure),
),
EnableFT: true,
Param: pingParam{
opts: []ping.Option{ping.Count(1000), ping.Interval(0.01)},
maxLoss: 25,
},
},
}},
})
}
func RoamContPing(ctx context.Context, s *testing.State) {
tf := s.FixtValue().(*wificell.TestFixture)
param := s.Param().(wifiutil.ContParam)
// Allow override
var rounds int
roundsStr, ok := s.Var("wifi.RoamContPing.rounds")
if !ok {
rounds = param.Rounds
} else {
var err error
rounds, err = strconv.Atoi(roundsStr)
if err != nil {
s.Fatal("Failed to convert value, err: ", err)
}
}
ctx, ct, finish := wifiutil.ContinuityTestInitialSetup(ctx, s, tf)
defer finish()
ctx, cancel := ctxutil.Shorten(ctx, 10*time.Second)
defer cancel()
var vf *verifier.Verifier
var resultAssertF func(context.Context, []verifier.ResultType)
pingF := func(ctx context.Context) (verifier.ResultType, error) {
iface, err := tf.ClientInterface(ctx)
if err != nil {
s.Fatal("DUT: failed to get the client WiFi interface: ", err)
}
opts := param.Param.(pingParam).opts
// Bind ping used in all WiFi Tests to WiFiInterface. Otherwise if the
// WiFi interface is not up yet they will be routed through the Ethernet
// interface. Also see b/225205611 for details.
opts = append(opts, ping.BindAddress(true), ping.SourceIface(iface))
// We need more result data than a simple tf.PingFromDUT(), so we use a separate runner.
pr := remoteping.NewRemoteRunner(s.DUT().Conn())
res, err := pr.Ping(ctx, wifiutil.ServerIP(), opts...)
if err != nil {
testing.ContextLog(ctx, "ping error: ", err)
return verifier.ResultType{}, err
}
testing.ContextLogf(ctx, "Continuity: ping statistics=%+v", res)
return verifier.ResultType{Data: res, Timestamp: time.Now()}, nil
}
resultAssertF = func(ctx context.Context, results []verifier.ResultType) {
var sent, received int
for i, ret := range results {
pingData := ret.Data.(*ping.Result)
testing.ContextLogf(ctx, "Iteration %d: End Time=%s, Packets lost=%d",
i+1, ret.Timestamp.Format("15:04:05.000"), pingData.Sent-pingData.Received)
sent += pingData.Sent
received += pingData.Received
}
loss := sent - received
testing.ContextLogf(ctx, "Total packets lost=%d/%d (%d per round)",
loss, sent, loss/rounds)
if loss > rounds*param.Param.(pingParam).maxLoss {
s.Fatal("Loss threshold exceeded")
}
}
vf = verifier.NewVerifier(ctx, pingF)
defer vf.Finish()
ctx, cancel = ctxutil.Shorten(ctx, time.Second)
defer cancel()
ctx, destroy := ct.ContinuityTestSetupFinalize(ctx, s)
defer destroy()
ctx, cancel = ctxutil.Shorten(ctx, time.Second)
defer cancel()
vf.StartJob()
for i := 0; i < rounds; i++ {
ct.ContinuityRound(ctx, s, i)
}
results, err := vf.StopJob()
if err != nil {
s.Fatal("Error while receiving verification results, err: ", err)
return
}
resultAssertF(ctx, results)
}