OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / bpf / vm_test.go
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 bpf_test
6
7 import (
8         "fmt"
9         "testing"
10
11         "golang.org/x/net/bpf"
12 )
13
14 var _ bpf.Instruction = unknown{}
15
16 type unknown struct{}
17
18 func (unknown) Assemble() (bpf.RawInstruction, error) {
19         return bpf.RawInstruction{}, nil
20 }
21
22 func TestVMUnknownInstruction(t *testing.T) {
23         vm, done, err := testVM(t, []bpf.Instruction{
24                 bpf.LoadConstant{
25                         Dst: bpf.RegA,
26                         Val: 100,
27                 },
28                 // Should terminate the program with an error immediately
29                 unknown{},
30                 bpf.RetA{},
31         })
32         if err != nil {
33                 t.Fatalf("unexpected error: %v", err)
34         }
35         defer done()
36
37         _, err = vm.Run([]byte{
38                 0xff, 0xff, 0xff, 0xff,
39                 0xff, 0xff, 0xff, 0xff,
40                 0x00, 0x00,
41         })
42         if errStr(err) != "unknown Instruction at index 1: bpf_test.unknown" {
43                 t.Fatalf("unexpected error while running program: %v", err)
44         }
45 }
46
47 func TestVMNoReturnInstruction(t *testing.T) {
48         _, _, err := testVM(t, []bpf.Instruction{
49                 bpf.LoadConstant{
50                         Dst: bpf.RegA,
51                         Val: 1,
52                 },
53         })
54         if errStr(err) != "BPF program must end with RetA or RetConstant" {
55                 t.Fatalf("unexpected error: %v", err)
56         }
57 }
58
59 func TestVMNoInputInstructions(t *testing.T) {
60         _, _, err := testVM(t, []bpf.Instruction{})
61         if errStr(err) != "one or more Instructions must be specified" {
62                 t.Fatalf("unexpected error: %v", err)
63         }
64 }
65
66 // ExampleNewVM demonstrates usage of a VM, using an Ethernet frame
67 // as input and checking its EtherType to determine if it should be accepted.
68 func ExampleNewVM() {
69         // Offset | Length | Comment
70         // -------------------------
71         //   00   |   06   | Ethernet destination MAC address
72         //   06   |   06   | Ethernet source MAC address
73         //   12   |   02   | Ethernet EtherType
74         const (
75                 etOff = 12
76                 etLen = 2
77
78                 etARP = 0x0806
79         )
80
81         // Set up a VM to filter traffic based on if its EtherType
82         // matches the ARP EtherType.
83         vm, err := bpf.NewVM([]bpf.Instruction{
84                 // Load EtherType value from Ethernet header
85                 bpf.LoadAbsolute{
86                         Off:  etOff,
87                         Size: etLen,
88                 },
89                 // If EtherType is equal to the ARP EtherType, jump to allow
90                 // packet to be accepted
91                 bpf.JumpIf{
92                         Cond:     bpf.JumpEqual,
93                         Val:      etARP,
94                         SkipTrue: 1,
95                 },
96                 // EtherType does not match the ARP EtherType
97                 bpf.RetConstant{
98                         Val: 0,
99                 },
100                 // EtherType matches the ARP EtherType, accept up to 1500
101                 // bytes of packet
102                 bpf.RetConstant{
103                         Val: 1500,
104                 },
105         })
106         if err != nil {
107                 panic(fmt.Sprintf("failed to load BPF program: %v", err))
108         }
109
110         // Create an Ethernet frame with the ARP EtherType for testing
111         frame := []byte{
112                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
113                 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
114                 0x08, 0x06,
115                 // Payload omitted for brevity
116         }
117
118         // Run our VM's BPF program using the Ethernet frame as input
119         out, err := vm.Run(frame)
120         if err != nil {
121                 panic(fmt.Sprintf("failed to accept Ethernet frame: %v", err))
122         }
123
124         // BPF VM can return a byte count greater than the number of input
125         // bytes, so trim the output to match the input byte length
126         if out > len(frame) {
127                 out = len(frame)
128         }
129
130         fmt.Printf("out: %d bytes", out)
131
132         // Output:
133         // out: 14 bytes
134 }
135
136 // errStr returns the string representation of an error, or
137 // "<nil>" if it is nil.
138 func errStr(err error) string {
139         if err == nil {
140                 return "<nil>"
141         }
142
143         return err.Error()
144 }