diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 58b02fc..ebc7f24 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,22 +2,13 @@ - + + - - - - - - - - - - + - + @@ -117,15 +109,4 @@ true - - - - - file://$PROJECT_DIR$/tests/client/client.go - 57 - - - - \ No newline at end of file diff --git a/report.go b/report.go index 5d879df..810d1df 100644 --- a/report.go +++ b/report.go @@ -27,13 +27,15 @@ func (si *StreamInterval) String() string { } type StreamIntervalReport struct { - Socket int `json:"socket"` - StartInterval float32 `json:"start"` - EndInterval float32 `json:"end"` - Seconds float32 `json:"seconds"` - Bytes int `json:"bytes"` - BitsPerSecond float64 `json:"bits_per_second"` - Omitted bool `json:"omitted"` + Socket int `json:"socket"` + StartInterval float32 `json:"start"` + EndInterval float32 `json:"end"` + Seconds float32 `json:"seconds"` + Bytes int `json:"bytes"` + BitsPerSecond float64 `json:"bits_per_second"` + Retransmissions int `json:"retransmissions"` + CongestionWindow int `json:"congestion_window"` + Omitted bool `json:"omitted"` } func (sir *StreamIntervalReport) String() string { diff --git a/reporter.go b/reporter.go index 2d8d98c..43a53d1 100644 --- a/reporter.go +++ b/reporter.go @@ -1,18 +1,9 @@ package iperf -import ( - "fmt" - "github.com/BGrewell/tail" - "github.com/BGrewell/go-conversions" - "log" - "strconv" - "strings" -) - type Reporter struct { ReportingChannel chan *StreamIntervalReport - LogFile string - running bool + LogFile string + running bool } func (r *Reporter) Start() { @@ -25,68 +16,4 @@ func (r *Reporter) Stop() { close(r.ReportingChannel) } -func (r *Reporter) runLogProcessor() { - tailer, err := tail.TailFile(r.LogFile, tail.Config{ - Follow: true, - ReOpen: true, - Poll: true, - MustExist: true, - }) - if err != nil { - log.Fatalf("failed to tail log file: %v", err) - } - for line := range tailer.Lines { - // TODO: For now this only cares about individual streams it ignores the sum lines - if len(line.Text) > 5 { - id := line.Text[1:4] - stream, err := strconv.Atoi(strings.TrimSpace(id)) - if err != nil { - continue - } - fields := strings.Fields(line.Text[5:]) - if len(fields) >= 6 { - if fields[0] == "local" { - continue - } - timeFields := strings.Split(fields[0], "-") - start, err := strconv.ParseFloat(timeFields[0], 32) - if err != nil { - log.Printf("failed to convert start time: %s\n", err) - } - end, err := strconv.ParseFloat(timeFields[1], 32) - transferedStr := fmt.Sprintf("%s%s", fields[2], fields[3]) - transferedBytes, err := conversions.StringBitRateToInt(transferedStr) - if err != nil { - log.Printf("failed to convert units: %s\n", err) - } - transferedBytes = transferedBytes / 8 - rateStr := fmt.Sprintf("%s%s", fields[4], fields[5]) - rate, err := conversions.StringBitRateToInt(rateStr) - if err != nil { - log.Printf("failed to convert units: %s\n", err) - } - omitted := false - if len(fields) >= 7 && fields[6] == "(omitted)" { - omitted = true - } - report := &StreamIntervalReport{ - Socket: stream, - StartInterval: float32(start), - EndInterval: float32(end), - Seconds: float32(end - start), - Bytes: int(transferedBytes), - BitsPerSecond: float64(rate), - Omitted: omitted, - } - r.ReportingChannel <- report - } - } - - if !r.running { - return - } - } -} - - - +// runLogProcessor is OS specific because of differences in iperf on Windows and Linux diff --git a/reporter_linux.go b/reporter_linux.go new file mode 100644 index 0000000..4d27143 --- /dev/null +++ b/reporter_linux.go @@ -0,0 +1,118 @@ +package iperf + +import ( + "fmt" + "github.com/BGrewell/go-conversions" + "github.com/BGrewell/tail" + "log" + "strconv" + "strings" +) + +/* +Connecting to host 10.254.100.100, port 5201 +[ 4] local 192.168.3.182 port 54104 connected to 10.254.100.100 port 5201 +[ ID] Interval Transfer Bandwidth Retr Cwnd +[ 4] 0.00-1.00 sec 109 MBytes 913 Mbits/sec 13 634 KBytes (omitted) +[ 4] 1.00-2.00 sec 110 MBytes 927 Mbits/sec 7 550 KBytes (omitted) +[ 4] 2.00-3.00 sec 109 MBytes 918 Mbits/sec 6 559 KBytes (omitted) +[ 4] 3.00-4.00 sec 111 MBytes 930 Mbits/sec 6 690 KBytes (omitted) +[ 4] 4.00-5.00 sec 111 MBytes 933 Mbits/sec 0 803 KBytes (omitted) +[ 4] 5.00-6.00 sec 111 MBytes 933 Mbits/sec 6 673 KBytes (omitted) +[ 4] 6.00-7.00 sec 111 MBytes 932 Mbits/sec 6 605 KBytes (omitted) +[ 4] 7.00-8.00 sec 110 MBytes 925 Mbits/sec 0 732 KBytes (omitted) +[ 4] 8.00-9.00 sec 111 MBytes 932 Mbits/sec 0 840 KBytes (omitted) +[ 4] 9.00-10.00 sec 110 MBytes 923 Mbits/sec 6 690 KBytes (omitted) +[ 4] 0.00-1.00 sec 111 MBytes 928 Mbits/sec 6 618 KBytes +[ 4] 1.00-2.00 sec 111 MBytes 931 Mbits/sec 0 745 KBytes +[ 4] 2.00-3.00 sec 111 MBytes 929 Mbits/sec 11 614 KBytes +[ 4] 3.00-4.00 sec 110 MBytes 922 Mbits/sec 6 551 KBytes +[ 4] 4.00-5.00 sec 111 MBytes 933 Mbits/sec 6 519 KBytes +[ 4] 5.00-6.00 sec 111 MBytes 928 Mbits/sec 0 663 KBytes +[ 4] 6.00-7.00 sec 111 MBytes 932 Mbits/sec 0 783 KBytes +[ 4] 7.00-8.00 sec 111 MBytes 933 Mbits/sec 6 656 KBytes +[ 4] 8.00-9.00 sec 111 MBytes 933 Mbits/sec 6 598 KBytes +[ 4] 9.00-10.00 sec 110 MBytes 925 Mbits/sec 0 728 KBytes +[ 4] 10.00-11.00 sec 111 MBytes 933 Mbits/sec 0 839 KBytes +[ 4] 11.00-12.00 sec 109 MBytes 918 Mbits/sec 6 680 KBytes +[ 4] 12.00-12.24 sec 25.0 MBytes 888 Mbits/sec 0 711 KBytes +- - - - - - - - - - - - - - - - - - - - - - - - - +[ ID] Interval Transfer Bandwidth Retr +[ 4] 0.00-12.24 sec 1.32 GBytes 928 Mbits/sec 47 sender +[ 4] 0.00-12.24 sec 0.00 Bytes 0.00 bits/sec receiver + +iperf Done. + +*/ + +func (r *Reporter) runLogProcessor() { + tailer, err := tail.TailFile(r.LogFile, tail.Config{ + Follow: true, + ReOpen: true, + Poll: true, + MustExist: true, + }) + if err != nil { + log.Fatalf("failed to tail log file: %v", err) + } + for line := range tailer.Lines { + // TODO: For now this only cares about individual streams it ignores the sum lines + if len(line.Text) > 5 { + id := line.Text[1:4] + stream, err := strconv.Atoi(strings.TrimSpace(id)) + if err != nil { + continue + } + fields := strings.Fields(line.Text[5:]) + if len(fields) >= 6 { + if fields[0] == "local" { + continue + } + timeFields := strings.Split(fields[0], "-") + start, err := strconv.ParseFloat(timeFields[0], 32) + if err != nil { + log.Printf("failed to convert start time: %s\n", err) + } + end, err := strconv.ParseFloat(timeFields[1], 32) + transferedStr := fmt.Sprintf("%s%s", fields[2], fields[3]) + transferedBytes, err := conversions.StringBitRateToInt(transferedStr) + if err != nil { + log.Printf("failed to convert units: %s\n", err) + } + transferedBytes = transferedBytes / 8 + rateStr := fmt.Sprintf("%s%s", fields[4], fields[5]) + rate, err := conversions.StringBitRateToInt(rateStr) + if err != nil { + log.Printf("failed to convert units: %s\n", err) + } + retrans := strconv.Atoi(fields[6]) + cwndStr := fmt.Sprintf("%s%s", fields[7], fields[8]) + cwnd, err := conversions.StringBitRateToInt(cwndStr) + if err != nil { + log.Printf("failed to convert units: %s\n", err) + } + cwnd = cwnd / 8 + omitted := false + if len(fields) >= 10 && fields[9] == "(omitted)" { + omitted = true + } + report := &StreamIntervalReport{ + Socket: stream, + StartInterval: float32(start), + EndInterval: float32(end), + Seconds: float32(end - start), + Bytes: int(transferedBytes), + BitsPerSecond: float64(rate), + Retransmissions: retrans, + CongestionWindow: cwnd, + Omitted: omitted, + } + r.ReportingChannel <- report + } + } + + if !r.running { + return + } + } +} diff --git a/reporter_windows.go b/reporter_windows.go new file mode 100644 index 0000000..cb4c81d --- /dev/null +++ b/reporter_windows.go @@ -0,0 +1,73 @@ +package iperf + +import ( + "fmt" + "github.com/BGrewell/go-conversions" + "github.com/BGrewell/tail" + "log" + "strconv" + "strings" +) + +func (r *Reporter) runLogProcessor() { + tailer, err := tail.TailFile(r.LogFile, tail.Config{ + Follow: true, + ReOpen: true, + Poll: true, + MustExist: true, + }) + if err != nil { + log.Fatalf("failed to tail log file: %v", err) + } + for line := range tailer.Lines { + // TODO: For now this only cares about individual streams it ignores the sum lines + if len(line.Text) > 5 { + id := line.Text[1:4] + stream, err := strconv.Atoi(strings.TrimSpace(id)) + if err != nil { + continue + } + fields := strings.Fields(line.Text[5:]) + if len(fields) >= 6 { + if fields[0] == "local" { + continue + } + timeFields := strings.Split(fields[0], "-") + start, err := strconv.ParseFloat(timeFields[0], 32) + if err != nil { + log.Printf("failed to convert start time: %s\n", err) + } + end, err := strconv.ParseFloat(timeFields[1], 32) + transferedStr := fmt.Sprintf("%s%s", fields[2], fields[3]) + transferedBytes, err := conversions.StringBitRateToInt(transferedStr) + if err != nil { + log.Printf("failed to convert units: %s\n", err) + } + transferedBytes = transferedBytes / 8 + rateStr := fmt.Sprintf("%s%s", fields[4], fields[5]) + rate, err := conversions.StringBitRateToInt(rateStr) + if err != nil { + log.Printf("failed to convert units: %s\n", err) + } + omitted := false + if len(fields) >= 7 && fields[6] == "(omitted)" { + omitted = true + } + report := &StreamIntervalReport{ + Socket: stream, + StartInterval: float32(start), + EndInterval: float32(end), + Seconds: float32(end - start), + Bytes: int(transferedBytes), + BitsPerSecond: float64(rate), + Omitted: omitted, + } + r.ReportingChannel <- report + } + } + + if !r.running { + return + } + } +} diff --git a/shared.go b/shared.go index e0fe723..5a1b1bf 100644 --- a/shared.go +++ b/shared.go @@ -7,6 +7,7 @@ import ( ) type TestMode string + const ( MODE_JSON TestMode = "json" MODE_LIVE TestMode = "live" diff --git a/tests/client/client.go b/tests/client/client.go index ae3e4a9..867a3df 100644 --- a/tests/client/client.go +++ b/tests/client/client.go @@ -39,7 +39,7 @@ func main() { } // Method 1: Wait for the test to finish by pulling from the 'Done' channel which will block until something is put in or it's closed - <- c.Done + <-c.Done // Method 2: Poll the c.Running state and wait for it to be 'false' //for c.Running {