153 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2020 Facebook */3#include <uapi/linux/if_link.h>4#include <test_progs.h>5#include "test_xdp_link.skel.h"6 7#define IFINDEX_LO 18 9void serial_test_xdp_link(void)10{11 struct test_xdp_link *skel1 = NULL, *skel2 = NULL;12 __u32 id1, id2, id0 = 0, prog_fd1, prog_fd2;13 LIBBPF_OPTS(bpf_xdp_attach_opts, opts);14 struct bpf_link_info link_info;15 struct bpf_prog_info prog_info;16 struct bpf_link *link;17 int err;18 __u32 link_info_len = sizeof(link_info);19 __u32 prog_info_len = sizeof(prog_info);20 21 skel1 = test_xdp_link__open_and_load();22 if (!ASSERT_OK_PTR(skel1, "skel_load"))23 goto cleanup;24 prog_fd1 = bpf_program__fd(skel1->progs.xdp_handler);25 26 skel2 = test_xdp_link__open_and_load();27 if (!ASSERT_OK_PTR(skel2, "skel_load"))28 goto cleanup;29 prog_fd2 = bpf_program__fd(skel2->progs.xdp_handler);30 31 memset(&prog_info, 0, sizeof(prog_info));32 err = bpf_prog_get_info_by_fd(prog_fd1, &prog_info, &prog_info_len);33 if (!ASSERT_OK(err, "fd_info1"))34 goto cleanup;35 id1 = prog_info.id;36 37 memset(&prog_info, 0, sizeof(prog_info));38 err = bpf_prog_get_info_by_fd(prog_fd2, &prog_info, &prog_info_len);39 if (!ASSERT_OK(err, "fd_info2"))40 goto cleanup;41 id2 = prog_info.id;42 43 /* set initial prog attachment */44 err = bpf_xdp_attach(IFINDEX_LO, prog_fd1, XDP_FLAGS_REPLACE, &opts);45 if (!ASSERT_OK(err, "fd_attach"))46 goto cleanup;47 48 /* validate prog ID */49 err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);50 if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))51 goto cleanup;52 53 /* BPF link is not allowed to replace prog attachment */54 link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);55 if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {56 bpf_link__destroy(link);57 /* best-effort detach prog */58 opts.old_prog_fd = prog_fd1;59 bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);60 goto cleanup;61 }62 63 /* detach BPF program */64 opts.old_prog_fd = prog_fd1;65 err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);66 if (!ASSERT_OK(err, "prog_detach"))67 goto cleanup;68 69 /* now BPF link should attach successfully */70 link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);71 if (!ASSERT_OK_PTR(link, "link_attach"))72 goto cleanup;73 skel1->links.xdp_handler = link;74 75 /* validate prog ID */76 err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);77 if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))78 goto cleanup;79 80 /* BPF prog attach is not allowed to replace BPF link */81 opts.old_prog_fd = prog_fd1;82 err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, XDP_FLAGS_REPLACE, &opts);83 if (!ASSERT_ERR(err, "prog_attach_fail"))84 goto cleanup;85 86 /* Can't force-update when BPF link is active */87 err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, 0, NULL);88 if (!ASSERT_ERR(err, "prog_update_fail"))89 goto cleanup;90 91 /* Can't force-detach when BPF link is active */92 err = bpf_xdp_detach(IFINDEX_LO, 0, NULL);93 if (!ASSERT_ERR(err, "prog_detach_fail"))94 goto cleanup;95 96 /* BPF link is not allowed to replace another BPF link */97 link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);98 if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {99 bpf_link__destroy(link);100 goto cleanup;101 }102 103 bpf_link__destroy(skel1->links.xdp_handler);104 skel1->links.xdp_handler = NULL;105 106 /* new link attach should succeed */107 link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);108 if (!ASSERT_OK_PTR(link, "link_attach"))109 goto cleanup;110 skel2->links.xdp_handler = link;111 112 err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);113 if (!ASSERT_OK(err, "id2_check_err") || !ASSERT_EQ(id0, id2, "id2_check_val"))114 goto cleanup;115 116 /* updating program under active BPF link works as expected */117 err = bpf_link__update_program(link, skel1->progs.xdp_handler);118 if (!ASSERT_OK(err, "link_upd"))119 goto cleanup;120 121 memset(&link_info, 0, sizeof(link_info));122 err = bpf_link_get_info_by_fd(bpf_link__fd(link),123 &link_info, &link_info_len);124 if (!ASSERT_OK(err, "link_info"))125 goto cleanup;126 127 ASSERT_EQ(link_info.type, BPF_LINK_TYPE_XDP, "link_type");128 ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");129 ASSERT_EQ(link_info.xdp.ifindex, IFINDEX_LO, "link_ifindex");130 131 /* updating program under active BPF link with different type fails */132 err = bpf_link__update_program(link, skel1->progs.tc_handler);133 if (!ASSERT_ERR(err, "link_upd_invalid"))134 goto cleanup;135 136 err = bpf_link__detach(link);137 if (!ASSERT_OK(err, "link_detach"))138 goto cleanup;139 140 memset(&link_info, 0, sizeof(link_info));141 err = bpf_link_get_info_by_fd(bpf_link__fd(link),142 &link_info, &link_info_len);143 144 ASSERT_OK(err, "link_info");145 ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");146 /* ifindex should be zeroed out */147 ASSERT_EQ(link_info.xdp.ifindex, 0, "link_ifindex");148 149cleanup:150 test_xdp_link__destroy(skel1);151 test_xdp_link__destroy(skel2);152}153