Skip to content

Commit c06c5d8

Browse files
committed
added performance tests
Signed-off-by: Mikhail Avramenko <[email protected]>
1 parent 1d3df12 commit c06c5d8

File tree

77 files changed

+61759
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+61759
-2
lines changed

.DS_Store

6 KB
Binary file not shown.

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ COPY . .
2323
RUN go build -o /bin/forwarder .
2424

2525
FROM build as test
26-
CMD go test -test.v ./...
26+
RUN apt-get update -y
27+
RUN apt-get install -y iperf3
28+
CMD go test -test.v ./... -bench=. -timeout 1h
2729

2830
FROM test as debug
2931
WORKDIR /build/internal/tests/

internal/tests/iperf/iperf.go

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
package iperf
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"github.com/edwarnicke/exechelper"
8+
"github.com/networkservicemesh/api/pkg/api/networkservice"
9+
"github.com/pkg/errors"
10+
"github.com/vishvananda/netns"
11+
"io"
12+
"net"
13+
"os"
14+
"strconv"
15+
"strings"
16+
"sync"
17+
)
18+
19+
type IperfResult struct {
20+
Start struct {
21+
Connected []struct {
22+
Socket int `json:"socket"`
23+
LocalHost string `json:"local_host"`
24+
LocalPort int `json:"local_port"`
25+
RemoteHost string `json:"remote_host"`
26+
RemotePort int `json:"remote_port"`
27+
} `json:"connected"`
28+
Version string `json:"version"`
29+
SystemInfo string `json:"system_info"`
30+
Timestamp struct {
31+
Time string `json:"time"`
32+
Timesecs int `json:"timesecs"`
33+
} `json:"timestamp"`
34+
ConnectingTo struct {
35+
Host string `json:"host"`
36+
Port int `json:"port"`
37+
} `json:"connecting_to"`
38+
Cookie string `json:"cookie"`
39+
TcpMssDefault int `json:"tcp_mss_default"`
40+
SockBufsize int `json:"sock_bufsize"`
41+
SndbufActual int `json:"sndbuf_actual"`
42+
RcvbufActual int `json:"rcvbuf_actual"`
43+
TestStart struct {
44+
Protocol string `json:"protocol"`
45+
NumStreams int `json:"num_streams"`
46+
Blksize int `json:"blksize"`
47+
Omit int `json:"omit"`
48+
Duration int `json:"duration"`
49+
Bytes int `json:"bytes"`
50+
Blocks int `json:"blocks"`
51+
Reverse int `json:"reverse"`
52+
Tos int `json:"tos"`
53+
} `json:"test_start"`
54+
} `json:"start"`
55+
Intervals []struct {
56+
Streams []struct {
57+
Socket int `json:"socket"`
58+
Start float64 `json:"start"`
59+
End float64 `json:"end"`
60+
Seconds float64 `json:"seconds"`
61+
Bytes int `json:"bytes"`
62+
BitsPerSecond float64 `json:"bits_per_second"`
63+
Omitted bool `json:"omitted"`
64+
Sender bool `json:"sender"`
65+
} `json:"streams"`
66+
Sum struct {
67+
Start float64 `json:"start"`
68+
End float64 `json:"end"`
69+
Seconds float64 `json:"seconds"`
70+
Bytes int `json:"bytes"`
71+
BitsPerSecond float64 `json:"bits_per_second"`
72+
Omitted bool `json:"omitted"`
73+
Sender bool `json:"sender"`
74+
} `json:"sum"`
75+
} `json:"intervals"`
76+
End struct {
77+
Streams []struct {
78+
Sender struct {
79+
Socket int `json:"socket"`
80+
Start int `json:"start"`
81+
End float64 `json:"end"`
82+
Seconds float64 `json:"seconds"`
83+
Bytes int `json:"bytes"`
84+
BitsPerSecond float64 `json:"bits_per_second"`
85+
Sender bool `json:"sender"`
86+
} `json:"sender"`
87+
Receiver struct {
88+
Socket int `json:"socket"`
89+
Start int `json:"start"`
90+
End float64 `json:"end"`
91+
Seconds float64 `json:"seconds"`
92+
Bytes int `json:"bytes"`
93+
BitsPerSecond float64 `json:"bits_per_second"`
94+
Sender bool `json:"sender"`
95+
} `json:"receiver"`
96+
} `json:"streams"`
97+
SumSent struct {
98+
Start int `json:"start"`
99+
End float64 `json:"end"`
100+
Seconds float64 `json:"seconds"`
101+
Bytes int `json:"bytes"`
102+
BitsPerSecond float64 `json:"bits_per_second"`
103+
Sender bool `json:"sender"`
104+
} `json:"sum_sent"`
105+
SumReceived struct {
106+
Start int `json:"start"`
107+
End float64 `json:"end"`
108+
Seconds float64 `json:"seconds"`
109+
Bytes int `json:"bytes"`
110+
BitsPerSecond float64 `json:"bits_per_second"`
111+
Sender bool `json:"sender"`
112+
} `json:"sum_received"`
113+
CpuUtilizationPercent struct {
114+
HostTotal float64 `json:"host_total"`
115+
HostUser float64 `json:"host_user"`
116+
HostSystem float64 `json:"host_system"`
117+
RemoteTotal float64 `json:"remote_total"`
118+
RemoteUser float64 `json:"remote_user"`
119+
RemoteSystem float64 `json:"remote_system"`
120+
} `json:"cpu_utilization_percent"`
121+
} `json:"end"`
122+
}
123+
124+
type ResultByIP struct {
125+
Ip string
126+
Result IperfResult
127+
}
128+
129+
type ResultTable struct {
130+
IperfTable map[string][]ResultByIP `json:"iperf_table"`
131+
Mut sync.Mutex
132+
Err []string
133+
}
134+
135+
func WriteFile(clientMech, endpointMech string, cN, eN int) error {
136+
dir := "results"
137+
_, err := os.Stat(dir)
138+
if os.IsNotExist(err){
139+
err := os.Mkdir(dir, 0755)
140+
if err != nil {
141+
return err
142+
}
143+
}
144+
145+
err = writeJson(&Result, dir, clientMech, endpointMech, cN, eN)
146+
if err != nil {
147+
return err
148+
}
149+
150+
err = writeCSV(&Result, dir, clientMech, endpointMech, cN, eN)
151+
if err != nil {
152+
return err
153+
}
154+
155+
//err = writeServerError(dir, clientMech, endpointMech, cN, eN)
156+
//if err != nil {
157+
// return err
158+
//}
159+
160+
//err = writeServerOutput(dir, clientMech, endpointMech, cN, eN)
161+
//if err != nil {
162+
// return err
163+
//}
164+
165+
return nil
166+
}
167+
168+
// write full result json, just in case
169+
func writeJson(table *ResultTable, dir, clientMech, endpointMech string, cN, eN int) error {
170+
filename := fmt.Sprintf("%v/%v_to_%v_%v_to_%v.json", dir, clientMech, endpointMech, cN, eN)
171+
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm)
172+
if err != nil {
173+
return err
174+
}
175+
176+
b, err := json.Marshal(table.IperfTable)
177+
if err != nil {
178+
return err
179+
}
180+
181+
_, err = file.Write(b)
182+
if err != nil {
183+
return err
184+
}
185+
186+
return nil
187+
}
188+
189+
// write result in csv processed for plotting in gnuplot
190+
func writeCSV(table *ResultTable, dir, clientMech, endpointMech string, cN, eN int) error{
191+
filename := fmt.Sprintf("%v/%v_to_%v_%v_to_%v.csv", dir, clientMech, endpointMech, cN, eN)
192+
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm)
193+
if err != nil {
194+
return err
195+
}
196+
var columns [][]string
197+
for key, val := range table.IperfTable {
198+
for _, v := range val {
199+
var sums []string
200+
for _, i := range v.Result.Intervals {
201+
sums = append(sums, strconv.Itoa(i.Sum.Bytes/(1024*1024)))
202+
}
203+
columns = append(columns, append([]string{key + "(" + v.Ip + ")" }, sums...))
204+
}
205+
}
206+
if len(columns) == 0 {
207+
return errors.New("empty result")
208+
}
209+
210+
var rows = make([][]string, len(columns[0]))
211+
for i, col := range columns {
212+
for j := range col {
213+
if len(rows[j]) == 0 {
214+
rows[j] = make([]string, len(columns[0]))
215+
}
216+
rows[j][i] = columns[i][j]
217+
}
218+
}
219+
220+
str := strings.Builder{}
221+
for i, r := range rows {
222+
str.WriteString(strconv.Itoa(i - 1) + "," + strings.Join(r, ",") + "\n")
223+
}
224+
225+
_, err = file.WriteString(str.String())
226+
if err != nil {
227+
return err
228+
}
229+
230+
return nil
231+
}
232+
233+
var Result = ResultTable{IperfTable: map[string][]ResultByIP{}, Err: []string{}}
234+
func Cmd(ipnet *net.IPNet, clientHandle netns.NsHandle, conn *networkservice.Connection) error {
235+
if ipnet == nil {
236+
return nil
237+
}
238+
239+
// start client
240+
var buff bytes.Buffer
241+
var errBuff strings.Builder
242+
iperfStr := fmt.Sprintf("iperf3 -t 60 -M 1400 -J -c %s", ipnet.IP.String())
243+
if err := exechelper.Run(iperfStr,
244+
exechelper.WithEnvirons(os.Environ()...),
245+
exechelper.WithStdout(io.MultiWriter(os.Stdout, &buff)),
246+
exechelper.WithStderr(io.MultiWriter(os.Stderr, &errBuff)),
247+
exechelper.WithNetNS(clientHandle),
248+
); err != nil {
249+
return errors.Wrapf(err, "failed to measure throughput with command %q", iperfStr)
250+
}
251+
252+
var res IperfResult
253+
err := json.Unmarshal(buff.Bytes(), &res)
254+
if err != nil {
255+
return err
256+
}
257+
258+
Result.Mut.Lock()
259+
Result.IperfTable[conn.Id] = append(Result.IperfTable[conn.Id], ResultByIP{Result: res, Ip: ipnet.IP.String()})
260+
Result.Err = append(Result.Err, errBuff.String())
261+
Result.Mut.Unlock()
262+
263+
return nil
264+
}
265+
266+
func StartServer(ipnet *net.IPNet, endpointHandle netns.NsHandle) error{
267+
iperfSrvStr := fmt.Sprintf("iperf3 -s --bind %s", ipnet.IP.String())
268+
err := exechelper.Run(iperfSrvStr,
269+
exechelper.WithEnvirons(os.Environ()...),
270+
exechelper.WithStdout(bytes.NewBuffer([]byte{})),
271+
exechelper.WithStderr(bytes.NewBuffer([]byte{})),
272+
exechelper.WithNetNS(endpointHandle))
273+
if err != nil {
274+
return err
275+
}
276+
277+
return nil
278+
}
279+
280+
func writeServerError(dir, clientMech, endpointMech string, cN, eN int) error {
281+
filename := fmt.Sprintf("%v/errors_%v_to_%v_%v_to_%v.txt", dir, clientMech, endpointMech, cN, eN)
282+
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm)
283+
if err != nil {
284+
return err
285+
}
286+
287+
_, err = file.WriteString(strings.Join(Result.Err, ";"))
288+
if err != nil {
289+
return err
290+
}
291+
292+
//for k,v := range srvr.serverErrors {
293+
// _, err = file.WriteString(k + "\n" + strings.Join(v, "\n"))
294+
// _, err = file.WriteString(strings.Repeat("|", 30))
295+
// if err != nil {
296+
// continue
297+
// }
298+
//}
299+
300+
return nil
301+
}
302+
303+
func writeServerOutput(dir, clientMech, endpointMech string, cN, eN int) error {
304+
filename := fmt.Sprintf("%v/server_output_%v_to_%v_%v_to_%v.txt", dir, clientMech, endpointMech, cN, eN)
305+
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm)
306+
if err != nil {
307+
return err
308+
}
309+
310+
if len(srvr.serverOutput) == 0 {
311+
return nil
312+
}
313+
314+
for k,v := range srvr.serverOutput {
315+
_, err = file.WriteString(k + "\n" + strings.Join(v, "\n"))
316+
_, err = file.WriteString(strings.Repeat("|", 30))
317+
if err != nil {
318+
continue
319+
}
320+
}
321+
322+
return nil
323+
}
324+
325+
var srvr = &srv{
326+
serverOutput: map[string][]string{},
327+
serverErrors: map[string][]string{},
328+
}
329+
type srv struct {
330+
serverErrors map[string][]string
331+
serverOutput map[string][]string
332+
mut sync.Mutex
333+
}

internal/tests/suite_combinatronics_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ import (
4747
)
4848

4949
func (f *ForwarderTestSuite) TestCombinations() {
50+
f.T().Skip()
51+
5052
_, prefix1, err := net.ParseCIDR("10.0.0.0/24")
5153
f.Require().NoError(err)
5254
_, prefix2, err := net.ParseCIDR("fc00::/7")

0 commit comments

Comments
 (0)