github.com/vishvananda/netlink@v1.3.1/handle_test.go (about) 1 // +build linux 2 3 package netlink 4 5 import ( 6 "crypto/rand" 7 "encoding/hex" 8 "fmt" 9 "io" 10 "net" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 "github.com/vishvananda/netlink/nl" 17 "github.com/vishvananda/netns" 18 ) 19 20 func TestHandleCreateClose(t *testing.T) { 21 h, err := NewHandle() 22 if err != nil { 23 t.Fatal(err) 24 } 25 for _, f := range nl.SupportedNlFamilies { 26 sh, ok := h.sockets[f] 27 if !ok { 28 t.Fatalf("Handle socket(s) for family %d was not created", f) 29 } 30 if sh.Socket == nil { 31 t.Fatalf("Socket for family %d was not created", f) 32 } 33 } 34 35 h.Close() 36 if h.sockets != nil { 37 t.Fatalf("Handle socket(s) were not closed") 38 } 39 } 40 41 func TestHandleCreateNetns(t *testing.T) { 42 skipUnlessRoot(t) 43 44 id := make([]byte, 4) 45 if _, err := io.ReadFull(rand.Reader, id); err != nil { 46 t.Fatal(err) 47 } 48 ifName := "dummy-" + hex.EncodeToString(id) 49 50 // Create an handle on the current netns 51 curNs, err := netns.Get() 52 if err != nil { 53 t.Fatal(err) 54 } 55 defer curNs.Close() 56 57 ch, err := NewHandleAt(curNs) 58 if err != nil { 59 t.Fatal(err) 60 } 61 defer ch.Close() 62 63 // Create an handle on a custom netns 64 newNs, err := netns.New() 65 if err != nil { 66 t.Fatal(err) 67 } 68 defer newNs.Close() 69 70 nh, err := NewHandleAt(newNs) 71 if err != nil { 72 t.Fatal(err) 73 } 74 defer nh.Close() 75 76 // Create an interface using the current handle 77 err = ch.LinkAdd(&Dummy{LinkAttrs{Name: ifName}}) 78 if err != nil { 79 t.Fatal(err) 80 } 81 l, err := ch.LinkByName(ifName) 82 if err != nil { 83 t.Fatal(err) 84 } 85 if l.Type() != "dummy" { 86 t.Fatalf("Unexpected link type: %s", l.Type()) 87 } 88 89 // Verify the new handle cannot find the interface 90 ll, err := nh.LinkByName(ifName) 91 if err == nil { 92 t.Fatalf("Unexpected link found on netns %s: %v", newNs, ll) 93 } 94 95 // Move the interface to the new netns 96 err = ch.LinkSetNsFd(l, int(newNs)) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 // Verify new netns handle can find the interface while current cannot 102 ll, err = nh.LinkByName(ifName) 103 if err != nil { 104 t.Fatal(err) 105 } 106 if ll.Type() != "dummy" { 107 t.Fatalf("Unexpected link type: %s", ll.Type()) 108 } 109 ll, err = ch.LinkByName(ifName) 110 if err == nil { 111 t.Fatalf("Unexpected link found on netns %s: %v", curNs, ll) 112 } 113 } 114 115 func TestHandleTimeout(t *testing.T) { 116 h, err := NewHandle() 117 if err != nil { 118 t.Fatal(err) 119 } 120 defer h.Close() 121 122 for _, sh := range h.sockets { 123 verifySockTimeVal(t, sh.Socket, time.Duration(0)) 124 } 125 126 const timeout = 2*time.Second + 8*time.Millisecond 127 h.SetSocketTimeout(timeout) 128 129 for _, sh := range h.sockets { 130 verifySockTimeVal(t, sh.Socket, timeout) 131 } 132 } 133 134 func verifySockTimeVal(t *testing.T, socket *nl.NetlinkSocket, expTimeout time.Duration) { 135 t.Helper() 136 send, receive := socket.GetTimeouts() 137 if send != expTimeout || receive != expTimeout { 138 t.Fatalf("Expected timeout: %v, got Send: %v, Receive: %v", expTimeout, send, receive) 139 } 140 } 141 142 func TestHandleReceiveBuffer(t *testing.T) { 143 h, err := NewHandle() 144 if err != nil { 145 t.Fatal(err) 146 } 147 defer h.Close() 148 if err := h.SetSocketReceiveBufferSize(65536, false); err != nil { 149 t.Fatal(err) 150 } 151 sizes, err := h.GetSocketReceiveBufferSize() 152 if err != nil { 153 t.Fatal(err) 154 } 155 if len(sizes) != len(h.sockets) { 156 t.Fatalf("Unexpected number of socket buffer sizes: %d (expected %d)", 157 len(sizes), len(h.sockets)) 158 } 159 for _, s := range sizes { 160 if s < 65536 || s > 2*65536 { 161 t.Fatalf("Unexpected socket receive buffer size: %d (expected around %d)", 162 s, 65536) 163 } 164 } 165 } 166 167 var ( 168 iter = 10 169 numThread = uint32(4) 170 prefix = "iface" 171 handle1 *Handle 172 handle2 *Handle 173 ns1 netns.NsHandle 174 ns2 netns.NsHandle 175 done uint32 176 initError error 177 once sync.Once 178 ) 179 180 func getXfrmState(thread int) *XfrmState { 181 return &XfrmState{ 182 Src: net.IPv4(byte(192), byte(168), 1, byte(1+thread)), 183 Dst: net.IPv4(byte(192), byte(168), 2, byte(1+thread)), 184 Proto: XFRM_PROTO_AH, 185 Mode: XFRM_MODE_TUNNEL, 186 Spi: thread, 187 Auth: &XfrmStateAlgo{ 188 Name: "hmac(sha256)", 189 Key: []byte("abcdefghijklmnopqrstuvwzyzABCDEF"), 190 }, 191 } 192 } 193 194 func getXfrmPolicy(thread int) *XfrmPolicy { 195 return &XfrmPolicy{ 196 Src: &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}}, 197 Dst: &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}}, 198 Proto: 17, 199 DstPort: 1234, 200 SrcPort: 5678, 201 Dir: XFRM_DIR_OUT, 202 Tmpls: []XfrmPolicyTmpl{ 203 { 204 Src: net.IPv4(byte(192), byte(168), 1, byte(thread)), 205 Dst: net.IPv4(byte(192), byte(168), 2, byte(thread)), 206 Proto: XFRM_PROTO_ESP, 207 Mode: XFRM_MODE_TUNNEL, 208 }, 209 }, 210 } 211 } 212 func initParallel() { 213 ns1, initError = netns.New() 214 if initError != nil { 215 return 216 } 217 handle1, initError = NewHandleAt(ns1) 218 if initError != nil { 219 return 220 } 221 ns2, initError = netns.New() 222 if initError != nil { 223 return 224 } 225 handle2, initError = NewHandleAt(ns2) 226 if initError != nil { 227 return 228 } 229 } 230 231 func parallelDone() { 232 atomic.AddUint32(&done, 1) 233 if done == numThread { 234 if ns1.IsOpen() { 235 ns1.Close() 236 } 237 if ns2.IsOpen() { 238 ns2.Close() 239 } 240 if handle1 != nil { 241 handle1.Close() 242 } 243 if handle2 != nil { 244 handle2.Close() 245 } 246 } 247 } 248 249 // Do few route and xfrm operation on the two handles in parallel 250 func runParallelTests(t *testing.T, thread int) { 251 skipUnlessRoot(t) 252 defer parallelDone() 253 254 t.Parallel() 255 256 once.Do(initParallel) 257 if initError != nil { 258 t.Fatal(initError) 259 } 260 261 state := getXfrmState(thread) 262 policy := getXfrmPolicy(thread) 263 for i := 0; i < iter; i++ { 264 ifName := fmt.Sprintf("%s_%d_%d", prefix, thread, i) 265 link := &Dummy{LinkAttrs{Name: ifName}} 266 err := handle1.LinkAdd(link) 267 if err != nil { 268 t.Fatal(err) 269 } 270 l, err := handle1.LinkByName(ifName) 271 if err != nil { 272 t.Fatal(err) 273 } 274 err = handle1.LinkSetUp(l) 275 if err != nil { 276 t.Fatal(err) 277 } 278 handle1.LinkSetNsFd(l, int(ns2)) 279 if err != nil { 280 t.Fatal(err) 281 } 282 err = handle1.XfrmStateAdd(state) 283 if err != nil { 284 t.Fatal(err) 285 } 286 err = handle1.XfrmPolicyAdd(policy) 287 if err != nil { 288 t.Fatal(err) 289 } 290 err = handle2.LinkSetDown(l) 291 if err != nil { 292 t.Fatal(err) 293 } 294 err = handle2.XfrmStateAdd(state) 295 if err != nil { 296 t.Fatal(err) 297 } 298 err = handle2.XfrmPolicyAdd(policy) 299 if err != nil { 300 t.Fatal(err) 301 } 302 _, err = handle2.LinkByName(ifName) 303 if err != nil { 304 t.Fatal(err) 305 } 306 handle2.LinkSetNsFd(l, int(ns1)) 307 if err != nil { 308 t.Fatal(err) 309 } 310 err = handle1.LinkSetUp(l) 311 if err != nil { 312 t.Fatal(err) 313 } 314 _, err = handle1.LinkByName(ifName) 315 if err != nil { 316 t.Fatal(err) 317 } 318 err = handle1.XfrmPolicyDel(policy) 319 if err != nil { 320 t.Fatal(err) 321 } 322 err = handle2.XfrmPolicyDel(policy) 323 if err != nil { 324 t.Fatal(err) 325 } 326 err = handle1.XfrmStateDel(state) 327 if err != nil { 328 t.Fatal(err) 329 } 330 err = handle2.XfrmStateDel(state) 331 if err != nil { 332 t.Fatal(err) 333 } 334 } 335 } 336 337 func TestHandleParallel1(t *testing.T) { 338 runParallelTests(t, 1) 339 } 340 341 func TestHandleParallel2(t *testing.T) { 342 runParallelTests(t, 2) 343 } 344 345 func TestHandleParallel3(t *testing.T) { 346 runParallelTests(t, 3) 347 } 348 349 func TestHandleParallel4(t *testing.T) { 350 runParallelTests(t, 4) 351 }