1 // 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.
18 "golang.org/x/net/internal/iana"
19 "golang.org/x/net/internal/nettest"
20 "golang.org/x/net/ipv4"
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")
30 iph, err := (&ipv4.Header{
31 Version: ipv4.Version,
33 TotalLen: ipv4.HeaderLen + len(payload),
35 Protocol: iana.ProtocolReserved,
36 Src: net.IPv4(192, 0, 2, 1),
37 Dst: net.IPv4(192, 0, 2, 254),
42 greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
43 datagram := append(greh, append(iph, payload...)...)
44 bb := make([]byte, 128)
45 cm := ipv4.ControlMessage{
46 Src: net.IPv4(127, 0, 0, 1),
48 if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil {
49 cm.IfIndex = ifi.Index
52 b.Run("UDP", func(b *testing.B) {
53 c, err := nettest.NewLocalPacketListener("udp4")
55 b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
58 p := ipv4.NewPacketConn(c)
60 cf := ipv4.FlagTTL | ipv4.FlagInterface
61 if err := p.SetControlMessage(cf, true); err != nil {
64 b.Run("Net", func(b *testing.B) {
65 for i := 0; i < b.N; i++ {
66 if _, err := c.WriteTo(payload, dst); err != nil {
69 if _, _, err := c.ReadFrom(bb); err != nil {
74 b.Run("ToFrom", func(b *testing.B) {
75 for i := 0; i < b.N; i++ {
76 if _, err := p.WriteTo(payload, &cm, dst); err != nil {
79 if _, _, _, err := p.ReadFrom(bb); err != nil {
85 b.Run("IP", func(b *testing.B) {
88 b.Skip("need to configure gre on netbsd")
90 b.Skip("net.inet.gre.allow=0 by default on openbsd")
93 c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
95 b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
98 p := ipv4.NewPacketConn(c)
100 cf := ipv4.FlagTTL | ipv4.FlagInterface
101 if err := p.SetControlMessage(cf, true); err != nil {
104 b.Run("Net", func(b *testing.B) {
105 for i := 0; i < b.N; i++ {
106 if _, err := c.WriteTo(datagram, dst); err != nil {
109 if _, _, err := c.ReadFrom(bb); err != nil {
114 b.Run("ToFrom", func(b *testing.B) {
115 for i := 0; i < b.N; i++ {
116 if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
119 if _, _, _, err := p.ReadFrom(bb); err != nil {
127 func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
128 switch runtime.GOOS {
129 case "nacl", "plan9", "windows":
130 t.Skipf("not supported on %s", runtime.GOOS)
133 payload := []byte("HELLO-R-U-THERE")
134 iph, err := (&ipv4.Header{
135 Version: ipv4.Version,
137 TotalLen: ipv4.HeaderLen + len(payload),
139 Protocol: iana.ProtocolReserved,
140 Src: net.IPv4(192, 0, 2, 1),
141 Dst: net.IPv4(192, 0, 2, 254),
146 greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
147 datagram := append(greh, append(iph, payload...)...)
149 t.Run("UDP", func(t *testing.T) {
150 c, err := nettest.NewLocalPacketListener("udp4")
152 t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
155 p := ipv4.NewPacketConn(c)
156 t.Run("ToFrom", func(t *testing.T) {
157 testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr())
160 t.Run("IP", func(t *testing.T) {
161 switch runtime.GOOS {
163 t.Skip("need to configure gre on netbsd")
165 t.Skip("net.inet.gre.allow=0 by default on openbsd")
168 c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
170 t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
173 p := ipv4.NewPacketConn(c)
174 t.Run("ToFrom", func(t *testing.T) {
175 testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr())
180 func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr) {
181 ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
182 cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
184 if err := p.SetControlMessage(cf, true); err != nil { // probe before test
185 if nettest.ProtocolNotSupported(err) {
186 t.Skipf("not supported on %s", runtime.GOOS)
191 var wg sync.WaitGroup
194 b := make([]byte, 128)
195 n, cm, _, err := p.ReadFrom(b)
200 if !bytes.Equal(b[:n], data) {
201 t.Errorf("got %#v; want %#v", b[:n], data)
205 if strings.Contains(s, ",") {
206 t.Errorf("should be space-separated values: %s", s)
210 writer := func(toggle bool) {
212 cm := ipv4.ControlMessage{
213 Src: net.IPv4(127, 0, 0, 1),
216 cm.IfIndex = ifi.Index
218 if err := p.SetControlMessage(cf, toggle); err != nil {
222 n, err := p.WriteTo(data, &cm, dst)
228 t.Errorf("got %d; want %d", n, len(data))
235 for i := 0; i < N; i++ {
239 for i := 0; i < 2*N; i++ {
244 for i := 0; i < N; i++ {