1 // Copyright 2013 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.
18 "golang.org/x/net/internal/iana"
19 "golang.org/x/net/internal/nettest"
20 "golang.org/x/net/ipv6"
23 func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
25 case "nacl", "plan9", "windows":
26 b.Skipf("not supported on %s", runtime.GOOS)
29 payload := []byte("HELLO-R-U-THERE")
31 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
32 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
34 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
37 greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
38 datagram := append(greh, append(iph, payload...)...)
39 bb := make([]byte, 128)
40 cm := ipv6.ControlMessage{
41 TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
43 Src: net.IPv6loopback,
45 if ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); ifi != nil {
46 cm.IfIndex = ifi.Index
49 b.Run("UDP", func(b *testing.B) {
50 c, err := nettest.NewLocalPacketListener("udp6")
52 b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
55 p := ipv6.NewPacketConn(c)
57 cf := ipv6.FlagHopLimit | ipv6.FlagInterface
58 if err := p.SetControlMessage(cf, true); err != nil {
61 b.Run("Net", func(b *testing.B) {
62 for i := 0; i < b.N; i++ {
63 if _, err := c.WriteTo(payload, dst); err != nil {
66 if _, _, err := c.ReadFrom(bb); err != nil {
71 b.Run("ToFrom", func(b *testing.B) {
72 for i := 0; i < b.N; i++ {
73 if _, err := p.WriteTo(payload, &cm, dst); err != nil {
76 if _, _, _, err := p.ReadFrom(bb); err != nil {
82 b.Run("IP", func(b *testing.B) {
85 b.Skip("need to configure gre on netbsd")
87 b.Skip("net.inet.gre.allow=0 by default on openbsd")
90 c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
92 b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
95 p := ipv6.NewPacketConn(c)
97 cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
98 if err := p.SetControlMessage(cf, true); err != nil {
101 b.Run("Net", func(b *testing.B) {
102 for i := 0; i < b.N; i++ {
103 if _, err := c.WriteTo(datagram, dst); err != nil {
106 if _, _, err := c.ReadFrom(bb); err != nil {
111 b.Run("ToFrom", func(b *testing.B) {
112 for i := 0; i < b.N; i++ {
113 if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
116 if _, _, _, err := p.ReadFrom(bb); err != nil {
124 func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
125 switch runtime.GOOS {
126 case "nacl", "plan9", "windows":
127 t.Skipf("not supported on %s", runtime.GOOS)
130 payload := []byte("HELLO-R-U-THERE")
132 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
133 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
135 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
138 greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
139 datagram := append(greh, append(iph, payload...)...)
141 t.Run("UDP", func(t *testing.T) {
142 c, err := nettest.NewLocalPacketListener("udp6")
144 t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
147 p := ipv6.NewPacketConn(c)
148 t.Run("ToFrom", func(t *testing.T) {
149 testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr())
152 t.Run("IP", func(t *testing.T) {
153 switch runtime.GOOS {
155 t.Skip("need to configure gre on netbsd")
157 t.Skip("net.inet.gre.allow=0 by default on openbsd")
160 c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
162 t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
165 p := ipv6.NewPacketConn(c)
166 t.Run("ToFrom", func(t *testing.T) {
167 testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr())
172 func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr) {
173 ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
174 cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
176 if err := p.SetControlMessage(cf, true); err != nil { // probe before test
177 if nettest.ProtocolNotSupported(err) {
178 t.Skipf("not supported on %s", runtime.GOOS)
183 var wg sync.WaitGroup
186 b := make([]byte, 128)
187 n, cm, _, err := p.ReadFrom(b)
192 if !bytes.Equal(b[:n], data) {
193 t.Errorf("got %#v; want %#v", b[:n], data)
197 if strings.Contains(s, ",") {
198 t.Errorf("should be space-separated values: %s", s)
202 writer := func(toggle bool) {
204 cm := ipv6.ControlMessage{
205 TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
207 Src: net.IPv6loopback,
210 cm.IfIndex = ifi.Index
212 if err := p.SetControlMessage(cf, toggle); err != nil {
216 n, err := p.WriteTo(data, &cm, dst)
222 t.Errorf("got %d; want %d", n, len(data))
229 for i := 0; i < N; i++ {
233 for i := 0; i < 2*N; i++ {
238 for i := 0; i < N; i++ {