bpf_test.go 1.9 KB

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