Skip to content

Commit

Permalink
Parse max_elapsed_time as microseconds (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristinaleonr authored Oct 10, 2024
2 parents eb775c4 + e832115 commit 0c1cfe3
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 23 deletions.
59 changes: 40 additions & 19 deletions handler/ndt7.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ func (c *Client) NDT7Download(rw http.ResponseWriter, req *http.Request) {
}

// Get client parameters.
params, err := getParams(req.URL.Query())
params, err := GetParams(req.URL.Query())
if err != nil {
log.Errorf("Invalid parameters: %v", req.URL.Query())
rw.WriteHeader(http.StatusBadRequest)
return
}

// Get data.
data, err := getData(conn)
Expand Down Expand Up @@ -75,40 +80,56 @@ func (c *Client) NDT7Download(rw http.ResponseWriter, req *http.Request) {
}
}

func getData(conn *websocket.Conn) (*model.ArchivalData, error) {
ci := netx.ToConnInfo(conn.UnderlyingConn())
uuid, err := ci.GetUUID()
if err != nil {
return nil, err
}
data := &model.ArchivalData{
UUID: uuid,
}
return data, nil
}

func getParams(urlValues url.Values) (*sender.Params, error) {
// GetParams interprets and returns the client parameters.
func GetParams(urlValues url.Values) (*sender.Params, error) {
params := &sender.Params{}

for name, values := range urlValues {
value := values[0]
name = strings.TrimPrefix(name, "client_")

switch name {
case static.EarlyExitParameterName:
bytes, _ := strconv.ParseInt(value, 10, 64)
bytes, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return nil, err
}
params.MaxBytes = bytes * 1000000 // Convert MB to bytes.
case static.MaxCwndGainParameterName:
cwnd, _ := strconv.ParseUint(value, 10, 32)
cwnd, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return nil, err
}
params.MaxCwndGain = uint32(cwnd)
case static.MaxElapsedTimeParameterName:
time, _ := strconv.ParseInt(value, 10, 64)
params.MaxElapsedTime = time
time, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return nil, err
}
params.MaxElapsedTime = time * 1e6 // Convert seconds to microseconds.
case static.ImmediateExitParameterName:
params.ImmediateExit, _ = strconv.ParseBool(value)
immExit, err := strconv.ParseBool(value)
if err != nil {
return nil, err
}
params.ImmediateExit = immExit
}
}
return params, nil
}

func getData(conn *websocket.Conn) (*model.ArchivalData, error) {
ci := netx.ToConnInfo(conn.UnderlyingConn())
uuid, err := ci.GetUUID()
if err != nil {
return nil, err
}
data := &model.ArchivalData{
UUID: uuid,
}
return data, nil
}

// setupResult creates an NDT7Result from the given conn.
func setupResult(conn *websocket.Conn) *data.NDT7Result {
// NOTE: unless we plan to run the NDT server over different protocols than TCP,
Expand Down
76 changes: 76 additions & 0 deletions handler/ndt7_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import (
"net/http"
"net/url"
"os"
"reflect"
"testing"
"time"

"github.com/gorilla/websocket"
"github.com/m-lab/go/testingx"
"github.com/m-lab/ndt-server/ndt7/spec"
"github.com/m-lab/packet-test/handler"
"github.com/m-lab/packet-test/pkg/ndt7/sender"
"github.com/m-lab/packet-test/static"
"github.com/m-lab/packet-test/testdata"
)
Expand Down Expand Up @@ -50,3 +53,76 @@ func simpleDownload(ctx context.Context, t *testing.T, conn *websocket.Conn) err
// We only read one message, so this is an early close.
return conn.Close()
}

func Test_getParams(t *testing.T) {
type args struct {
urlValues url.Values
}
tests := []struct {
name string
vals url.Values
want *sender.Params
wantErr bool
}{
{
name: static.EarlyExitParameterName,
vals: url.Values{
static.EarlyExitParameterName: []string{"10"}, // 10 MB.
},
want: &sender.Params{
MaxBytes: 10000000, // 10000000 Bytes.
},
wantErr: false,
},
{
name: static.MaxCwndGainParameterName,
vals: url.Values{
static.MaxCwndGainParameterName: []string{"512"},
},
want: &sender.Params{
MaxCwndGain: 512,
},
wantErr: false,
},
{
name: static.MaxElapsedTimeParameterName,
vals: url.Values{
static.MaxElapsedTimeParameterName: []string{"5"}, // 5 seconds.
},
want: &sender.Params{
MaxElapsedTime: 5000000, // 5000000 microseconds.
},
wantErr: false,
},
{
name: static.ImmediateExitParameterName,
vals: url.Values{
static.ImmediateExitParameterName: []string{"true"},
},
want: &sender.Params{
ImmediateExit: true,
},
wantErr: false,
},
{
name: "error",
vals: url.Values{
static.EarlyExitParameterName: []string{"foo"},
},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := handler.GetParams(tt.vals)
if (err != nil) != tt.wantErr {
t.Errorf("handler.GetParams() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("handler.GetParams() = %v, want %v", got, tt.want)
}
})
}
}
8 changes: 4 additions & 4 deletions pkg/ndt7/sender/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (

// Params defines the parameters for the sender to end the test early.
type Params struct {
MaxBytes int64 // TCPInfo.BytesAcked is of type int64.
MaxElapsedTime int64 // TCPInfo.ElapsedTime is of type int64.
MaxBytes int64 // TCPInfo.BytesAcked is of type int64 (bytes).
MaxElapsedTime int64 // TCPInfo.ElapsedTime is of type int64 (microseconds).
MaxCwndGain uint32 // BBRInfo.CwndGain is of type uint32.
ImmediateExit bool
}
Expand Down Expand Up @@ -175,7 +175,7 @@ func terminateTest(p *Params, m model.Measurement) bool {
switch {
case p.isMaxCwndGainLimit() && p.isMaxElapsedTimeLimit():
if p.isMaxCwndGainDone(m) && p.isMaxElapsedTimeDone(m) {
log.Infof("sender: terminating test after %d CwndGain and %d ElapsedTime (s)", m.BBRInfo.CwndGain, m.TCPInfo.ElapsedTime)
log.Infof("sender: terminating test after %d CwndGain and %d ElapsedTime (µs)", m.BBRInfo.CwndGain, m.TCPInfo.ElapsedTime)
return true
}
case p.isMaxCwndGainLimit() && p.isEarlyExitLimit():
Expand All @@ -190,7 +190,7 @@ func terminateTest(p *Params, m model.Measurement) bool {
log.Infof("sender: terminating test after %d BytesAcked", m.TCPInfo.BytesAcked)
return true
case p.isMaxElapsedTimeLimit() && p.isMaxElapsedTimeDone(m):
log.Infof("sender: terminating test after %d ElapsedTime (s)", m.TCPInfo.ElapsedTime)
log.Infof("sender: terminating test after %d ElapsedTime (µs)", m.TCPInfo.ElapsedTime)
return true
}

Expand Down

0 comments on commit 0c1cfe3

Please sign in to comment.