github.com/vishvananda/netlink@v1.3.1/addr_test.go (about) 1 //go:build linux 2 // +build linux 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 type addrTest struct { 24 name string 25 addr *Addr 26 expected *Addr 27 canFail bool 28 t *testing.T 29 } 30 31 func (at *addrTest) Fatal(a interface{}) { 32 at.t.Helper() 33 if !at.canFail { 34 at.t.Fatal(a) 35 return 36 } 37 at.t.Skipf("Non-fatal: %v", a) 38 } 39 40 func (at *addrTest) Fatalf(fmt string, a ...interface{}) { 41 at.t.Helper() 42 if !at.canFail { 43 at.t.Fatalf(fmt, a...) 44 return 45 } 46 at.t.Skipf("Non-fatal: "+fmt, a...) 47 } 48 49 func DoTestAddr(t *testing.T, FunctionUndertest func(Link, *Addr) error) { 50 if os.Getenv("CI") == "true" { 51 t.Skipf("Fails in CI with: addr_test.go:*: Address flags not set properly, got=128, expected=132") 52 } 53 54 // TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels? 55 // TODO: IFA_F_OPTIMISTIC failing in CI. should we just skip that one check? 56 var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(32, 32)} 57 var peer = &net.IPNet{IP: net.IPv4(127, 0, 0, 3), Mask: net.CIDRMask(24, 32)} 58 var addrTests = []addrTest{ 59 { 60 name: "lo_uni_perm", addr: &Addr{IPNet: address}, 61 expected: &Addr{IPNet: address, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT}, 62 }, 63 { 64 name: "local_uni_perm", addr: &Addr{IPNet: address, Label: "local"}, 65 expected: &Addr{IPNet: address, Label: "local", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT}, 66 }, 67 { 68 name: "lo_uni_optimistic_perm", addr: &Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC}, canFail: true, 69 expected: &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE}, 70 }, 71 { 72 // Is this a valid scenario for IPv4? 73 name: "lo_uni_optimistic_perm_dupe", addr: &Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED}, canFail: true, 74 expected: &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE}, 75 }, 76 { 77 name: "lo_nullroute_perm", addr: &Addr{IPNet: address, Scope: unix.RT_SCOPE_NOWHERE}, 78 expected: &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_NOWHERE}, 79 }, 80 { 81 name: "lo_uni_perm_with_peer", addr: &Addr{IPNet: address, Peer: peer}, 82 expected: &Addr{IPNet: address, Peer: peer, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT}, 83 }, 84 } 85 86 for _, tt := range addrTests { 87 t.Run(tt.name, func(t *testing.T) { 88 tt.t = t 89 90 tearDown := setUpNetlinkTest(t) 91 defer tearDown() 92 93 link, err := LinkByName("lo") 94 if err != nil { 95 tt.Fatal(err) 96 } 97 98 if err = FunctionUndertest(link, tt.addr); err != nil { 99 tt.Fatal(err) 100 } 101 102 addrs, err := AddrList(link, FAMILY_ALL) 103 if err != nil { 104 tt.Fatal(err) 105 } 106 107 if len(addrs) != 1 { 108 tt.Fatal("Address not added properly") 109 } 110 111 if !addrs[0].Equal(*tt.expected) { 112 tt.Fatalf("Address ip not set properly, got=%s, expected=%s", addrs[0], tt.expected) 113 } 114 115 if addrs[0].Label != tt.expected.Label { 116 tt.Fatalf("Address label not set properly, got=%s, expected=%s", addrs[0].Label, tt.expected.Label) 117 } 118 119 if addrs[0].Flags != tt.expected.Flags { 120 tt.Fatalf("Address flags not set properly, got=%d, expected=%d", addrs[0].Flags, tt.expected.Flags) 121 } 122 123 if addrs[0].Scope != tt.expected.Scope { 124 tt.Fatalf("Address scope not set properly, got=%d, expected=%d", addrs[0].Scope, tt.expected.Scope) 125 } 126 127 if ifindex := link.Attrs().Index; ifindex != addrs[0].LinkIndex { 128 tt.Fatalf("Address ifindex not set properly, got=%d, expected=%d", addrs[0].LinkIndex, ifindex) 129 } 130 131 if tt.expected.Peer != nil { 132 if !addrs[0].PeerEqual(*tt.expected) { 133 tt.Fatalf("Peer Address ip not set properly, got=%s, expected=%s", addrs[0].Peer, tt.expected.Peer) 134 } 135 } 136 137 // Pass FAMILY_V4, we should get the same results as FAMILY_ALL 138 addrs, err = AddrList(link, FAMILY_V4) 139 if err != nil { 140 tt.Fatal(err) 141 } 142 if len(addrs) != 1 { 143 tt.Fatal("Address not added properly") 144 } 145 146 // Pass a wrong family number, we should get nil list 147 addrs, err = AddrList(link, 0x8) 148 if err != nil { 149 tt.Fatal(err) 150 } 151 152 if len(addrs) != 0 { 153 tt.Fatal("Address not expected") 154 } 155 156 if err = AddrDel(link, tt.addr); err != nil { 157 tt.Fatal(err) 158 } 159 160 addrs, err = AddrList(link, FAMILY_ALL) 161 if err != nil { 162 tt.Fatal(err) 163 } 164 165 if len(addrs) != 0 { 166 tt.Fatal("Address not removed properly") 167 } 168 }) 169 } 170 171 } 172 173 func TestAddrAddReplace(t *testing.T) { 174 tearDown := setUpNetlinkTest(t) 175 defer tearDown() 176 177 for _, nilLink := range []bool{false, true} { 178 var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(24, 32)} 179 var addr = &Addr{IPNet: address} 180 181 link, err := LinkByName("lo") 182 if err != nil { 183 t.Fatal(err) 184 } 185 186 if nilLink { 187 addr.LinkIndex = link.Attrs().Index 188 link = nil 189 } 190 191 err = AddrAdd(link, addr) 192 if err != nil { 193 t.Fatal(err) 194 } 195 196 addrs, err := AddrList(link, FAMILY_ALL) 197 if err != nil { 198 t.Fatal(err) 199 } 200 201 if len(addrs) != 1 { 202 t.Fatal("Address not added properly") 203 } 204 205 err = AddrAdd(link, addr) 206 if err == nil { 207 t.Fatal("Re-adding address should fail (but succeeded unexpectedly).") 208 } 209 210 err = AddrReplace(link, addr) 211 if err != nil { 212 t.Fatal("Replacing address failed.") 213 } 214 215 addrs, err = AddrList(link, FAMILY_ALL) 216 if err != nil { 217 t.Fatal(err) 218 } 219 220 if len(addrs) != 1 { 221 t.Fatal("Address not added properly") 222 } 223 224 if err = AddrDel(link, addr); err != nil { 225 t.Fatal(err) 226 } 227 228 addrs, err = AddrList(link, FAMILY_ALL) 229 if err != nil { 230 t.Fatal(err) 231 } 232 233 if len(addrs) != 0 { 234 t.Fatal("Address not removed properly") 235 } 236 } 237 } 238 239 func expectAddrUpdate(ch <-chan AddrUpdate, add bool, dst net.IP) bool { 240 for { 241 timeout := time.After(time.Minute) 242 select { 243 case update := <-ch: 244 if update.NewAddr == add && update.LinkAddress.IP.Equal(dst) { 245 return true 246 } 247 case <-timeout: 248 return false 249 } 250 } 251 } 252 253 func TestAddrSubscribeWithOptions(t *testing.T) { 254 tearDown := setUpNetlinkTest(t) 255 defer tearDown() 256 257 ch := make(chan AddrUpdate) 258 done := make(chan struct{}) 259 defer close(done) 260 var lastError error 261 defer func() { 262 if lastError != nil { 263 t.Fatalf("Fatal error received during subscription: %v", lastError) 264 } 265 }() 266 if err := AddrSubscribeWithOptions(ch, done, AddrSubscribeOptions{ 267 ErrorCallback: func(err error) { 268 lastError = err 269 }, 270 }); err != nil { 271 t.Fatal(err) 272 } 273 274 // get loopback interface 275 link, err := LinkByName("lo") 276 if err != nil { 277 t.Fatal(err) 278 } 279 280 // bring the interface up 281 if err = LinkSetUp(link); err != nil { 282 t.Fatal(err) 283 } 284 285 ip := net.IPv4(127, 0, 0, 1) 286 if !expectAddrUpdate(ch, true, ip) { 287 t.Fatal("Add update not received as expected") 288 } 289 } 290 291 func TestAddrSubscribeListExisting(t *testing.T) { 292 tearDown := setUpNetlinkTest(t) 293 defer tearDown() 294 295 ch := make(chan AddrUpdate) 296 done := make(chan struct{}) 297 defer close(done) 298 299 // get loopback interface 300 link, err := LinkByName("lo") 301 if err != nil { 302 t.Fatal(err) 303 } 304 305 // bring the interface up 306 if err = LinkSetUp(link); err != nil { 307 t.Fatal(err) 308 } 309 310 var lastError error 311 defer func() { 312 if lastError != nil { 313 t.Fatalf("Fatal error received during subscription: %v", lastError) 314 } 315 }() 316 if err := AddrSubscribeWithOptions(ch, done, AddrSubscribeOptions{ 317 ErrorCallback: func(err error) { 318 lastError = err 319 }, 320 ListExisting: true, 321 }); err != nil { 322 t.Fatal(err) 323 } 324 325 ip := net.IPv4(127, 0, 0, 1) 326 if !expectAddrUpdate(ch, true, ip) { 327 t.Fatal("Add update not received as expected") 328 } 329 }