linux/tools/testing/selftests/bpf/prog_tests/flow_dissector_reattach.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Tests for attaching, detaching, and replacing flow_dissector BPF program.
   4 */
   5
   6#define _GNU_SOURCE
   7#include <errno.h>
   8#include <fcntl.h>
   9#include <sched.h>
  10#include <stdbool.h>
  11#include <sys/stat.h>
  12#include <unistd.h>
  13
  14#include <linux/bpf.h>
  15#include <bpf/bpf.h>
  16
  17#include "test_progs.h"
  18
  19static int init_net = -1;
  20
  21static __u32 query_attached_prog_id(int netns)
  22{
  23        __u32 prog_ids[1] = {};
  24        __u32 prog_cnt = ARRAY_SIZE(prog_ids);
  25        int err;
  26
  27        err = bpf_prog_query(netns, BPF_FLOW_DISSECTOR, 0, NULL,
  28                             prog_ids, &prog_cnt);
  29        if (CHECK_FAIL(err)) {
  30                perror("bpf_prog_query");
  31                return 0;
  32        }
  33
  34        return prog_cnt == 1 ? prog_ids[0] : 0;
  35}
  36
  37static bool prog_is_attached(int netns)
  38{
  39        return query_attached_prog_id(netns) > 0;
  40}
  41
  42static int load_prog(enum bpf_prog_type type)
  43{
  44        struct bpf_insn prog[] = {
  45                BPF_MOV64_IMM(BPF_REG_0, BPF_OK),
  46                BPF_EXIT_INSN(),
  47        };
  48        int fd;
  49
  50        fd = bpf_load_program(type, prog, ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
  51        if (CHECK_FAIL(fd < 0))
  52                perror("bpf_load_program");
  53
  54        return fd;
  55}
  56
  57static __u32 query_prog_id(int prog)
  58{
  59        struct bpf_prog_info info = {};
  60        __u32 info_len = sizeof(info);
  61        int err;
  62
  63        err = bpf_obj_get_info_by_fd(prog, &info, &info_len);
  64        if (CHECK_FAIL(err || info_len != sizeof(info))) {
  65                perror("bpf_obj_get_info_by_fd");
  66                return 0;
  67        }
  68
  69        return info.id;
  70}
  71
  72static int unshare_net(int old_net)
  73{
  74        int err, new_net;
  75
  76        err = unshare(CLONE_NEWNET);
  77        if (CHECK_FAIL(err)) {
  78                perror("unshare(CLONE_NEWNET)");
  79                return -1;
  80        }
  81        new_net = open("/proc/self/ns/net", O_RDONLY);
  82        if (CHECK_FAIL(new_net < 0)) {
  83                perror("open(/proc/self/ns/net)");
  84                setns(old_net, CLONE_NEWNET);
  85                return -1;
  86        }
  87        return new_net;
  88}
  89
  90static void test_prog_attach_prog_attach(int netns, int prog1, int prog2)
  91{
  92        int err;
  93
  94        err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
  95        if (CHECK_FAIL(err)) {
  96                perror("bpf_prog_attach(prog1)");
  97                return;
  98        }
  99        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 100
 101        /* Expect success when attaching a different program */
 102        err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
 103        if (CHECK_FAIL(err)) {
 104                perror("bpf_prog_attach(prog2) #1");
 105                goto out_detach;
 106        }
 107        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
 108
 109        /* Expect failure when attaching the same program twice */
 110        err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
 111        if (CHECK_FAIL(!err || errno != EINVAL))
 112                perror("bpf_prog_attach(prog2) #2");
 113        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
 114
 115out_detach:
 116        err = bpf_prog_detach2(prog2, 0, BPF_FLOW_DISSECTOR);
 117        if (CHECK_FAIL(err))
 118                perror("bpf_prog_detach");
 119        CHECK_FAIL(prog_is_attached(netns));
 120}
 121
 122static void test_link_create_link_create(int netns, int prog1, int prog2)
 123{
 124        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
 125        int link1, link2;
 126
 127        link1 = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
 128        if (CHECK_FAIL(link < 0)) {
 129                perror("bpf_link_create(prog1)");
 130                return;
 131        }
 132        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 133
 134        /* Expect failure creating link when another link exists */
 135        errno = 0;
 136        link2 = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
 137        if (CHECK_FAIL(link2 >= 0 || errno != E2BIG))
 138                perror("bpf_prog_attach(prog2) expected E2BIG");
 139        if (link2 >= 0)
 140                close(link2);
 141        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 142
 143        close(link1);
 144        CHECK_FAIL(prog_is_attached(netns));
 145}
 146
 147static void test_prog_attach_link_create(int netns, int prog1, int prog2)
 148{
 149        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
 150        int err, link;
 151
 152        err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
 153        if (CHECK_FAIL(err)) {
 154                perror("bpf_prog_attach(prog1)");
 155                return;
 156        }
 157        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 158
 159        /* Expect failure creating link when prog attached */
 160        errno = 0;
 161        link = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
 162        if (CHECK_FAIL(link >= 0 || errno != EEXIST))
 163                perror("bpf_link_create(prog2) expected EEXIST");
 164        if (link >= 0)
 165                close(link);
 166        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 167
 168        err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
 169        if (CHECK_FAIL(err))
 170                perror("bpf_prog_detach");
 171        CHECK_FAIL(prog_is_attached(netns));
 172}
 173
 174static void test_link_create_prog_attach(int netns, int prog1, int prog2)
 175{
 176        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
 177        int err, link;
 178
 179        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
 180        if (CHECK_FAIL(link < 0)) {
 181                perror("bpf_link_create(prog1)");
 182                return;
 183        }
 184        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 185
 186        /* Expect failure attaching prog when link exists */
 187        errno = 0;
 188        err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
 189        if (CHECK_FAIL(!err || errno != EEXIST))
 190                perror("bpf_prog_attach(prog2) expected EEXIST");
 191        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 192
 193        close(link);
 194        CHECK_FAIL(prog_is_attached(netns));
 195}
 196
 197static void test_link_create_prog_detach(int netns, int prog1, int prog2)
 198{
 199        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
 200        int err, link;
 201
 202        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
 203        if (CHECK_FAIL(link < 0)) {
 204                perror("bpf_link_create(prog1)");
 205                return;
 206        }
 207        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 208
 209        /* Expect failure detaching prog when link exists */
 210        errno = 0;
 211        err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
 212        if (CHECK_FAIL(!err || errno != EINVAL))
 213                perror("bpf_prog_detach expected EINVAL");
 214        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 215
 216        close(link);
 217        CHECK_FAIL(prog_is_attached(netns));
 218}
 219
 220static void test_prog_attach_detach_query(int netns, int prog1, int prog2)
 221{
 222        int err;
 223
 224        err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
 225        if (CHECK_FAIL(err)) {
 226                perror("bpf_prog_attach(prog1)");
 227                return;
 228        }
 229        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 230
 231        err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
 232        if (CHECK_FAIL(err)) {
 233                perror("bpf_prog_detach");
 234                return;
 235        }
 236
 237        /* Expect no prog attached after successful detach */
 238        CHECK_FAIL(prog_is_attached(netns));
 239}
 240
 241static void test_link_create_close_query(int netns, int prog1, int prog2)
 242{
 243        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
 244        int link;
 245
 246        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
 247        if (CHECK_FAIL(link < 0)) {
 248                perror("bpf_link_create(prog1)");
 249                return;
 250        }
 251        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 252
 253        close(link);
 254        /* Expect no prog attached after closing last link FD */
 255        CHECK_FAIL(prog_is_attached(netns));
 256}
 257
 258static void test_link_update_no_old_prog(int netns, int prog1, int prog2)
 259{
 260        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
 261        DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
 262        int err, link;
 263
 264        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
 265        if (CHECK_FAIL(link < 0)) {
 266                perror("bpf_link_create(prog1)");
 267                return;
 268        }
 269        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 270
 271        /* Expect success replacing the prog when old prog not specified */
 272        update_opts.flags = 0;
 273        update_opts.old_prog_fd = 0;
 274        err = bpf_link_update(link, prog2, &update_opts);
 275        if (CHECK_FAIL(err))
 276                perror("bpf_link_update");
 277        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
 278
 279        close(link);
 280        CHECK_FAIL(prog_is_attached(netns));
 281}
 282
 283static void test_link_update_replace_old_prog(int netns, int prog1, int prog2)
 284{
 285        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
 286        DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
 287        int err, link;
 288
 289        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
 290        if (CHECK_FAIL(link < 0)) {
 291                perror("bpf_link_create(prog1)");
 292                return;
 293        }
 294        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 295
 296        /* Expect success F_REPLACE and old prog specified to succeed */
 297        update_opts.flags = BPF_F_REPLACE;
 298        update_opts.old_prog_fd = prog1;
 299        err = bpf_link_update(link, prog2, &update_opts);
 300        if (CHECK_FAIL(err))
 301                perror("bpf_link_update");
 302        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
 303
 304        close(link);
 305        CHECK_FAIL(prog_is_attached(netns));
 306}
 307
 308static void test_link_update_same_prog(int netns, int prog1, int prog2)
 309{
 310        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
 311        DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
 312        int err, link;
 313
 314        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
 315        if (CHECK_FAIL(link < 0)) {
 316                perror("bpf_link_create(prog1)");
 317                return;
 318        }
 319        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 320
 321        /* Expect success updating the prog with the same one */
 322        update_opts.flags = 0;
 323        update_opts.old_prog_fd = 0;
 324        err = bpf_link_update(link, prog1, &update_opts);
 325        if (CHECK_FAIL(err))
 326                perror("bpf_link_update");
 327        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 328
 329        close(link);
 330        CHECK_FAIL(prog_is_attached(netns));
 331}
 332
 333static void test_link_update_invalid_opts(int netns, int prog1, int prog2)
 334{
 335        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
 336        DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
 337        int err, link;
 338
 339        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
 340        if (CHECK_FAIL(link < 0)) {
 341                perror("bpf_link_create(prog1)");
 342                return;
 343        }
 344        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 345
 346        /* Expect update to fail w/ old prog FD but w/o F_REPLACE*/
 347        errno = 0;
 348        update_opts.flags = 0;
 349        update_opts.old_prog_fd = prog1;
 350        err = bpf_link_update(link, prog2, &update_opts);
 351        if (CHECK_FAIL(!err || errno != EINVAL)) {
 352                perror("bpf_link_update expected EINVAL");
 353                goto out_close;
 354        }
 355        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 356
 357        /* Expect update to fail on old prog FD mismatch */
 358        errno = 0;
 359        update_opts.flags = BPF_F_REPLACE;
 360        update_opts.old_prog_fd = prog2;
 361        err = bpf_link_update(link, prog2, &update_opts);
 362        if (CHECK_FAIL(!err || errno != EPERM)) {
 363                perror("bpf_link_update expected EPERM");
 364                goto out_close;
 365        }
 366        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 367
 368        /* Expect update to fail for invalid old prog FD */
 369        errno = 0;
 370        update_opts.flags = BPF_F_REPLACE;
 371        update_opts.old_prog_fd = -1;
 372        err = bpf_link_update(link, prog2, &update_opts);
 373        if (CHECK_FAIL(!err || errno != EBADF)) {
 374                perror("bpf_link_update expected EBADF");
 375                goto out_close;
 376        }
 377        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 378
 379        /* Expect update to fail with invalid flags */
 380        errno = 0;
 381        update_opts.flags = BPF_F_ALLOW_MULTI;
 382        update_opts.old_prog_fd = 0;
 383        err = bpf_link_update(link, prog2, &update_opts);
 384        if (CHECK_FAIL(!err || errno != EINVAL))
 385                perror("bpf_link_update expected EINVAL");
 386        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 387
 388out_close:
 389        close(link);
 390        CHECK_FAIL(prog_is_attached(netns));
 391}
 392
 393static void test_link_update_invalid_prog(int netns, int prog1, int prog2)
 394{
 395        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
 396        DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
 397        int err, link, prog3;
 398
 399        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
 400        if (CHECK_FAIL(link < 0)) {
 401                perror("bpf_link_create(prog1)");
 402                return;
 403        }
 404        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 405
 406        /* Expect failure when new prog FD is not valid */
 407        errno = 0;
 408        update_opts.flags = 0;
 409        update_opts.old_prog_fd = 0;
 410        err = bpf_link_update(link, -1, &update_opts);
 411        if (CHECK_FAIL(!err || errno != EBADF)) {
 412                perror("bpf_link_update expected EINVAL");
 413                goto out_close_link;
 414        }
 415        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 416
 417        prog3 = load_prog(BPF_PROG_TYPE_SOCKET_FILTER);
 418        if (prog3 < 0)
 419                goto out_close_link;
 420
 421        /* Expect failure when new prog FD type doesn't match */
 422        errno = 0;
 423        update_opts.flags = 0;
 424        update_opts.old_prog_fd = 0;
 425        err = bpf_link_update(link, prog3, &update_opts);
 426        if (CHECK_FAIL(!err || errno != EINVAL))
 427                perror("bpf_link_update expected EINVAL");
 428        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 429
 430        close(prog3);
 431out_close_link:
 432        close(link);
 433        CHECK_FAIL(prog_is_attached(netns));
 434}
 435
 436static void test_link_update_netns_gone(int netns, int prog1, int prog2)
 437{
 438        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
 439        DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
 440        int err, link, old_net;
 441
 442        old_net = netns;
 443        netns = unshare_net(old_net);
 444        if (netns < 0)
 445                return;
 446
 447        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
 448        if (CHECK_FAIL(link < 0)) {
 449                perror("bpf_link_create(prog1)");
 450                return;
 451        }
 452        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 453
 454        close(netns);
 455        err = setns(old_net, CLONE_NEWNET);
 456        if (CHECK_FAIL(err)) {
 457                perror("setns(CLONE_NEWNET)");
 458                close(link);
 459                return;
 460        }
 461
 462        /* Expect failure when netns destroyed */
 463        errno = 0;
 464        update_opts.flags = 0;
 465        update_opts.old_prog_fd = 0;
 466        err = bpf_link_update(link, prog2, &update_opts);
 467        if (CHECK_FAIL(!err || errno != ENOLINK))
 468                perror("bpf_link_update");
 469
 470        close(link);
 471}
 472
 473static void test_link_get_info(int netns, int prog1, int prog2)
 474{
 475        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
 476        DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
 477        struct bpf_link_info info = {};
 478        struct stat netns_stat = {};
 479        __u32 info_len, link_id;
 480        int err, link, old_net;
 481
 482        old_net = netns;
 483        netns = unshare_net(old_net);
 484        if (netns < 0)
 485                return;
 486
 487        err = fstat(netns, &netns_stat);
 488        if (CHECK_FAIL(err)) {
 489                perror("stat(netns)");
 490                goto out_resetns;
 491        }
 492
 493        link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
 494        if (CHECK_FAIL(link < 0)) {
 495                perror("bpf_link_create(prog1)");
 496                goto out_resetns;
 497        }
 498
 499        info_len = sizeof(info);
 500        err = bpf_obj_get_info_by_fd(link, &info, &info_len);
 501        if (CHECK_FAIL(err)) {
 502                perror("bpf_obj_get_info");
 503                goto out_unlink;
 504        }
 505        CHECK_FAIL(info_len != sizeof(info));
 506
 507        /* Expect link info to be sane and match prog and netns details */
 508        CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
 509        CHECK_FAIL(info.id == 0);
 510        CHECK_FAIL(info.prog_id != query_prog_id(prog1));
 511        CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
 512        CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
 513
 514        update_opts.flags = 0;
 515        update_opts.old_prog_fd = 0;
 516        err = bpf_link_update(link, prog2, &update_opts);
 517        if (CHECK_FAIL(err)) {
 518                perror("bpf_link_update(prog2)");
 519                goto out_unlink;
 520        }
 521
 522        link_id = info.id;
 523        info_len = sizeof(info);
 524        err = bpf_obj_get_info_by_fd(link, &info, &info_len);
 525        if (CHECK_FAIL(err)) {
 526                perror("bpf_obj_get_info");
 527                goto out_unlink;
 528        }
 529        CHECK_FAIL(info_len != sizeof(info));
 530
 531        /* Expect no info change after update except in prog id */
 532        CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
 533        CHECK_FAIL(info.id != link_id);
 534        CHECK_FAIL(info.prog_id != query_prog_id(prog2));
 535        CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
 536        CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
 537
 538        /* Leave netns link is attached to and close last FD to it */
 539        err = setns(old_net, CLONE_NEWNET);
 540        if (CHECK_FAIL(err)) {
 541                perror("setns(NEWNET)");
 542                goto out_unlink;
 543        }
 544        close(netns);
 545        old_net = -1;
 546        netns = -1;
 547
 548        info_len = sizeof(info);
 549        err = bpf_obj_get_info_by_fd(link, &info, &info_len);
 550        if (CHECK_FAIL(err)) {
 551                perror("bpf_obj_get_info");
 552                goto out_unlink;
 553        }
 554        CHECK_FAIL(info_len != sizeof(info));
 555
 556        /* Expect netns_ino to change to 0 */
 557        CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
 558        CHECK_FAIL(info.id != link_id);
 559        CHECK_FAIL(info.prog_id != query_prog_id(prog2));
 560        CHECK_FAIL(info.netns.netns_ino != 0);
 561        CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
 562
 563out_unlink:
 564        close(link);
 565out_resetns:
 566        if (old_net != -1)
 567                setns(old_net, CLONE_NEWNET);
 568        if (netns != -1)
 569                close(netns);
 570}
 571
 572static void run_tests(int netns)
 573{
 574        struct test {
 575                const char *test_name;
 576                void (*test_func)(int netns, int prog1, int prog2);
 577        } tests[] = {
 578                { "prog attach, prog attach",
 579                  test_prog_attach_prog_attach },
 580                { "link create, link create",
 581                  test_link_create_link_create },
 582                { "prog attach, link create",
 583                  test_prog_attach_link_create },
 584                { "link create, prog attach",
 585                  test_link_create_prog_attach },
 586                { "link create, prog detach",
 587                  test_link_create_prog_detach },
 588                { "prog attach, detach, query",
 589                  test_prog_attach_detach_query },
 590                { "link create, close, query",
 591                  test_link_create_close_query },
 592                { "link update no old prog",
 593                  test_link_update_no_old_prog },
 594                { "link update with replace old prog",
 595                  test_link_update_replace_old_prog },
 596                { "link update with same prog",
 597                  test_link_update_same_prog },
 598                { "link update invalid opts",
 599                  test_link_update_invalid_opts },
 600                { "link update invalid prog",
 601                  test_link_update_invalid_prog },
 602                { "link update netns gone",
 603                  test_link_update_netns_gone },
 604                { "link get info",
 605                  test_link_get_info },
 606        };
 607        int i, progs[2] = { -1, -1 };
 608        char test_name[80];
 609
 610        for (i = 0; i < ARRAY_SIZE(progs); i++) {
 611                progs[i] = load_prog(BPF_PROG_TYPE_FLOW_DISSECTOR);
 612                if (progs[i] < 0)
 613                        goto out_close;
 614        }
 615
 616        for (i = 0; i < ARRAY_SIZE(tests); i++) {
 617                snprintf(test_name, sizeof(test_name),
 618                         "flow dissector %s%s",
 619                         tests[i].test_name,
 620                         netns == init_net ? " (init_net)" : "");
 621                if (test__start_subtest(test_name))
 622                        tests[i].test_func(netns, progs[0], progs[1]);
 623        }
 624out_close:
 625        for (i = 0; i < ARRAY_SIZE(progs); i++) {
 626                if (progs[i] >= 0)
 627                        CHECK_FAIL(close(progs[i]));
 628        }
 629}
 630
 631void test_flow_dissector_reattach(void)
 632{
 633        int err, new_net, saved_net;
 634
 635        saved_net = open("/proc/self/ns/net", O_RDONLY);
 636        if (CHECK_FAIL(saved_net < 0)) {
 637                perror("open(/proc/self/ns/net");
 638                return;
 639        }
 640
 641        init_net = open("/proc/1/ns/net", O_RDONLY);
 642        if (CHECK_FAIL(init_net < 0)) {
 643                perror("open(/proc/1/ns/net)");
 644                goto out_close;
 645        }
 646
 647        err = setns(init_net, CLONE_NEWNET);
 648        if (CHECK_FAIL(err)) {
 649                perror("setns(/proc/1/ns/net)");
 650                goto out_close;
 651        }
 652
 653        if (prog_is_attached(init_net)) {
 654                test__skip();
 655                printf("Can't test with flow dissector attached to init_net\n");
 656                goto out_setns;
 657        }
 658
 659        /* First run tests in root network namespace */
 660        run_tests(init_net);
 661
 662        /* Then repeat tests in a non-root namespace */
 663        new_net = unshare_net(init_net);
 664        if (new_net < 0)
 665                goto out_setns;
 666        run_tests(new_net);
 667        close(new_net);
 668
 669out_setns:
 670        /* Move back to netns we started in. */
 671        err = setns(saved_net, CLONE_NEWNET);
 672        if (CHECK_FAIL(err))
 673                perror("setns(/proc/self/ns/net)");
 674
 675out_close:
 676        close(init_net);
 677        close(saved_net);
 678}
 679