bpf_test.go 1.9 KB

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