github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/ipv6/bpf_test.go (about) 1 // Copyright 2016 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 5 package ipv6_test 6 7 import ( 8 "net" 9 "runtime" 10 "testing" 11 "time" 12 13 "github.com/Andyfoo/golang/x/net/bpf" 14 "github.com/Andyfoo/golang/x/net/ipv6" 15 "github.com/Andyfoo/golang/x/net/nettest" 16 ) 17 18 func TestBPF(t *testing.T) { 19 if runtime.GOOS != "linux" { 20 t.Skipf("not supported on %s", runtime.GOOS) 21 } 22 if !nettest.SupportsIPv6() { 23 t.Skip("ipv6 is not supported") 24 } 25 26 l, err := net.ListenPacket("udp6", "[::1]:0") 27 if err != nil { 28 t.Fatal(err) 29 } 30 defer l.Close() 31 32 p := ipv6.NewPacketConn(l) 33 34 // This filter accepts UDP packets whose first payload byte is 35 // even. 36 prog, err := bpf.Assemble([]bpf.Instruction{ 37 // Load the first byte of the payload (skipping UDP header). 38 bpf.LoadAbsolute{Off: 8, Size: 1}, 39 // Select LSB of the byte. 40 bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1}, 41 // Byte is even? 42 bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1}, 43 // Accept. 44 bpf.RetConstant{Val: 4096}, 45 // Ignore. 46 bpf.RetConstant{Val: 0}, 47 }) 48 if err != nil { 49 t.Fatalf("compiling BPF: %s", err) 50 } 51 52 if err = p.SetBPF(prog); err != nil { 53 t.Fatalf("attaching filter to Conn: %s", err) 54 } 55 56 s, err := net.Dial("udp6", l.LocalAddr().String()) 57 if err != nil { 58 t.Fatal(err) 59 } 60 defer s.Close() 61 go func() { 62 for i := byte(0); i < 10; i++ { 63 s.Write([]byte{i}) 64 } 65 }() 66 67 l.SetDeadline(time.Now().Add(2 * time.Second)) 68 seen := make([]bool, 5) 69 for { 70 var b [512]byte 71 n, _, err := l.ReadFrom(b[:]) 72 if err != nil { 73 t.Fatalf("reading from listener: %s", err) 74 } 75 if n != 1 { 76 t.Fatalf("unexpected packet length, want 1, got %d", n) 77 } 78 if b[0] >= 10 { 79 t.Fatalf("unexpected byte, want 0-9, got %d", b[0]) 80 } 81 if b[0]%2 != 0 { 82 t.Fatalf("got odd byte %d, wanted only even bytes", b[0]) 83 } 84 seen[b[0]/2] = true 85 86 seenAll := true 87 for _, v := range seen { 88 if !v { 89 seenAll = false 90 break 91 } 92 } 93 if seenAll { 94 break 95 } 96 } 97 }