forked from ti-mo/conntrack
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconn_integration_test.go
177 lines (136 loc) · 3.54 KB
/
conn_integration_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package conntrack
import (
"encoding/binary"
"fmt"
"io/ioutil"
"log"
"net"
"os"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/ti-mo/netfilter"
"github.com/mdlayher/netlink"
"github.com/vishvananda/netns"
)
var ksyms []string
func TestMain(m *testing.M) {
var err error
if err = checkKmod(); err != nil {
log.Fatal(err)
}
ksyms, err = getKsyms()
if err != nil {
log.Fatal(err)
}
rc := m.Run()
os.Exit(rc)
}
// Open a Netlink socket and set an option on it.
func TestConnDialSetOption(t *testing.T) {
c, err := Dial(nil)
require.NoError(t, err, "opening Conn")
err = c.SetOption(netlink.ListenAllNSID, true)
require.NoError(t, err, "setting SockOption")
err = c.Close()
require.NoError(t, err, "closing Conn")
}
// checkKmod checks if the kernel modules required for this test suite are loaded into the kernel.
// Since around 4.19, conntrack is a single module, so only warn about _ipv4/6 when that one
// is not loaded.
func checkKmod() error {
kmods := []string{
"nf_conntrack_ipv4",
"nf_conntrack_ipv6",
}
if _, err := os.Stat("/sys/module/nf_conntrack"); os.IsNotExist(err) {
// Fall back to _ipv4/6 if nf_conntrack is missing.
for _, km := range kmods {
if _, err := os.Stat(fmt.Sprintf("/sys/module/%s", km)); os.IsNotExist(err) {
return fmt.Errorf("missing kernel module %s and module nf_conntrack", km)
}
}
}
return nil
}
// makeNSConn creates a Conn in a new network namespace to use for testing.
// Returns the Conn, the netns identifier and error.
func makeNSConn() (*Conn, int, error) {
newns, err := netns.New()
if err != nil {
return nil, 0, fmt.Errorf("unexpected error creating network namespace: %s", err)
}
newConn, err := Dial(&netlink.Config{NetNS: int(newns)})
if err != nil {
return nil, 0, fmt.Errorf("unexpected error dialing namespaced connection: %s", err)
}
return newConn, int(newns), nil
}
// getKsyms gets a list of all symbols in the kernel. (/proc/kallsyms)
func getKsyms() ([]string, error) {
f, err := ioutil.ReadFile("/proc/kallsyms")
if err != nil {
return nil, err
}
// Trim trailing newlines and split by newline
content := strings.Split(strings.TrimSuffix(string(f), "\n"), "\n")
out := make([]string, len(content))
for i, l := range content {
// Replace any tabs by spaces
l = strings.Replace(l, "\t", " ", -1)
// Get the third column
out[i] = strings.Split(l, " ")[2]
}
return out, nil
}
// findKsym finds a given string in /proc/kallsyms. True means the string was found.
func findKsym(sym string) bool {
for _, v := range ksyms {
if v == sym {
return true
}
}
return false
}
/////////////////////////
func testMarshal(f Flow) error {
attrs, err := f.marshal()
if err != nil {
return err
}
pf := netfilter.ProtoIPv4
if f.TupleOrig.IP.IsIPv6() && f.TupleReply.IP.IsIPv6() {
pf = netfilter.ProtoIPv6
}
req, err := netfilter.MarshalNetlink(
netfilter.Header{
SubsystemID: netfilter.NFSubsysCTNetlink,
MessageType: netfilter.MessageType(ctNew),
Family: pf,
Flags: netlink.Request | netlink.Acknowledge,
}, attrs)
if err != nil {
return err
}
_ = req
return nil
}
func BenchmarkMsg(b *testing.B) {
src := net.ParseIP("1.1.1.1")
dst := net.ParseIP("1.1.1.1")
sp := uint16(2222)
dp := uint16(22)
f := NewFlow(
6, 0,
src, dst,
sp, dp,
0, 0)
f.Labels = make([]byte, 16)
f.LabelsMask = make([]byte, 16)
binary.LittleEndian.PutUint32(f.Labels[0:4], 1)
binary.LittleEndian.PutUint32(f.LabelsMask[0:4], ^uint32(0))
// update
for i := 0; i < b.N; i++ {
testMarshal(f)
}
}