blob: 5e6533ef8b190b407d603c305e1f48aedb31826e [file] [log] [blame]
Mikio Haraf0ba5dc2014-11-11 21:19:19 +09001// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ipv4_test
6
7import (
8 "bytes"
9 "net"
10 "runtime"
11 "sync"
12 "testing"
13
14 "golang.org/x/net/internal/nettest"
15 "golang.org/x/net/ipv4"
16)
17
18func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
19 c, err := net.ListenPacket("udp4", "127.0.0.1:0")
20 if err != nil {
21 return nil, nil, err
22 }
23 dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
24 if err != nil {
25 c.Close()
26 return nil, nil, err
27 }
28 return c, dst, nil
29}
30
31func BenchmarkReadWriteNetUDP(b *testing.B) {
32 c, dst, err := benchmarkUDPListener()
33 if err != nil {
Mikio Harac25a4f32014-11-16 11:30:27 +090034 b.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090035 }
36 defer c.Close()
37
38 wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
39 b.ResetTimer()
40 for i := 0; i < b.N; i++ {
41 benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
42 }
43}
44
45func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
46 if _, err := c.WriteTo(wb, dst); err != nil {
Mikio Harac25a4f32014-11-16 11:30:27 +090047 b.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090048 }
49 if _, _, err := c.ReadFrom(rb); err != nil {
Mikio Harac25a4f32014-11-16 11:30:27 +090050 b.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090051 }
52}
53
54func BenchmarkReadWriteIPv4UDP(b *testing.B) {
55 c, dst, err := benchmarkUDPListener()
56 if err != nil {
Mikio Harac25a4f32014-11-16 11:30:27 +090057 b.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090058 }
59 defer c.Close()
60
61 p := ipv4.NewPacketConn(c)
62 defer p.Close()
63 cf := ipv4.FlagTTL | ipv4.FlagInterface
64 if err := p.SetControlMessage(cf, true); err != nil {
Mikio Harac25a4f32014-11-16 11:30:27 +090065 b.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090066 }
67 ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
68
69 wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
70 b.ResetTimer()
71 for i := 0; i < b.N; i++ {
72 benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi)
73 }
74}
75
76func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
77 cm := ipv4.ControlMessage{TTL: 1}
78 if ifi != nil {
79 cm.IfIndex = ifi.Index
80 }
81 if n, err := p.WriteTo(wb, &cm, dst); err != nil {
Mikio Harac25a4f32014-11-16 11:30:27 +090082 b.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090083 } else if n != len(wb) {
Mikio Harac25a4f32014-11-16 11:30:27 +090084 b.Fatalf("got %v; want %v", n, len(wb))
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090085 }
86 if _, _, _, err := p.ReadFrom(rb); err != nil {
Mikio Harac25a4f32014-11-16 11:30:27 +090087 b.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090088 }
89}
90
91func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
92 switch runtime.GOOS {
93 case "nacl", "plan9", "solaris", "windows":
Mikio Hara200fa7c2015-01-30 09:49:48 +090094 t.Skipf("not supported on %s", runtime.GOOS)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +090095 }
96
97 c, err := net.ListenPacket("udp4", "127.0.0.1:0")
98 if err != nil {
99 t.Fatal(err)
100 }
101 defer c.Close()
102 p := ipv4.NewPacketConn(c)
103 defer p.Close()
104
105 dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
106 if err != nil {
107 t.Fatal(err)
108 }
109
110 ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
111 cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
112 wb := []byte("HELLO-R-U-THERE")
113
114 if err := p.SetControlMessage(cf, true); err != nil { // probe before test
115 if nettest.ProtocolNotSupported(err) {
Mikio Hara200fa7c2015-01-30 09:49:48 +0900116 t.Skipf("not supported on %s", runtime.GOOS)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +0900117 }
Mikio Harac25a4f32014-11-16 11:30:27 +0900118 t.Fatal(err)
Mikio Haraf0ba5dc2014-11-11 21:19:19 +0900119 }
120
121 var wg sync.WaitGroup
122 reader := func() {
123 defer wg.Done()
124 rb := make([]byte, 128)
125 if n, cm, _, err := p.ReadFrom(rb); err != nil {
126 t.Error(err)
127 return
128 } else if !bytes.Equal(rb[:n], wb) {
129 t.Errorf("got %v; want %v", rb[:n], wb)
130 return
131 } else {
132 t.Logf("rcvd cmsg: %v", cm)
133 }
134 }
135 writer := func(toggle bool) {
136 defer wg.Done()
137 cm := ipv4.ControlMessage{
138 Src: net.IPv4(127, 0, 0, 1),
139 }
140 if ifi != nil {
141 cm.IfIndex = ifi.Index
142 }
143 if err := p.SetControlMessage(cf, toggle); err != nil {
144 t.Error(err)
145 return
146 }
147 if n, err := p.WriteTo(wb, &cm, dst); err != nil {
148 t.Error(err)
149 return
150 } else if n != len(wb) {
151 t.Errorf("short write: %v", n)
152 return
153 }
154 }
155
156 const N = 10
157 wg.Add(N)
158 for i := 0; i < N; i++ {
159 go reader()
160 }
161 wg.Add(2 * N)
162 for i := 0; i < 2*N; i++ {
163 go writer(i%2 != 0)
164 }
165 wg.Add(N)
166 for i := 0; i < N; i++ {
167 go reader()
168 }
169 wg.Wait()
170}