-
Notifications
You must be signed in to change notification settings - Fork 8
/
iperf.go
130 lines (122 loc) · 2.5 KB
/
iperf.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import (
"bufio"
"golang.org/x/crypto/ssh"
"io"
"io/ioutil"
"strconv"
"strings"
)
type DataPoint struct {
StartTime int
Sender string // the location of the sender (client)
Receiver string
Bps float64
TotalBytes int
Duration float64
Retransmits int
MaxRTT int
MinRTT int
MeanRTT int
}
type IperfOutput struct {
Start struct {
Timestamp struct {
Timesecs int
}
}
End struct {
Streams []struct {
Sender struct {
Bytes int
Seconds float64
Bits_per_second float64
Retransmits int
Max_rtt int
Min_rtt int
Mean_rtt int
}
}
}
}
func killIperf(c *ssh.Client) error {
pkill, err := c.NewSession()
if err != nil {
return RemoteError{err, "error creating session"}
}
pkill.Run("pkill iperf3")
pkill.Close()
return nil
}
func startIperfServer(c *ssh.Client, n int) error {
err := killIperf(c)
if err != nil {
return err
}
for idx := 0; idx < n; idx++ {
s, err := c.NewSession()
if err != nil {
return RemoteError{err, "error creating session"}
}
cmd := "iperf3 -s --forceflush -p " + strconv.Itoa(5201+idx) // forceflush or they won't output anything
// connect to stdout
stdout, err := s.StdoutPipe()
if err != nil {
return RemoteError{err, "error connecting to stdout"}
}
// start the server
err = s.Start(cmd)
if err != nil {
return RemoteError{err, "error starting iperf server"}
}
// wait for iperf to start
scanner := bufio.NewScanner(stdout)
found := false
for scanner.Scan() {
t := scanner.Text()
if strings.Contains(t, "Server listening") {
found = true
break
}
}
err = scanner.Err()
if err != nil {
return RemoteError{err, "error reading stdout"}
}
// start a goroutine that drains the stdout
go func() {
io.Copy(ioutil.Discard, stdout)
}()
if !found {
return RemoteError{nil, "iperf server crashed"}
}
}
return nil
}
func installIPerf(c *ssh.Client) error {
s, err := c.NewSession()
if err != nil {
return RemoteError{err, "error creating session"}
}
defer s.Close()
cmd := "apt-get install -y iperf3"
err = s.Run(cmd)
if err != nil {
return RemoteError{err, "error installing iperf3"}
}
return nil
}
func checkIPerf(c *ssh.Client) (bool, error) {
s, err := c.NewSession()
if err != nil {
return false, RemoteError{err, "error creating session"}
}
defer s.Close()
cmd := "iperf3 -v"
err = s.Run(cmd)
if err != nil {
return false, nil
} else {
return true, nil
}
}