1
2
3
4 package netlink
5
6 import (
7 "net"
8 "os"
9 "testing"
10 "time"
11
12 "golang.org/x/sys/unix"
13 )
14
15 func TestAddrAdd(t *testing.T) {
16 DoTestAddr(t, AddrAdd)
17 }
18
19 func TestAddrReplace(t *testing.T) {
20 DoTestAddr(t, AddrReplace)
21 }
22
23 func DoTestAddr(t *testing.T, FunctionUndertest func(Link, *Addr) error) {
24 if os.Getenv("CI") == "true" {
25 t.Skipf("Fails in CI with: addr_test.go:*: Address flags not set properly, got=128, expected=132")
26 }
27
28
29 var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(32, 32)}
30 var peer = &net.IPNet{IP: net.IPv4(127, 0, 0, 3), Mask: net.CIDRMask(24, 32)}
31 var addrTests = []struct {
32 addr *Addr
33 expected *Addr
34 }{
35 {
36 &Addr{IPNet: address},
37 &Addr{IPNet: address, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
38 },
39 {
40 &Addr{IPNet: address, Label: "local"},
41 &Addr{IPNet: address, Label: "local", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
42 },
43 {
44 &Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC},
45 &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE},
46 },
47 {
48 &Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED},
49 &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE},
50 },
51 {
52 &Addr{IPNet: address, Scope: unix.RT_SCOPE_NOWHERE},
53 &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_NOWHERE},
54 },
55 {
56 &Addr{IPNet: address, Peer: peer},
57 &Addr{IPNet: address, Peer: peer, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
58 },
59 }
60
61 tearDown := setUpNetlinkTest(t)
62 defer tearDown()
63
64 link, err := LinkByName("lo")
65 if err != nil {
66 t.Fatal(err)
67 }
68
69 for _, tt := range addrTests {
70 if err = FunctionUndertest(link, tt.addr); err != nil {
71 t.Fatal(err)
72 }
73
74 addrs, err := AddrList(link, FAMILY_ALL)
75 if err != nil {
76 t.Fatal(err)
77 }
78
79 if len(addrs) != 1 {
80 t.Fatal("Address not added properly")
81 }
82
83 if !addrs[0].Equal(*tt.expected) {
84 t.Fatalf("Address ip no set properly, got=%s, expected=%s", addrs[0], tt.expected)
85 }
86
87 if addrs[0].Label != tt.expected.Label {
88 t.Fatalf("Address label not set properly, got=%s, expected=%s", addrs[0].Label, tt.expected.Label)
89 }
90
91 if addrs[0].Flags != tt.expected.Flags {
92 t.Fatalf("Address flags not set properly, got=%d, expected=%d", addrs[0].Flags, tt.expected.Flags)
93 }
94
95 if addrs[0].Scope != tt.expected.Scope {
96 t.Fatalf("Address scope not set properly, got=%d, expected=%d", addrs[0].Scope, tt.expected.Scope)
97 }
98
99 if ifindex := link.Attrs().Index; ifindex != addrs[0].LinkIndex {
100 t.Fatalf("Address ifindex not set properly, got=%d, expected=%d", addrs[0].LinkIndex, ifindex)
101 }
102
103 if tt.expected.Peer != nil {
104 if !addrs[0].PeerEqual(*tt.expected) {
105 t.Fatalf("Peer Address ip no set properly, got=%s, expected=%s", addrs[0].Peer, tt.expected.Peer)
106 }
107 }
108
109
110 addrs, err = AddrList(link, FAMILY_V4)
111 if err != nil {
112 t.Fatal(err)
113 }
114 if len(addrs) != 1 {
115 t.Fatal("Address not added properly")
116 }
117
118
119 addrs, err = AddrList(link, 0x8)
120 if err != nil {
121 t.Fatal(err)
122 }
123
124 if len(addrs) != 0 {
125 t.Fatal("Address not expected")
126 }
127
128 if err = AddrDel(link, tt.addr); err != nil {
129 t.Fatal(err)
130 }
131
132 addrs, err = AddrList(link, FAMILY_ALL)
133 if err != nil {
134 t.Fatal(err)
135 }
136
137 if len(addrs) != 0 {
138 t.Fatal("Address not removed properly")
139 }
140 }
141
142 }
143
144 func TestAddrAddReplace(t *testing.T) {
145 tearDown := setUpNetlinkTest(t)
146 defer tearDown()
147
148 for _, nilLink := range []bool{false, true} {
149 var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(24, 32)}
150 var addr = &Addr{IPNet: address}
151
152 link, err := LinkByName("lo")
153 if err != nil {
154 t.Fatal(err)
155 }
156
157 if nilLink {
158 addr.LinkIndex = link.Attrs().Index
159 link = nil
160 }
161
162 err = AddrAdd(link, addr)
163 if err != nil {
164 t.Fatal(err)
165 }
166
167 addrs, err := AddrList(link, FAMILY_ALL)
168 if err != nil {
169 t.Fatal(err)
170 }
171
172 if len(addrs) != 1 {
173 t.Fatal("Address not added properly")
174 }
175
176 err = AddrAdd(link, addr)
177 if err == nil {
178 t.Fatal("Re-adding address should fail (but succeeded unexpectedly).")
179 }
180
181 err = AddrReplace(link, addr)
182 if err != nil {
183 t.Fatal("Replacing address failed.")
184 }
185
186 addrs, err = AddrList(link, FAMILY_ALL)
187 if err != nil {
188 t.Fatal(err)
189 }
190
191 if len(addrs) != 1 {
192 t.Fatal("Address not added properly")
193 }
194
195 if err = AddrDel(link, addr); err != nil {
196 t.Fatal(err)
197 }
198
199 addrs, err = AddrList(link, FAMILY_ALL)
200 if err != nil {
201 t.Fatal(err)
202 }
203
204 if len(addrs) != 0 {
205 t.Fatal("Address not removed properly")
206 }
207 }
208 }
209
210 func expectAddrUpdate(ch <-chan AddrUpdate, add bool, dst net.IP) bool {
211 for {
212 timeout := time.After(time.Minute)
213 select {
214 case update := <-ch:
215 if update.NewAddr == add && update.LinkAddress.IP.Equal(dst) {
216 return true
217 }
218 case <-timeout:
219 return false
220 }
221 }
222 }
223
224 func TestAddrSubscribeWithOptions(t *testing.T) {
225 tearDown := setUpNetlinkTest(t)
226 defer tearDown()
227
228 ch := make(chan AddrUpdate)
229 done := make(chan struct{})
230 defer close(done)
231 var lastError error
232 defer func() {
233 if lastError != nil {
234 t.Fatalf("Fatal error received during subscription: %v", lastError)
235 }
236 }()
237 if err := AddrSubscribeWithOptions(ch, done, AddrSubscribeOptions{
238 ErrorCallback: func(err error) {
239 lastError = err
240 },
241 }); err != nil {
242 t.Fatal(err)
243 }
244
245
246 link, err := LinkByName("lo")
247 if err != nil {
248 t.Fatal(err)
249 }
250
251
252 if err = LinkSetUp(link); err != nil {
253 t.Fatal(err)
254 }
255
256 ip := net.IPv4(127, 0, 0, 1)
257 if !expectAddrUpdate(ch, true, ip) {
258 t.Fatal("Add update not received as expected")
259 }
260 }
261
262 func TestAddrSubscribeListExisting(t *testing.T) {
263 tearDown := setUpNetlinkTest(t)
264 defer tearDown()
265
266 ch := make(chan AddrUpdate)
267 done := make(chan struct{})
268 defer close(done)
269
270
271 link, err := LinkByName("lo")
272 if err != nil {
273 t.Fatal(err)
274 }
275
276
277 if err = LinkSetUp(link); err != nil {
278 t.Fatal(err)
279 }
280
281 var lastError error
282 defer func() {
283 if lastError != nil {
284 t.Fatalf("Fatal error received during subscription: %v", lastError)
285 }
286 }()
287 if err := AddrSubscribeWithOptions(ch, done, AddrSubscribeOptions{
288 ErrorCallback: func(err error) {
289 lastError = err
290 },
291 ListExisting: true,
292 }); err != nil {
293 t.Fatal(err)
294 }
295
296 ip := net.IPv4(127, 0, 0, 1)
297 if !expectAddrUpdate(ch, true, ip) {
298 t.Fatal("Add update not received as expected")
299 }
300 }
301
View as plain text