Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 2109 lines 66 kB view raw
1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3 4import errno 5import time 6from lib.py import ( 7 ksft_run, 8 ksft_exit, 9 ksft_eq, 10 ksft_ne, 11 ksft_in, 12 ksft_not_in, 13 ksft_raises, 14) 15from lib.py import ( 16 NetNS, 17 NetNSEnter, 18 EthtoolFamily, 19 NetdevFamily, 20 RtnlFamily, 21 NetdevSimDev, 22) 23from lib.py import ( 24 NlError, 25 Netlink, 26 cmd, 27 defer, 28 ip, 29) 30 31 32def wait_until(cond, timeout=2.0, interval=0.05): 33 deadline = time.monotonic() + timeout 34 while not cond(): 35 if time.monotonic() >= deadline: 36 return 37 time.sleep(interval) 38 39 40def create_netkit(rxqueues, mode="l2"): 41 all_links = ip("-d link show", json=True) 42 old_idxs = { 43 link["ifindex"] 44 for link in all_links 45 if link.get("linkinfo", {}).get("info_kind") == "netkit" 46 } 47 48 rtnl = RtnlFamily() 49 rtnl.newlink( 50 { 51 "linkinfo": { 52 "kind": "netkit", 53 "data": { 54 "mode": mode, 55 "policy": "forward", 56 "peer-policy": "forward", 57 }, 58 }, 59 "num-rx-queues": rxqueues, 60 }, 61 flags=[Netlink.NLM_F_CREATE, Netlink.NLM_F_EXCL], 62 ) 63 64 all_links = ip("-d link show", json=True) 65 nk_links = [ 66 link 67 for link in all_links 68 if link.get("linkinfo", {}).get("info_kind") == "netkit" 69 and link["ifindex"] not in old_idxs 70 ] 71 nk_links.sort(key=lambda x: x["ifindex"]) 72 return ( 73 nk_links[1]["ifname"], 74 nk_links[1]["ifindex"], 75 nk_links[0]["ifname"], 76 nk_links[0]["ifindex"], 77 ) 78 79 80def create_netkit_single(rxqueues): 81 rtnl = RtnlFamily() 82 rtnl.newlink( 83 { 84 "linkinfo": { 85 "kind": "netkit", 86 "data": { 87 "mode": "l2", 88 "pairing": "single", 89 }, 90 }, 91 "num-rx-queues": rxqueues, 92 }, 93 flags=[Netlink.NLM_F_CREATE, Netlink.NLM_F_EXCL], 94 ) 95 96 all_links = ip("-d link show", json=True) 97 nk_links = [ 98 link 99 for link in all_links 100 if link.get("linkinfo", {}).get("info_kind") == "netkit" 101 and "UP" not in link.get("flags", []) 102 ] 103 return nk_links[0]["ifname"], nk_links[0]["ifindex"] 104 105 106def test_remove_phys(netns) -> None: 107 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 108 defer(nsimdev.remove) 109 nsim = nsimdev.nsims[0] 110 ip(f"link set dev {nsim.ifname} up") 111 112 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 113 defer(cmd, f"ip link del dev {nk_host}", fail=False) 114 115 ip(f"link set dev {nk_guest} netns {netns.name}") 116 ip(f"link set dev {nk_host} up") 117 ip(f"link set dev {nk_guest} up", ns=netns) 118 119 src_queue = 1 120 with NetNSEnter(str(netns)): 121 netdevnl = NetdevFamily() 122 result = netdevnl.queue_create( 123 { 124 "ifindex": nk_guest_idx, 125 "type": "rx", 126 "lease": { 127 "ifindex": nsim.ifindex, 128 "queue": {"id": src_queue, "type": "rx"}, 129 "netns-id": 0, 130 }, 131 } 132 ) 133 nk_queue_id = result["id"] 134 135 netdevnl = NetdevFamily() 136 queue_info = netdevnl.queue_get( 137 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 138 ) 139 ksft_in("lease", queue_info) 140 ksft_eq(queue_info["lease"]["ifindex"], nk_guest_idx) 141 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 142 143 nsimdev.remove() 144 wait_until(lambda: cmd(f"ip link show dev {nk_host}", fail=False).ret != 0) 145 ret = cmd(f"ip link show dev {nk_host}", fail=False) 146 ksft_ne(ret.ret, 0) 147 148 149def test_double_lease(netns) -> None: 150 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 151 defer(nsimdev.remove) 152 nsim = nsimdev.nsims[0] 153 ip(f"link set dev {nsim.ifname} up") 154 155 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=3) 156 defer(cmd, f"ip link del dev {nk_host}") 157 158 ip(f"link set dev {nk_guest} netns {netns.name}") 159 ip(f"link set dev {nk_host} up") 160 ip(f"link set dev {nk_guest} up", ns=netns) 161 162 src_queue = 1 163 with NetNSEnter(str(netns)): 164 netdevnl = NetdevFamily() 165 result = netdevnl.queue_create( 166 { 167 "ifindex": nk_guest_idx, 168 "type": "rx", 169 "lease": { 170 "ifindex": nsim.ifindex, 171 "queue": {"id": src_queue, "type": "rx"}, 172 "netns-id": 0, 173 }, 174 } 175 ) 176 ksft_eq(result["id"], 1) 177 178 with ksft_raises(NlError) as e: 179 netdevnl.queue_create( 180 { 181 "ifindex": nk_guest_idx, 182 "type": "rx", 183 "lease": { 184 "ifindex": nsim.ifindex, 185 "queue": {"id": src_queue, "type": "rx"}, 186 "netns-id": 0, 187 }, 188 } 189 ) 190 ksft_eq(e.exception.nl_msg.error, -errno.EBUSY) 191 192 193def test_virtual_lessor(netns) -> None: 194 nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) 195 defer(cmd, f"ip link del dev {nk_host_a}") 196 ip(f"link set dev {nk_host_a} up") 197 ip(f"link set dev {nk_guest_a} up") 198 199 nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) 200 defer(cmd, f"ip link del dev {nk_host_b}") 201 202 ip(f"link set dev {nk_guest_b} netns {netns.name}") 203 ip(f"link set dev {nk_host_b} up") 204 ip(f"link set dev {nk_guest_b} up", ns=netns) 205 206 with NetNSEnter(str(netns)): 207 netdevnl = NetdevFamily() 208 with ksft_raises(NlError) as e: 209 netdevnl.queue_create( 210 { 211 "ifindex": nk_guest_b_idx, 212 "type": "rx", 213 "lease": { 214 "ifindex": nk_guest_a_idx, 215 "queue": {"id": 0, "type": "rx"}, 216 "netns-id": 0, 217 }, 218 } 219 ) 220 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 221 222 223def test_phys_lessee(_netns) -> None: 224 nsimdev_a = NetdevSimDev(port_count=1, queue_count=2) 225 defer(nsimdev_a.remove) 226 nsim_a = nsimdev_a.nsims[0] 227 ip(f"link set dev {nsim_a.ifname} up") 228 229 nsimdev_b = NetdevSimDev(port_count=1, queue_count=2) 230 defer(nsimdev_b.remove) 231 nsim_b = nsimdev_b.nsims[0] 232 ip(f"link set dev {nsim_b.ifname} up") 233 234 netdevnl = NetdevFamily() 235 with ksft_raises(NlError) as e: 236 netdevnl.queue_create( 237 { 238 "ifindex": nsim_a.ifindex, 239 "type": "rx", 240 "lease": { 241 "ifindex": nsim_b.ifindex, 242 "queue": {"id": 0, "type": "rx"}, 243 }, 244 } 245 ) 246 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 247 248 249def test_different_lessors(netns) -> None: 250 nsimdev_a = NetdevSimDev(port_count=1, queue_count=2) 251 defer(nsimdev_a.remove) 252 nsim_a = nsimdev_a.nsims[0] 253 ip(f"link set dev {nsim_a.ifname} up") 254 255 nsimdev_b = NetdevSimDev(port_count=1, queue_count=2) 256 defer(nsimdev_b.remove) 257 nsim_b = nsimdev_b.nsims[0] 258 ip(f"link set dev {nsim_b.ifname} up") 259 260 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=3) 261 defer(cmd, f"ip link del dev {nk_host}", fail=False) 262 263 ip(f"link set dev {nk_guest} netns {netns.name}") 264 ip(f"link set dev {nk_host} up") 265 ip(f"link set dev {nk_guest} up", ns=netns) 266 267 with NetNSEnter(str(netns)): 268 netdevnl = NetdevFamily() 269 netdevnl.queue_create( 270 { 271 "ifindex": nk_guest_idx, 272 "type": "rx", 273 "lease": { 274 "ifindex": nsim_a.ifindex, 275 "queue": {"id": 1, "type": "rx"}, 276 "netns-id": 0, 277 }, 278 } 279 ) 280 281 with ksft_raises(NlError) as e: 282 netdevnl.queue_create( 283 { 284 "ifindex": nk_guest_idx, 285 "type": "rx", 286 "lease": { 287 "ifindex": nsim_b.ifindex, 288 "queue": {"id": 1, "type": "rx"}, 289 "netns-id": 0, 290 }, 291 } 292 ) 293 ksft_eq(e.exception.nl_msg.error, -errno.EOPNOTSUPP) 294 295 296def test_queue_out_of_range(netns) -> None: 297 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 298 defer(nsimdev.remove) 299 nsim = nsimdev.nsims[0] 300 ip(f"link set dev {nsim.ifname} up") 301 302 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 303 defer(cmd, f"ip link del dev {nk_host}", fail=False) 304 305 ip(f"link set dev {nk_guest} netns {netns.name}") 306 ip(f"link set dev {nk_host} up") 307 ip(f"link set dev {nk_guest} up", ns=netns) 308 309 with NetNSEnter(str(netns)): 310 netdevnl = NetdevFamily() 311 with ksft_raises(NlError) as e: 312 netdevnl.queue_create( 313 { 314 "ifindex": nk_guest_idx, 315 "type": "rx", 316 "lease": { 317 "ifindex": nsim.ifindex, 318 "queue": {"id": 2, "type": "rx"}, 319 "netns-id": 0, 320 }, 321 } 322 ) 323 ksft_eq(e.exception.nl_msg.error, -errno.ERANGE) 324 325 326def test_resize_leased(netns) -> None: 327 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 328 defer(nsimdev.remove) 329 nsim = nsimdev.nsims[0] 330 ip(f"link set dev {nsim.ifname} up") 331 332 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 333 defer(cmd, f"ip link del dev {nk_host}", fail=False) 334 335 ip(f"link set dev {nk_guest} netns {netns.name}") 336 ip(f"link set dev {nk_host} up") 337 ip(f"link set dev {nk_guest} up", ns=netns) 338 339 with NetNSEnter(str(netns)): 340 netdevnl = NetdevFamily() 341 netdevnl.queue_create( 342 { 343 "ifindex": nk_guest_idx, 344 "type": "rx", 345 "lease": { 346 "ifindex": nsim.ifindex, 347 "queue": {"id": 1, "type": "rx"}, 348 "netns-id": 0, 349 }, 350 } 351 ) 352 353 ethnl = EthtoolFamily() 354 with ksft_raises(NlError) as e: 355 ethnl.channels_set({"header": {"dev-index": nsim.ifindex}, "combined-count": 1}) 356 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 357 358 359def test_self_lease(_netns) -> None: 360 nk_host, _, _, nk_guest_idx = create_netkit(rxqueues=2) 361 defer(cmd, f"ip link del dev {nk_host}", fail=False) 362 363 netdevnl = NetdevFamily() 364 with ksft_raises(NlError) as e: 365 netdevnl.queue_create( 366 { 367 "ifindex": nk_guest_idx, 368 "type": "rx", 369 "lease": { 370 "ifindex": nk_guest_idx, 371 "queue": {"id": 0, "type": "rx"}, 372 }, 373 } 374 ) 375 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 376 377 378def test_veth_queue_create(netns) -> None: 379 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 380 defer(nsimdev.remove) 381 nsim = nsimdev.nsims[0] 382 ip(f"link set dev {nsim.ifname} up") 383 384 ip("link add veth0 type veth peer name veth1") 385 defer(cmd, "ip link del dev veth0", fail=False) 386 387 all_links = ip("-d link show", json=True) 388 veth_peer = [ 389 link 390 for link in all_links 391 if link.get("ifname") == "veth1" 392 ] 393 veth_peer_idx = veth_peer[0]["ifindex"] 394 395 ip(f"link set dev veth1 netns {netns.name}") 396 ip("link set dev veth0 up") 397 ip("link set dev veth1 up", ns=netns) 398 399 with NetNSEnter(str(netns)): 400 netdevnl = NetdevFamily() 401 with ksft_raises(NlError) as e: 402 netdevnl.queue_create( 403 { 404 "ifindex": veth_peer_idx, 405 "type": "rx", 406 "lease": { 407 "ifindex": nsim.ifindex, 408 "queue": {"id": 1, "type": "rx"}, 409 "netns-id": 0, 410 }, 411 } 412 ) 413 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 414 415 416def test_create_tx_type(netns) -> None: 417 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 418 defer(nsimdev.remove) 419 nsim = nsimdev.nsims[0] 420 ip(f"link set dev {nsim.ifname} up") 421 422 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 423 defer(cmd, f"ip link del dev {nk_host}", fail=False) 424 425 ip(f"link set dev {nk_guest} netns {netns.name}") 426 ip(f"link set dev {nk_host} up") 427 ip(f"link set dev {nk_guest} up", ns=netns) 428 429 with NetNSEnter(str(netns)): 430 netdevnl = NetdevFamily() 431 with ksft_raises(NlError) as e: 432 netdevnl.queue_create( 433 { 434 "ifindex": nk_guest_idx, 435 "type": "tx", 436 "lease": { 437 "ifindex": nsim.ifindex, 438 "queue": {"id": 1, "type": "rx"}, 439 "netns-id": 0, 440 }, 441 } 442 ) 443 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 444 445 446def test_create_primary(_netns) -> None: 447 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 448 defer(nsimdev.remove) 449 nsim = nsimdev.nsims[0] 450 ip(f"link set dev {nsim.ifname} up") 451 452 nk_host, nk_host_idx, _, _ = create_netkit(rxqueues=2) 453 defer(cmd, f"ip link del dev {nk_host}", fail=False) 454 455 ip(f"link set dev {nk_host} up") 456 457 netdevnl = NetdevFamily() 458 with ksft_raises(NlError) as e: 459 netdevnl.queue_create( 460 { 461 "ifindex": nk_host_idx, 462 "type": "rx", 463 "lease": { 464 "ifindex": nsim.ifindex, 465 "queue": {"id": 1, "type": "rx"}, 466 }, 467 } 468 ) 469 ksft_eq(e.exception.nl_msg.error, -errno.EOPNOTSUPP) 470 471 472def test_create_limit(netns) -> None: 473 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 474 defer(nsimdev.remove) 475 nsim = nsimdev.nsims[0] 476 ip(f"link set dev {nsim.ifname} up") 477 478 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=1) 479 defer(cmd, f"ip link del dev {nk_host}", fail=False) 480 481 ip(f"link set dev {nk_guest} netns {netns.name}") 482 ip(f"link set dev {nk_host} up") 483 ip(f"link set dev {nk_guest} up", ns=netns) 484 485 with NetNSEnter(str(netns)): 486 netdevnl = NetdevFamily() 487 with ksft_raises(NlError) as e: 488 netdevnl.queue_create( 489 { 490 "ifindex": nk_guest_idx, 491 "type": "rx", 492 "lease": { 493 "ifindex": nsim.ifindex, 494 "queue": {"id": 1, "type": "rx"}, 495 "netns-id": 0, 496 }, 497 } 498 ) 499 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 500 501 502def test_link_flap_phys(netns) -> None: 503 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 504 defer(nsimdev.remove) 505 nsim = nsimdev.nsims[0] 506 ip(f"link set dev {nsim.ifname} up") 507 508 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 509 defer(cmd, f"ip link del dev {nk_host}") 510 511 ip(f"link set dev {nk_guest} netns {netns.name}") 512 ip(f"link set dev {nk_host} up") 513 ip(f"link set dev {nk_guest} up", ns=netns) 514 515 src_queue = 1 516 with NetNSEnter(str(netns)): 517 netdevnl = NetdevFamily() 518 result = netdevnl.queue_create( 519 { 520 "ifindex": nk_guest_idx, 521 "type": "rx", 522 "lease": { 523 "ifindex": nsim.ifindex, 524 "queue": {"id": src_queue, "type": "rx"}, 525 "netns-id": 0, 526 }, 527 } 528 ) 529 nk_queue_id = result["id"] 530 531 netdevnl = NetdevFamily() 532 queue_info = netdevnl.queue_get( 533 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 534 ) 535 ksft_in("lease", queue_info) 536 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 537 538 # Link flap the physical device 539 ip(f"link set dev {nsim.ifname} down") 540 ip(f"link set dev {nsim.ifname} up") 541 542 # Verify lease survives the flap 543 queue_info = netdevnl.queue_get( 544 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 545 ) 546 ksft_in("lease", queue_info) 547 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 548 549 550def test_queue_get_virtual(netns) -> None: 551 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 552 defer(nsimdev.remove) 553 nsim = nsimdev.nsims[0] 554 ip(f"link set dev {nsim.ifname} up") 555 556 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 557 defer(cmd, f"ip link del dev {nk_host}") 558 559 ip(f"link set dev {nk_guest} netns {netns.name}") 560 ip(f"link set dev {nk_host} up") 561 ip(f"link set dev {nk_guest} up", ns=netns) 562 563 src_queue = 1 564 with NetNSEnter(str(netns)): 565 netdevnl = NetdevFamily() 566 result = netdevnl.queue_create( 567 { 568 "ifindex": nk_guest_idx, 569 "type": "rx", 570 "lease": { 571 "ifindex": nsim.ifindex, 572 "queue": {"id": src_queue, "type": "rx"}, 573 "netns-id": 0, 574 }, 575 } 576 ) 577 nk_queue_id = result["id"] 578 579 # queue-get on virtual device's leased queue should not show lease 580 # info (lease info is only shown from the physical device's side) 581 queue_info = netdevnl.queue_get( 582 {"ifindex": nk_guest_idx, "id": nk_queue_id, "type": "rx"} 583 ) 584 ksft_eq(queue_info["id"], nk_queue_id) 585 ksft_eq(queue_info["ifindex"], nk_guest_idx) 586 ksft_not_in("lease", queue_info) 587 588 # Default queue (not leased) also has no lease info 589 queue_info = netdevnl.queue_get( 590 {"ifindex": nk_guest_idx, "id": 0, "type": "rx"} 591 ) 592 ksft_not_in("lease", queue_info) 593 594 595def test_remove_virt_first(netns) -> None: 596 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 597 defer(nsimdev.remove) 598 nsim = nsimdev.nsims[0] 599 ip(f"link set dev {nsim.ifname} up") 600 601 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 602 603 ip(f"link set dev {nk_guest} netns {netns.name}") 604 ip(f"link set dev {nk_host} up") 605 ip(f"link set dev {nk_guest} up", ns=netns) 606 607 src_queue = 1 608 with NetNSEnter(str(netns)): 609 netdevnl = NetdevFamily() 610 result = netdevnl.queue_create( 611 { 612 "ifindex": nk_guest_idx, 613 "type": "rx", 614 "lease": { 615 "ifindex": nsim.ifindex, 616 "queue": {"id": src_queue, "type": "rx"}, 617 "netns-id": 0, 618 }, 619 } 620 ) 621 ksft_eq(result["id"], 1) 622 623 netdevnl = NetdevFamily() 624 queue_info = netdevnl.queue_get( 625 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 626 ) 627 ksft_in("lease", queue_info) 628 ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) 629 630 # Delete netkit (virtual device removed first, physical stays) 631 cmd(f"ip link del dev {nk_host}") 632 633 # Verify lease is cleaned up on physical device 634 queue_info = netdevnl.queue_get( 635 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 636 ) 637 ksft_not_in("lease", queue_info) 638 639 640def test_multiple_leases(netns) -> None: 641 nsimdev = NetdevSimDev(port_count=1, queue_count=3) 642 defer(nsimdev.remove) 643 nsim = nsimdev.nsims[0] 644 ip(f"link set dev {nsim.ifname} up") 645 646 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=4) 647 defer(cmd, f"ip link del dev {nk_host}", fail=False) 648 649 ip(f"link set dev {nk_guest} netns {netns.name}") 650 ip(f"link set dev {nk_host} up") 651 ip(f"link set dev {nk_guest} up", ns=netns) 652 653 with NetNSEnter(str(netns)): 654 netdevnl = NetdevFamily() 655 r1 = netdevnl.queue_create( 656 { 657 "ifindex": nk_guest_idx, 658 "type": "rx", 659 "lease": { 660 "ifindex": nsim.ifindex, 661 "queue": {"id": 1, "type": "rx"}, 662 "netns-id": 0, 663 }, 664 } 665 ) 666 r2 = netdevnl.queue_create( 667 { 668 "ifindex": nk_guest_idx, 669 "type": "rx", 670 "lease": { 671 "ifindex": nsim.ifindex, 672 "queue": {"id": 2, "type": "rx"}, 673 "netns-id": 0, 674 }, 675 } 676 ) 677 678 ksft_eq(r1["id"], 1) 679 ksft_eq(r2["id"], 2) 680 681 # Verify both leases visible on physical device 682 netdevnl = NetdevFamily() 683 q1 = netdevnl.queue_get( 684 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 685 ) 686 q2 = netdevnl.queue_get( 687 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 688 ) 689 ksft_in("lease", q1) 690 ksft_in("lease", q2) 691 ksft_eq(q1["lease"]["ifindex"], nk_guest_idx) 692 ksft_eq(q2["lease"]["ifindex"], nk_guest_idx) 693 ksft_eq(q1["lease"]["queue"]["id"], r1["id"]) 694 ksft_eq(q2["lease"]["queue"]["id"], r2["id"]) 695 696 697def test_lease_queue_tx_type(netns) -> None: 698 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 699 defer(nsimdev.remove) 700 nsim = nsimdev.nsims[0] 701 ip(f"link set dev {nsim.ifname} up") 702 703 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 704 defer(cmd, f"ip link del dev {nk_host}", fail=False) 705 706 ip(f"link set dev {nk_guest} netns {netns.name}") 707 ip(f"link set dev {nk_host} up") 708 ip(f"link set dev {nk_guest} up", ns=netns) 709 710 with NetNSEnter(str(netns)): 711 netdevnl = NetdevFamily() 712 with ksft_raises(NlError) as e: 713 netdevnl.queue_create( 714 { 715 "ifindex": nk_guest_idx, 716 "type": "rx", 717 "lease": { 718 "ifindex": nsim.ifindex, 719 "queue": {"id": 1, "type": "tx"}, 720 "netns-id": 0, 721 }, 722 } 723 ) 724 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 725 726 727def test_invalid_netns(netns) -> None: 728 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 729 defer(cmd, f"ip link del dev {nk_host}", fail=False) 730 731 ip(f"link set dev {nk_guest} netns {netns.name}") 732 ip(f"link set dev {nk_host} up") 733 ip(f"link set dev {nk_guest} up", ns=netns) 734 735 with NetNSEnter(str(netns)): 736 netdevnl = NetdevFamily() 737 with ksft_raises(NlError) as e: 738 netdevnl.queue_create( 739 { 740 "ifindex": nk_guest_idx, 741 "type": "rx", 742 "lease": { 743 "ifindex": 1, 744 "queue": {"id": 0, "type": "rx"}, 745 "netns-id": 999, 746 }, 747 } 748 ) 749 ksft_eq(e.exception.nl_msg.error, -errno.ENONET) 750 751 752def test_invalid_phys_ifindex(netns) -> None: 753 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 754 defer(cmd, f"ip link del dev {nk_host}", fail=False) 755 756 ip(f"link set dev {nk_guest} netns {netns.name}") 757 ip(f"link set dev {nk_host} up") 758 ip(f"link set dev {nk_guest} up", ns=netns) 759 760 with NetNSEnter(str(netns)): 761 netdevnl = NetdevFamily() 762 with ksft_raises(NlError) as e: 763 netdevnl.queue_create( 764 { 765 "ifindex": nk_guest_idx, 766 "type": "rx", 767 "lease": { 768 "ifindex": 99999, 769 "queue": {"id": 0, "type": "rx"}, 770 "netns-id": 0, 771 }, 772 } 773 ) 774 ksft_eq(e.exception.nl_msg.error, -errno.ENODEV) 775 776 777def test_multi_netkit_remove_phys(netns) -> None: 778 nsimdev = NetdevSimDev(port_count=1, queue_count=3) 779 defer(nsimdev.remove) 780 nsim = nsimdev.nsims[0] 781 ip(f"link set dev {nsim.ifname} up") 782 783 # Create two netkit pairs, each leasing a different physical queue 784 nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) 785 defer(cmd, f"ip link del dev {nk_host_a}", fail=False) 786 787 nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) 788 defer(cmd, f"ip link del dev {nk_host_b}", fail=False) 789 790 ip(f"link set dev {nk_guest_a} netns {netns.name}") 791 ip(f"link set dev {nk_host_a} up") 792 ip(f"link set dev {nk_guest_a} up", ns=netns) 793 794 ip(f"link set dev {nk_guest_b} netns {netns.name}") 795 ip(f"link set dev {nk_host_b} up") 796 ip(f"link set dev {nk_guest_b} up", ns=netns) 797 798 with NetNSEnter(str(netns)): 799 netdevnl = NetdevFamily() 800 netdevnl.queue_create( 801 { 802 "ifindex": nk_guest_a_idx, 803 "type": "rx", 804 "lease": { 805 "ifindex": nsim.ifindex, 806 "queue": {"id": 1, "type": "rx"}, 807 "netns-id": 0, 808 }, 809 } 810 ) 811 netdevnl.queue_create( 812 { 813 "ifindex": nk_guest_b_idx, 814 "type": "rx", 815 "lease": { 816 "ifindex": nsim.ifindex, 817 "queue": {"id": 2, "type": "rx"}, 818 "netns-id": 0, 819 }, 820 } 821 ) 822 823 # Removing the physical device should take down both netkit pairs 824 nsimdev.remove() 825 wait_until(lambda: cmd(f"ip link show dev {nk_host_a}", fail=False).ret != 0 826 and cmd(f"ip link show dev {nk_host_b}", fail=False).ret != 0) 827 ret = cmd(f"ip link show dev {nk_host_a}", fail=False) 828 ksft_ne(ret.ret, 0) 829 ret = cmd(f"ip link show dev {nk_host_b}", fail=False) 830 ksft_ne(ret.ret, 0) 831 832 833def test_single_remove_phys(_netns) -> None: 834 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 835 defer(nsimdev.remove) 836 nsim = nsimdev.nsims[0] 837 ip(f"link set dev {nsim.ifname} up") 838 839 nk_name, nk_idx = create_netkit_single(rxqueues=2) 840 defer(cmd, f"ip link del dev {nk_name}", fail=False) 841 842 ip(f"link set dev {nk_name} up") 843 844 netdevnl = NetdevFamily() 845 netdevnl.queue_create( 846 { 847 "ifindex": nk_idx, 848 "type": "rx", 849 "lease": { 850 "ifindex": nsim.ifindex, 851 "queue": {"id": 1, "type": "rx"}, 852 }, 853 } 854 ) 855 856 # Removing the physical device should take down the single netkit device 857 nsimdev.remove() 858 wait_until(lambda: cmd(f"ip link show dev {nk_name}", fail=False).ret != 0) 859 ret = cmd(f"ip link show dev {nk_name}", fail=False) 860 ksft_ne(ret.ret, 0) 861 862 863def test_link_flap_virt(netns) -> None: 864 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 865 defer(nsimdev.remove) 866 nsim = nsimdev.nsims[0] 867 ip(f"link set dev {nsim.ifname} up") 868 869 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 870 defer(cmd, f"ip link del dev {nk_host}") 871 872 ip(f"link set dev {nk_guest} netns {netns.name}") 873 ip(f"link set dev {nk_host} up") 874 ip(f"link set dev {nk_guest} up", ns=netns) 875 876 src_queue = 1 877 with NetNSEnter(str(netns)): 878 netdevnl = NetdevFamily() 879 result = netdevnl.queue_create( 880 { 881 "ifindex": nk_guest_idx, 882 "type": "rx", 883 "lease": { 884 "ifindex": nsim.ifindex, 885 "queue": {"id": src_queue, "type": "rx"}, 886 "netns-id": 0, 887 }, 888 } 889 ) 890 nk_queue_id = result["id"] 891 892 netdevnl = NetdevFamily() 893 queue_info = netdevnl.queue_get( 894 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 895 ) 896 ksft_in("lease", queue_info) 897 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 898 899 # Link flap the virtual (netkit) device 900 ip(f"link set dev {nk_guest} down", ns=netns) 901 ip(f"link set dev {nk_guest} up", ns=netns) 902 903 # Verify lease survives the virtual device flap 904 queue_info = netdevnl.queue_get( 905 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 906 ) 907 ksft_in("lease", queue_info) 908 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 909 910 911def test_phys_queue_no_lease(netns) -> None: 912 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 913 defer(nsimdev.remove) 914 nsim = nsimdev.nsims[0] 915 ip(f"link set dev {nsim.ifname} up") 916 917 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 918 defer(cmd, f"ip link del dev {nk_host}") 919 920 ip(f"link set dev {nk_guest} netns {netns.name}") 921 ip(f"link set dev {nk_host} up") 922 ip(f"link set dev {nk_guest} up", ns=netns) 923 924 with NetNSEnter(str(netns)): 925 netdevnl = NetdevFamily() 926 netdevnl.queue_create( 927 { 928 "ifindex": nk_guest_idx, 929 "type": "rx", 930 "lease": { 931 "ifindex": nsim.ifindex, 932 "queue": {"id": 1, "type": "rx"}, 933 "netns-id": 0, 934 }, 935 } 936 ) 937 938 # Physical queue 0 (not leased) should have no lease info 939 netdevnl = NetdevFamily() 940 queue_info = netdevnl.queue_get( 941 {"ifindex": nsim.ifindex, "id": 0, "type": "rx"} 942 ) 943 ksft_not_in("lease", queue_info) 944 945 # Physical queue 1 (leased) should have lease info 946 queue_info = netdevnl.queue_get( 947 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 948 ) 949 ksft_in("lease", queue_info) 950 951 952def test_same_ns_lease(_netns) -> None: 953 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 954 defer(nsimdev.remove) 955 nsim = nsimdev.nsims[0] 956 ip(f"link set dev {nsim.ifname} up") 957 958 nk_name, nk_idx = create_netkit_single(rxqueues=2) 959 defer(cmd, f"ip link del dev {nk_name}", fail=False) 960 961 ip(f"link set dev {nk_name} up") 962 963 netdevnl = NetdevFamily() 964 result = netdevnl.queue_create( 965 { 966 "ifindex": nk_idx, 967 "type": "rx", 968 "lease": { 969 "ifindex": nsim.ifindex, 970 "queue": {"id": 1, "type": "rx"}, 971 }, 972 } 973 ) 974 ksft_eq(result["id"], 1) 975 976 # Same namespace: lease info should NOT have netns-id 977 queue_info = netdevnl.queue_get( 978 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 979 ) 980 ksft_in("lease", queue_info) 981 ksft_eq(queue_info["lease"]["ifindex"], nk_idx) 982 ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) 983 ksft_not_in("netns-id", queue_info["lease"]) 984 985 986def test_resize_after_unlease(netns) -> None: 987 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 988 defer(nsimdev.remove) 989 nsim = nsimdev.nsims[0] 990 ip(f"link set dev {nsim.ifname} up") 991 992 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 993 994 ip(f"link set dev {nk_guest} netns {netns.name}") 995 ip(f"link set dev {nk_host} up") 996 ip(f"link set dev {nk_guest} up", ns=netns) 997 998 with NetNSEnter(str(netns)): 999 netdevnl = NetdevFamily() 1000 netdevnl.queue_create( 1001 { 1002 "ifindex": nk_guest_idx, 1003 "type": "rx", 1004 "lease": { 1005 "ifindex": nsim.ifindex, 1006 "queue": {"id": 1, "type": "rx"}, 1007 "netns-id": 0, 1008 }, 1009 } 1010 ) 1011 1012 # Resize should fail while lease is active 1013 ethnl = EthtoolFamily() 1014 with ksft_raises(NlError) as e: 1015 ethnl.channels_set({"header": {"dev-index": nsim.ifindex}, "combined-count": 1}) 1016 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 1017 1018 # Delete netkit, clearing the lease 1019 cmd(f"ip link del dev {nk_host}") 1020 1021 # Resize should now succeed 1022 ethnl.channels_set({"header": {"dev-index": nsim.ifindex}, "combined-count": 1}) 1023 1024 1025def test_lease_queue_zero(netns) -> None: 1026 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1027 defer(nsimdev.remove) 1028 nsim = nsimdev.nsims[0] 1029 ip(f"link set dev {nsim.ifname} up") 1030 1031 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1032 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1033 1034 ip(f"link set dev {nk_guest} netns {netns.name}") 1035 ip(f"link set dev {nk_host} up") 1036 ip(f"link set dev {nk_guest} up", ns=netns) 1037 1038 with NetNSEnter(str(netns)): 1039 netdevnl = NetdevFamily() 1040 result = netdevnl.queue_create( 1041 { 1042 "ifindex": nk_guest_idx, 1043 "type": "rx", 1044 "lease": { 1045 "ifindex": nsim.ifindex, 1046 "queue": {"id": 0, "type": "rx"}, 1047 "netns-id": 0, 1048 }, 1049 } 1050 ) 1051 ksft_eq(result["id"], 1) 1052 1053 netdevnl = NetdevFamily() 1054 queue_info = netdevnl.queue_get( 1055 {"ifindex": nsim.ifindex, "id": 0, "type": "rx"} 1056 ) 1057 ksft_in("lease", queue_info) 1058 ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) 1059 1060 1061def test_release_and_reuse(netns) -> None: 1062 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1063 defer(nsimdev.remove) 1064 nsim = nsimdev.nsims[0] 1065 ip(f"link set dev {nsim.ifname} up") 1066 1067 src_queue = 1 1068 1069 # First lease 1070 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1071 1072 ip(f"link set dev {nk_guest} netns {netns.name}") 1073 ip(f"link set dev {nk_host} up") 1074 ip(f"link set dev {nk_guest} up", ns=netns) 1075 1076 with NetNSEnter(str(netns)): 1077 netdevnl = NetdevFamily() 1078 netdevnl.queue_create( 1079 { 1080 "ifindex": nk_guest_idx, 1081 "type": "rx", 1082 "lease": { 1083 "ifindex": nsim.ifindex, 1084 "queue": {"id": src_queue, "type": "rx"}, 1085 "netns-id": 0, 1086 }, 1087 } 1088 ) 1089 1090 netdevnl = NetdevFamily() 1091 queue_info = netdevnl.queue_get( 1092 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1093 ) 1094 ksft_in("lease", queue_info) 1095 1096 # Delete netkit, freeing the lease 1097 cmd(f"ip link del dev {nk_host}") 1098 1099 queue_info = netdevnl.queue_get( 1100 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1101 ) 1102 ksft_not_in("lease", queue_info) 1103 1104 # Re-create netkit and lease the same physical queue again 1105 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1106 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1107 1108 ip(f"link set dev {nk_guest} netns {netns.name}") 1109 ip(f"link set dev {nk_host} up") 1110 ip(f"link set dev {nk_guest} up", ns=netns) 1111 1112 with NetNSEnter(str(netns)): 1113 netdevnl = NetdevFamily() 1114 result = netdevnl.queue_create( 1115 { 1116 "ifindex": nk_guest_idx, 1117 "type": "rx", 1118 "lease": { 1119 "ifindex": nsim.ifindex, 1120 "queue": {"id": src_queue, "type": "rx"}, 1121 "netns-id": 0, 1122 }, 1123 } 1124 ) 1125 ksft_eq(result["id"], 1) 1126 1127 netdevnl = NetdevFamily() 1128 queue_info = netdevnl.queue_get( 1129 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1130 ) 1131 ksft_in("lease", queue_info) 1132 ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) 1133 1134 1135def test_two_netkits_same_queue(netns) -> None: 1136 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1137 defer(nsimdev.remove) 1138 nsim = nsimdev.nsims[0] 1139 ip(f"link set dev {nsim.ifname} up") 1140 1141 nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) 1142 defer(cmd, f"ip link del dev {nk_host_a}", fail=False) 1143 1144 nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) 1145 defer(cmd, f"ip link del dev {nk_host_b}", fail=False) 1146 1147 ip(f"link set dev {nk_guest_a} netns {netns.name}") 1148 ip(f"link set dev {nk_host_a} up") 1149 ip(f"link set dev {nk_guest_a} up", ns=netns) 1150 1151 ip(f"link set dev {nk_guest_b} netns {netns.name}") 1152 ip(f"link set dev {nk_host_b} up") 1153 ip(f"link set dev {nk_guest_b} up", ns=netns) 1154 1155 src_queue = 1 1156 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1157 netdevnl_ns.queue_create( 1158 { 1159 "ifindex": nk_guest_a_idx, 1160 "type": "rx", 1161 "lease": { 1162 "ifindex": nsim.ifindex, 1163 "queue": {"id": src_queue, "type": "rx"}, 1164 "netns-id": 0, 1165 }, 1166 } 1167 ) 1168 1169 with ksft_raises(NlError) as e: 1170 netdevnl_ns.queue_create( 1171 { 1172 "ifindex": nk_guest_b_idx, 1173 "type": "rx", 1174 "lease": { 1175 "ifindex": nsim.ifindex, 1176 "queue": {"id": src_queue, "type": "rx"}, 1177 "netns-id": 0, 1178 }, 1179 } 1180 ) 1181 ksft_eq(e.exception.nl_msg.error, -errno.EBUSY) 1182 1183 1184def test_l3_mode_lease(netns) -> None: 1185 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1186 defer(nsimdev.remove) 1187 nsim = nsimdev.nsims[0] 1188 ip(f"link set dev {nsim.ifname} up") 1189 1190 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2, mode="l3") 1191 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1192 1193 ip(f"link set dev {nk_guest} netns {netns.name}") 1194 ip(f"link set dev {nk_host} up") 1195 ip(f"link set dev {nk_guest} up", ns=netns) 1196 1197 src_queue = 1 1198 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1199 result = netdevnl_ns.queue_create( 1200 { 1201 "ifindex": nk_guest_idx, 1202 "type": "rx", 1203 "lease": { 1204 "ifindex": nsim.ifindex, 1205 "queue": {"id": src_queue, "type": "rx"}, 1206 "netns-id": 0, 1207 }, 1208 } 1209 ) 1210 ksft_eq(result["id"], 1) 1211 1212 netdevnl = NetdevFamily() 1213 queue_info = netdevnl.queue_get( 1214 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1215 ) 1216 ksft_in("lease", queue_info) 1217 ksft_eq(queue_info["lease"]["ifindex"], nk_guest_idx) 1218 ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) 1219 1220 1221def test_single_double_lease(_netns) -> None: 1222 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1223 defer(nsimdev.remove) 1224 nsim = nsimdev.nsims[0] 1225 ip(f"link set dev {nsim.ifname} up") 1226 1227 nk_name, nk_idx = create_netkit_single(rxqueues=3) 1228 defer(cmd, f"ip link del dev {nk_name}", fail=False) 1229 1230 ip(f"link set dev {nk_name} up") 1231 1232 netdevnl = NetdevFamily() 1233 result = netdevnl.queue_create( 1234 { 1235 "ifindex": nk_idx, 1236 "type": "rx", 1237 "lease": { 1238 "ifindex": nsim.ifindex, 1239 "queue": {"id": 1, "type": "rx"}, 1240 }, 1241 } 1242 ) 1243 ksft_eq(result["id"], 1) 1244 1245 with ksft_raises(NlError) as e: 1246 netdevnl.queue_create( 1247 { 1248 "ifindex": nk_idx, 1249 "type": "rx", 1250 "lease": { 1251 "ifindex": nsim.ifindex, 1252 "queue": {"id": 1, "type": "rx"}, 1253 }, 1254 } 1255 ) 1256 ksft_eq(e.exception.nl_msg.error, -errno.EBUSY) 1257 1258 1259def test_single_different_lessors(_netns) -> None: 1260 nsimdev_a = NetdevSimDev(port_count=1, queue_count=2) 1261 defer(nsimdev_a.remove) 1262 nsim_a = nsimdev_a.nsims[0] 1263 ip(f"link set dev {nsim_a.ifname} up") 1264 1265 nsimdev_b = NetdevSimDev(port_count=1, queue_count=2) 1266 defer(nsimdev_b.remove) 1267 nsim_b = nsimdev_b.nsims[0] 1268 ip(f"link set dev {nsim_b.ifname} up") 1269 1270 nk_name, nk_idx = create_netkit_single(rxqueues=3) 1271 defer(cmd, f"ip link del dev {nk_name}", fail=False) 1272 1273 ip(f"link set dev {nk_name} up") 1274 1275 netdevnl = NetdevFamily() 1276 netdevnl.queue_create( 1277 { 1278 "ifindex": nk_idx, 1279 "type": "rx", 1280 "lease": { 1281 "ifindex": nsim_a.ifindex, 1282 "queue": {"id": 1, "type": "rx"}, 1283 }, 1284 } 1285 ) 1286 1287 with ksft_raises(NlError) as e: 1288 netdevnl.queue_create( 1289 { 1290 "ifindex": nk_idx, 1291 "type": "rx", 1292 "lease": { 1293 "ifindex": nsim_b.ifindex, 1294 "queue": {"id": 1, "type": "rx"}, 1295 }, 1296 } 1297 ) 1298 ksft_eq(e.exception.nl_msg.error, -errno.EOPNOTSUPP) 1299 1300 1301def test_cross_ns_netns_id(netns) -> None: 1302 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1303 defer(nsimdev.remove) 1304 nsim = nsimdev.nsims[0] 1305 ip(f"link set dev {nsim.ifname} up") 1306 1307 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1308 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1309 1310 ip(f"link set dev {nk_guest} netns {netns.name}") 1311 ip(f"link set dev {nk_host} up") 1312 ip(f"link set dev {nk_guest} up", ns=netns) 1313 1314 src_queue = 1 1315 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1316 netdevnl_ns.queue_create( 1317 { 1318 "ifindex": nk_guest_idx, 1319 "type": "rx", 1320 "lease": { 1321 "ifindex": nsim.ifindex, 1322 "queue": {"id": src_queue, "type": "rx"}, 1323 "netns-id": 0, 1324 }, 1325 } 1326 ) 1327 1328 netdevnl = NetdevFamily() 1329 queue_info = netdevnl.queue_get( 1330 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1331 ) 1332 ksft_in("lease", queue_info) 1333 ksft_in("netns-id", queue_info["lease"]) 1334 1335 1336def test_delete_guest_netns(_netns) -> None: 1337 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1338 defer(nsimdev.remove) 1339 nsim = nsimdev.nsims[0] 1340 ip(f"link set dev {nsim.ifname} up") 1341 1342 test_ns = NetNS() 1343 ip("netns set init 0", ns=test_ns) 1344 ip("link set lo up", ns=test_ns) 1345 1346 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1347 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1348 1349 ip(f"link set dev {nk_guest} netns {test_ns.name}") 1350 ip(f"link set dev {nk_host} up") 1351 ip(f"link set dev {nk_guest} up", ns=test_ns) 1352 1353 src_queue = 1 1354 with NetNSEnter(str(test_ns)), NetdevFamily() as netdevnl_ns: 1355 netdevnl_ns.queue_create( 1356 { 1357 "ifindex": nk_guest_idx, 1358 "type": "rx", 1359 "lease": { 1360 "ifindex": nsim.ifindex, 1361 "queue": {"id": src_queue, "type": "rx"}, 1362 "netns-id": 0, 1363 }, 1364 } 1365 ) 1366 1367 netdevnl = NetdevFamily() 1368 queue_info = netdevnl.queue_get( 1369 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1370 ) 1371 ksft_in("lease", queue_info) 1372 1373 del test_ns 1374 wait_until(lambda: "lease" not in netdevnl.queue_get( 1375 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"})) 1376 1377 queue_info = netdevnl.queue_get( 1378 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1379 ) 1380 ksft_not_in("lease", queue_info) 1381 1382 ret = cmd(f"ip link show dev {nk_host}", fail=False) 1383 ksft_ne(ret.ret, 0) 1384 1385 1386def test_move_guest_netns(netns) -> None: 1387 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1388 defer(nsimdev.remove) 1389 nsim = nsimdev.nsims[0] 1390 ip(f"link set dev {nsim.ifname} up") 1391 1392 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1393 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1394 1395 ip(f"link set dev {nk_guest} netns {netns.name}") 1396 ip(f"link set dev {nk_host} up") 1397 ip(f"link set dev {nk_guest} up", ns=netns) 1398 1399 src_queue = 1 1400 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1401 result = netdevnl_ns.queue_create( 1402 { 1403 "ifindex": nk_guest_idx, 1404 "type": "rx", 1405 "lease": { 1406 "ifindex": nsim.ifindex, 1407 "queue": {"id": src_queue, "type": "rx"}, 1408 "netns-id": 0, 1409 }, 1410 } 1411 ) 1412 nk_queue_id = result["id"] 1413 1414 netdevnl = NetdevFamily() 1415 queue_info = netdevnl.queue_get( 1416 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1417 ) 1418 ksft_in("lease", queue_info) 1419 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 1420 1421 new_ns = NetNS() 1422 defer(new_ns.__del__) 1423 ip(f"link set dev {nk_guest} netns {new_ns.name}", ns=netns) 1424 1425 queue_info = netdevnl.queue_get( 1426 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1427 ) 1428 ksft_in("lease", queue_info) 1429 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 1430 1431 1432def test_resize_phys_no_reduction(netns) -> None: 1433 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1434 defer(nsimdev.remove) 1435 nsim = nsimdev.nsims[0] 1436 ip(f"link set dev {nsim.ifname} up") 1437 1438 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1439 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1440 1441 ip(f"link set dev {nk_guest} netns {netns.name}") 1442 ip(f"link set dev {nk_host} up") 1443 ip(f"link set dev {nk_guest} up", ns=netns) 1444 1445 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1446 netdevnl_ns.queue_create( 1447 { 1448 "ifindex": nk_guest_idx, 1449 "type": "rx", 1450 "lease": { 1451 "ifindex": nsim.ifindex, 1452 "queue": {"id": 1, "type": "rx"}, 1453 "netns-id": 0, 1454 }, 1455 } 1456 ) 1457 1458 ethnl = EthtoolFamily() 1459 ethnl.channels_set( 1460 {"header": {"dev-index": nsim.ifindex}, "combined-count": 2} 1461 ) 1462 1463 netdevnl = NetdevFamily() 1464 queue_info = netdevnl.queue_get( 1465 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1466 ) 1467 ksft_in("lease", queue_info) 1468 1469 1470def test_delete_one_netkit_of_two(netns) -> None: 1471 nsimdev = NetdevSimDev(port_count=1, queue_count=3) 1472 defer(nsimdev.remove) 1473 nsim = nsimdev.nsims[0] 1474 ip(f"link set dev {nsim.ifname} up") 1475 1476 nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) 1477 defer(cmd, f"ip link del dev {nk_host_a}", fail=False) 1478 1479 nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) 1480 defer(cmd, f"ip link del dev {nk_host_b}", fail=False) 1481 1482 ip(f"link set dev {nk_guest_a} netns {netns.name}") 1483 ip(f"link set dev {nk_host_a} up") 1484 ip(f"link set dev {nk_guest_a} up", ns=netns) 1485 1486 ip(f"link set dev {nk_guest_b} netns {netns.name}") 1487 ip(f"link set dev {nk_host_b} up") 1488 ip(f"link set dev {nk_guest_b} up", ns=netns) 1489 1490 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1491 netdevnl_ns.queue_create( 1492 { 1493 "ifindex": nk_guest_a_idx, 1494 "type": "rx", 1495 "lease": { 1496 "ifindex": nsim.ifindex, 1497 "queue": {"id": 1, "type": "rx"}, 1498 "netns-id": 0, 1499 }, 1500 } 1501 ) 1502 netdevnl_ns.queue_create( 1503 { 1504 "ifindex": nk_guest_b_idx, 1505 "type": "rx", 1506 "lease": { 1507 "ifindex": nsim.ifindex, 1508 "queue": {"id": 2, "type": "rx"}, 1509 "netns-id": 0, 1510 }, 1511 } 1512 ) 1513 1514 netdevnl = NetdevFamily() 1515 q1 = netdevnl.queue_get( 1516 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1517 ) 1518 q2 = netdevnl.queue_get( 1519 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 1520 ) 1521 ksft_in("lease", q1) 1522 ksft_in("lease", q2) 1523 1524 cmd(f"ip link del dev {nk_host_a}") 1525 1526 q1 = netdevnl.queue_get( 1527 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1528 ) 1529 q2 = netdevnl.queue_get( 1530 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 1531 ) 1532 ksft_not_in("lease", q1) 1533 ksft_in("lease", q2) 1534 1535 1536def test_bind_rx_leased_phys_queue(netns) -> None: 1537 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1538 defer(nsimdev.remove) 1539 nsim = nsimdev.nsims[0] 1540 ip(f"link set dev {nsim.ifname} up") 1541 1542 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1543 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1544 1545 ip(f"link set dev {nk_guest} netns {netns.name}") 1546 ip(f"link set dev {nk_host} up") 1547 ip(f"link set dev {nk_guest} up", ns=netns) 1548 1549 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1550 netdevnl_ns.queue_create( 1551 { 1552 "ifindex": nk_guest_idx, 1553 "type": "rx", 1554 "lease": { 1555 "ifindex": nsim.ifindex, 1556 "queue": {"id": 1, "type": "rx"}, 1557 "netns-id": 0, 1558 }, 1559 } 1560 ) 1561 1562 netdevnl = NetdevFamily() 1563 with ksft_raises(NlError) as e: 1564 netdevnl.bind_rx( 1565 { 1566 "ifindex": nsim.ifindex, 1567 "fd": 0, 1568 "queues": [ 1569 {"id": 0, "type": "rx"}, 1570 {"id": 1, "type": "rx"}, 1571 ], 1572 } 1573 ) 1574 ksft_eq(e.exception.nl_msg.error, -errno.EOPNOTSUPP) 1575 1576 1577def test_resize_phys_shrink_past_leased(netns) -> None: 1578 nsimdev = NetdevSimDev(port_count=1, queue_count=4) 1579 defer(nsimdev.remove) 1580 nsim = nsimdev.nsims[0] 1581 ip(f"link set dev {nsim.ifname} up") 1582 1583 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1584 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1585 1586 ip(f"link set dev {nk_guest} netns {netns.name}") 1587 ip(f"link set dev {nk_host} up") 1588 ip(f"link set dev {nk_guest} up", ns=netns) 1589 1590 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1591 netdevnl_ns.queue_create( 1592 { 1593 "ifindex": nk_guest_idx, 1594 "type": "rx", 1595 "lease": { 1596 "ifindex": nsim.ifindex, 1597 "queue": {"id": 1, "type": "rx"}, 1598 "netns-id": 0, 1599 }, 1600 } 1601 ) 1602 1603 ethnl = EthtoolFamily() 1604 1605 # Shrink past the leased queue — only queue 3 removed, queue 1 untouched 1606 ethnl.channels_set( 1607 {"header": {"dev-index": nsim.ifindex}, "combined-count": 3} 1608 ) 1609 1610 netdevnl = NetdevFamily() 1611 queue_info = netdevnl.queue_get( 1612 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1613 ) 1614 ksft_in("lease", queue_info) 1615 1616 # Shrink further — queue 2 removed, queue 1 still untouched 1617 ethnl.channels_set( 1618 {"header": {"dev-index": nsim.ifindex}, "combined-count": 2} 1619 ) 1620 1621 queue_info = netdevnl.queue_get( 1622 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1623 ) 1624 ksft_in("lease", queue_info) 1625 1626 # Shrink into the leased queue — queue 1 is busy, must fail 1627 with ksft_raises(NlError) as e: 1628 ethnl.channels_set( 1629 {"header": {"dev-index": nsim.ifindex}, "combined-count": 1} 1630 ) 1631 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 1632 1633 1634def test_resize_virt_not_supported(netns) -> None: 1635 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1636 defer(nsimdev.remove) 1637 nsim = nsimdev.nsims[0] 1638 ip(f"link set dev {nsim.ifname} up") 1639 1640 nk_host, nk_host_idx, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1641 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1642 1643 ip(f"link set dev {nk_guest} netns {netns.name}") 1644 ip(f"link set dev {nk_host} up") 1645 ip(f"link set dev {nk_guest} up", ns=netns) 1646 1647 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1648 netdevnl_ns.queue_create( 1649 { 1650 "ifindex": nk_guest_idx, 1651 "type": "rx", 1652 "lease": { 1653 "ifindex": nsim.ifindex, 1654 "queue": {"id": 1, "type": "rx"}, 1655 "netns-id": 0, 1656 }, 1657 } 1658 ) 1659 1660 # Channel resize on the netkit host must fail — not supported 1661 ethnl = EthtoolFamily() 1662 with ksft_raises(NlError) as e: 1663 ethnl.channels_set( 1664 {"header": {"dev-index": nk_host_idx}, "combined-count": 1} 1665 ) 1666 ksft_eq(e.exception.nl_msg.error, -errno.EOPNOTSUPP) 1667 1668 # Lease must be intact 1669 netdevnl = NetdevFamily() 1670 queue_info = netdevnl.queue_get( 1671 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1672 ) 1673 ksft_in("lease", queue_info) 1674 1675 1676def test_lease_devices_down(netns) -> None: 1677 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1678 defer(nsimdev.remove) 1679 nsim = nsimdev.nsims[0] 1680 1681 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1682 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1683 1684 ip(f"link set dev {nk_guest} netns {netns.name}") 1685 1686 # Create lease while both physical and virtual devices are down 1687 src_queue = 1 1688 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1689 result = netdevnl_ns.queue_create( 1690 { 1691 "ifindex": nk_guest_idx, 1692 "type": "rx", 1693 "lease": { 1694 "ifindex": nsim.ifindex, 1695 "queue": {"id": src_queue, "type": "rx"}, 1696 "netns-id": 0, 1697 }, 1698 } 1699 ) 1700 ksft_eq(result["id"], 1) 1701 1702 # Bring devices up before queue_get: netdevsim only instantiates NAPIs in 1703 # ndo_open, and netdev-genl queue_get returns -ENOENT without a NAPI. 1704 ip(f"link set dev {nsim.ifname} up") 1705 ip(f"link set dev {nk_host} up") 1706 ip(f"link set dev {nk_guest} up", ns=netns) 1707 1708 netdevnl = NetdevFamily() 1709 queue_info = netdevnl.queue_get( 1710 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 1711 ) 1712 ksft_in("lease", queue_info) 1713 ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) 1714 1715 1716def test_lease_capacity_exhaustion(netns) -> None: 1717 nsimdev = NetdevSimDev(port_count=1, queue_count=4) 1718 defer(nsimdev.remove) 1719 nsim = nsimdev.nsims[0] 1720 ip(f"link set dev {nsim.ifname} up") 1721 1722 # rxqueues=3 means num_rx_queues=3, real_num_rx_queues starts at 1. 1723 # Can create 2 leased queues (real goes 1->2->3) but not a 3rd (3->4 > 3). 1724 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=3) 1725 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1726 1727 ip(f"link set dev {nk_guest} netns {netns.name}") 1728 ip(f"link set dev {nk_host} up") 1729 ip(f"link set dev {nk_guest} up", ns=netns) 1730 1731 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1732 r1 = netdevnl_ns.queue_create( 1733 { 1734 "ifindex": nk_guest_idx, 1735 "type": "rx", 1736 "lease": { 1737 "ifindex": nsim.ifindex, 1738 "queue": {"id": 1, "type": "rx"}, 1739 "netns-id": 0, 1740 }, 1741 } 1742 ) 1743 ksft_eq(r1["id"], 1) 1744 1745 r2 = netdevnl_ns.queue_create( 1746 { 1747 "ifindex": nk_guest_idx, 1748 "type": "rx", 1749 "lease": { 1750 "ifindex": nsim.ifindex, 1751 "queue": {"id": 2, "type": "rx"}, 1752 "netns-id": 0, 1753 }, 1754 } 1755 ) 1756 ksft_eq(r2["id"], 2) 1757 1758 # Third lease fails — netkit queue capacity exhausted 1759 with ksft_raises(NlError) as e: 1760 netdevnl_ns.queue_create( 1761 { 1762 "ifindex": nk_guest_idx, 1763 "type": "rx", 1764 "lease": { 1765 "ifindex": nsim.ifindex, 1766 "queue": {"id": 3, "type": "rx"}, 1767 "netns-id": 0, 1768 }, 1769 } 1770 ) 1771 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 1772 1773 # Verify the two successful leases are intact 1774 netdevnl = NetdevFamily() 1775 q1 = netdevnl.queue_get( 1776 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1777 ) 1778 q2 = netdevnl.queue_get( 1779 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 1780 ) 1781 ksft_in("lease", q1) 1782 ksft_in("lease", q2) 1783 1784 1785def test_resize_phys_up(netns) -> None: 1786 nsimdev = NetdevSimDev(port_count=1, queue_count=3) 1787 defer(nsimdev.remove) 1788 nsim = nsimdev.nsims[0] 1789 ip(f"link set dev {nsim.ifname} up") 1790 1791 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1792 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1793 1794 ip(f"link set dev {nk_guest} netns {netns.name}") 1795 ip(f"link set dev {nk_host} up") 1796 ip(f"link set dev {nk_guest} up", ns=netns) 1797 1798 # Shrink nsim first so we have room to grow 1799 ethnl = EthtoolFamily() 1800 ethnl.channels_set( 1801 {"header": {"dev-index": nsim.ifindex}, "combined-count": 2} 1802 ) 1803 1804 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1805 netdevnl_ns.queue_create( 1806 { 1807 "ifindex": nk_guest_idx, 1808 "type": "rx", 1809 "lease": { 1810 "ifindex": nsim.ifindex, 1811 "queue": {"id": 1, "type": "rx"}, 1812 "netns-id": 0, 1813 }, 1814 } 1815 ) 1816 1817 # Grow channels — should succeed since leased queue is not removed 1818 ethnl.channels_set( 1819 {"header": {"dev-index": nsim.ifindex}, "combined-count": 3} 1820 ) 1821 1822 netdevnl = NetdevFamily() 1823 queue_info = netdevnl.queue_get( 1824 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1825 ) 1826 ksft_in("lease", queue_info) 1827 1828 # New queue 2 should exist without a lease 1829 queue_info = netdevnl.queue_get( 1830 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 1831 ) 1832 ksft_not_in("lease", queue_info) 1833 1834 1835def test_multi_ns_lease(netns) -> None: 1836 nsimdev = NetdevSimDev(port_count=1, queue_count=3) 1837 defer(nsimdev.remove) 1838 nsim = nsimdev.nsims[0] 1839 ip(f"link set dev {nsim.ifname} up") 1840 1841 ns_b = NetNS() 1842 defer(ns_b.__del__) 1843 ip("netns set init 0", ns=ns_b) 1844 ip("link set lo up", ns=ns_b) 1845 1846 # First netkit pair, guest in netns 1847 nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) 1848 defer(cmd, f"ip link del dev {nk_host_a}", fail=False) 1849 ip(f"link set dev {nk_guest_a} netns {netns.name}") 1850 ip(f"link set dev {nk_host_a} up") 1851 ip(f"link set dev {nk_guest_a} up", ns=netns) 1852 1853 # Second netkit pair, guest in ns_b 1854 nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) 1855 defer(cmd, f"ip link del dev {nk_host_b}", fail=False) 1856 ip(f"link set dev {nk_guest_b} netns {ns_b.name}") 1857 ip(f"link set dev {nk_host_b} up") 1858 ip(f"link set dev {nk_guest_b} up", ns=ns_b) 1859 1860 # Lease from netns 1861 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1862 result = netdevnl_ns.queue_create( 1863 { 1864 "ifindex": nk_guest_a_idx, 1865 "type": "rx", 1866 "lease": { 1867 "ifindex": nsim.ifindex, 1868 "queue": {"id": 1, "type": "rx"}, 1869 "netns-id": 0, 1870 }, 1871 } 1872 ) 1873 ksft_eq(result["id"], 1) 1874 1875 # Lease from ns_b (different namespace, same physical device) 1876 with NetNSEnter(str(ns_b)), NetdevFamily() as netdevnl_ns: 1877 result = netdevnl_ns.queue_create( 1878 { 1879 "ifindex": nk_guest_b_idx, 1880 "type": "rx", 1881 "lease": { 1882 "ifindex": nsim.ifindex, 1883 "queue": {"id": 2, "type": "rx"}, 1884 "netns-id": 0, 1885 }, 1886 } 1887 ) 1888 ksft_eq(result["id"], 1) 1889 1890 # Verify both leases from the physical side 1891 netdevnl = NetdevFamily() 1892 q1 = netdevnl.queue_get( 1893 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1894 ) 1895 q2 = netdevnl.queue_get( 1896 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 1897 ) 1898 ksft_in("lease", q1) 1899 ksft_in("lease", q2) 1900 ksft_eq(q1["lease"]["ifindex"], nk_guest_a_idx) 1901 ksft_eq(q2["lease"]["ifindex"], nk_guest_b_idx) 1902 1903 1904def test_multi_ns_delete_one(netns) -> None: 1905 nsimdev = NetdevSimDev(port_count=1, queue_count=3) 1906 defer(nsimdev.remove) 1907 nsim = nsimdev.nsims[0] 1908 ip(f"link set dev {nsim.ifname} up") 1909 1910 ns_b = NetNS() 1911 ip("netns set init 0", ns=ns_b) 1912 ip("link set lo up", ns=ns_b) 1913 1914 # First netkit pair, guest in netns (ns_a) 1915 nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) 1916 defer(cmd, f"ip link del dev {nk_host_a}", fail=False) 1917 ip(f"link set dev {nk_guest_a} netns {netns.name}") 1918 ip(f"link set dev {nk_host_a} up") 1919 ip(f"link set dev {nk_guest_a} up", ns=netns) 1920 1921 # Second netkit pair, guest in ns_b 1922 nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) 1923 defer(cmd, f"ip link del dev {nk_host_b}", fail=False) 1924 1925 ip(f"link set dev {nk_guest_b} netns {ns_b.name}") 1926 ip(f"link set dev {nk_host_b} up") 1927 ip(f"link set dev {nk_guest_b} up", ns=ns_b) 1928 1929 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 1930 netdevnl_ns.queue_create( 1931 { 1932 "ifindex": nk_guest_a_idx, 1933 "type": "rx", 1934 "lease": { 1935 "ifindex": nsim.ifindex, 1936 "queue": {"id": 1, "type": "rx"}, 1937 "netns-id": 0, 1938 }, 1939 } 1940 ) 1941 1942 with NetNSEnter(str(ns_b)), NetdevFamily() as netdevnl_ns: 1943 netdevnl_ns.queue_create( 1944 { 1945 "ifindex": nk_guest_b_idx, 1946 "type": "rx", 1947 "lease": { 1948 "ifindex": nsim.ifindex, 1949 "queue": {"id": 2, "type": "rx"}, 1950 "netns-id": 0, 1951 }, 1952 } 1953 ) 1954 1955 netdevnl = NetdevFamily() 1956 q1 = netdevnl.queue_get( 1957 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1958 ) 1959 q2 = netdevnl.queue_get( 1960 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 1961 ) 1962 ksft_in("lease", q1) 1963 ksft_in("lease", q2) 1964 1965 # Delete ns_b — destroys nk_guest_b, triggers unlease of queue 2 1966 del ns_b 1967 wait_until(lambda: "lease" not in netdevnl.queue_get( 1968 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"})) 1969 1970 # ns_a's lease on queue 1 must survive 1971 q1 = netdevnl.queue_get( 1972 {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} 1973 ) 1974 ksft_in("lease", q1) 1975 ksft_eq(q1["lease"]["ifindex"], nk_guest_a_idx) 1976 1977 # ns_b's lease on queue 2 must be gone 1978 q2 = netdevnl.queue_get( 1979 {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} 1980 ) 1981 ksft_not_in("lease", q2) 1982 1983 # nk_host_b should be gone too (phys removal cascades to netkit pair) 1984 ret = cmd(f"ip link show dev {nk_host_b}", fail=False) 1985 ksft_ne(ret.ret, 0) 1986 1987 1988def test_move_phys_netns(netns) -> None: 1989 nsimdev = NetdevSimDev(port_count=1, queue_count=2) 1990 defer(nsimdev.remove) 1991 nsim = nsimdev.nsims[0] 1992 ip(f"link set dev {nsim.ifname} up") 1993 1994 nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) 1995 defer(cmd, f"ip link del dev {nk_host}", fail=False) 1996 1997 ip(f"link set dev {nk_guest} netns {netns.name}") 1998 ip(f"link set dev {nk_host} up") 1999 ip(f"link set dev {nk_guest} up", ns=netns) 2000 2001 src_queue = 1 2002 with NetNSEnter(str(netns)), NetdevFamily() as netdevnl_ns: 2003 nk_queue_id = netdevnl_ns.queue_create( 2004 { 2005 "ifindex": nk_guest_idx, 2006 "type": "rx", 2007 "lease": { 2008 "ifindex": nsim.ifindex, 2009 "queue": {"id": src_queue, "type": "rx"}, 2010 "netns-id": 0, 2011 }, 2012 } 2013 )["id"] 2014 2015 netdevnl = NetdevFamily() 2016 queue_info = netdevnl.queue_get( 2017 {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} 2018 ) 2019 ksft_in("lease", queue_info) 2020 2021 # Move the physical device to a new namespace. Move it back to init_net 2022 # on cleanup before the other defers fire (new_ns deletion, nsimdev.remove) 2023 # so nsim lives in a stable namespace when they run. 2024 new_ns = NetNS() 2025 defer(new_ns.__del__) 2026 ip(f"link set dev {nsim.ifname} netns {new_ns.name}") 2027 defer(ip, f"link set dev {nsim.ifname} netns init", ns=new_ns) 2028 2029 # Physical device is now in new_ns — find its ifindex there 2030 all_links = ip("-d link show", json=True, ns=new_ns) 2031 nsim_in_new = [lnk for lnk in all_links if lnk.get("ifname") == nsim.ifname] 2032 new_ifindex = nsim_in_new[0]["ifindex"] 2033 2034 # Moving a device across netns brings it admin-down; bring it back up so 2035 # netdevsim re-creates the NAPI (netdev-genl queue_get needs it). 2036 ip(f"link set dev {nsim.ifname} up", ns=new_ns) 2037 2038 # Verify lease survived the namespace move 2039 with NetNSEnter(str(new_ns)), NetdevFamily() as netdevnl_ns: 2040 queue_info = netdevnl_ns.queue_get( 2041 {"ifindex": new_ifindex, "id": src_queue, "type": "rx"} 2042 ) 2043 ksft_in("lease", queue_info) 2044 ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) 2045 2046 2047def main() -> None: 2048 netns = NetNS() 2049 cmd("ip netns attach init 1") 2050 ip("netns set init 0", ns=netns) 2051 ip("link set lo up", ns=netns) 2052 2053 ksft_run( 2054 [ 2055 test_remove_phys, 2056 test_double_lease, 2057 test_virtual_lessor, 2058 test_phys_lessee, 2059 test_different_lessors, 2060 test_queue_out_of_range, 2061 test_resize_leased, 2062 test_self_lease, 2063 test_create_tx_type, 2064 test_create_primary, 2065 test_create_limit, 2066 test_link_flap_phys, 2067 test_queue_get_virtual, 2068 test_remove_virt_first, 2069 test_multiple_leases, 2070 test_lease_queue_tx_type, 2071 test_invalid_netns, 2072 test_invalid_phys_ifindex, 2073 test_multi_netkit_remove_phys, 2074 test_single_remove_phys, 2075 test_link_flap_virt, 2076 test_phys_queue_no_lease, 2077 test_same_ns_lease, 2078 test_resize_after_unlease, 2079 test_lease_queue_zero, 2080 test_release_and_reuse, 2081 test_veth_queue_create, 2082 test_two_netkits_same_queue, 2083 test_l3_mode_lease, 2084 test_single_double_lease, 2085 test_single_different_lessors, 2086 test_cross_ns_netns_id, 2087 test_delete_guest_netns, 2088 test_move_guest_netns, 2089 test_resize_phys_no_reduction, 2090 test_delete_one_netkit_of_two, 2091 test_bind_rx_leased_phys_queue, 2092 test_resize_phys_shrink_past_leased, 2093 test_resize_virt_not_supported, 2094 test_lease_devices_down, 2095 test_lease_capacity_exhaustion, 2096 test_resize_phys_up, 2097 test_multi_ns_lease, 2098 test_multi_ns_delete_one, 2099 test_move_phys_netns, 2100 ], 2101 args=(netns,), 2102 ) 2103 2104 cmd("ip netns del init", fail=False) 2105 ksft_exit() 2106 2107 2108if __name__ == "__main__": 2109 main()