github.com/vishvananda/netlink@v1.3.0/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 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 // TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels? 28 // TODO: IFA_F_OPTIMISTIC failing in CI. should we just skip that one check? 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 // Pass FAMILY_V4, we should get the same results as FAMILY_ALL 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 // Pass a wrong family number, we should get nil list 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 // get loopback interface 246 link, err := LinkByName("lo") 247 if err != nil { 248 t.Fatal(err) 249 } 250 251 // bring the interface up 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 // get loopback interface 271 link, err := LinkByName("lo") 272 if err != nil { 273 t.Fatal(err) 274 } 275 276 // bring the interface up 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 }