Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2020 Facebook */
0003 #include <uapi/linux/if_link.h>
0004 #include <test_progs.h>
0005 #include "test_xdp_link.skel.h"
0006 
0007 #define IFINDEX_LO 1
0008 
0009 void serial_test_xdp_link(void)
0010 {
0011     struct test_xdp_link *skel1 = NULL, *skel2 = NULL;
0012     __u32 id1, id2, id0 = 0, prog_fd1, prog_fd2;
0013     LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
0014     struct bpf_link_info link_info;
0015     struct bpf_prog_info prog_info;
0016     struct bpf_link *link;
0017     int err;
0018     __u32 link_info_len = sizeof(link_info);
0019     __u32 prog_info_len = sizeof(prog_info);
0020 
0021     skel1 = test_xdp_link__open_and_load();
0022     if (!ASSERT_OK_PTR(skel1, "skel_load"))
0023         goto cleanup;
0024     prog_fd1 = bpf_program__fd(skel1->progs.xdp_handler);
0025 
0026     skel2 = test_xdp_link__open_and_load();
0027     if (!ASSERT_OK_PTR(skel2, "skel_load"))
0028         goto cleanup;
0029     prog_fd2 = bpf_program__fd(skel2->progs.xdp_handler);
0030 
0031     memset(&prog_info, 0, sizeof(prog_info));
0032     err = bpf_obj_get_info_by_fd(prog_fd1, &prog_info, &prog_info_len);
0033     if (!ASSERT_OK(err, "fd_info1"))
0034         goto cleanup;
0035     id1 = prog_info.id;
0036 
0037     memset(&prog_info, 0, sizeof(prog_info));
0038     err = bpf_obj_get_info_by_fd(prog_fd2, &prog_info, &prog_info_len);
0039     if (!ASSERT_OK(err, "fd_info2"))
0040         goto cleanup;
0041     id2 = prog_info.id;
0042 
0043     /* set initial prog attachment */
0044     err = bpf_xdp_attach(IFINDEX_LO, prog_fd1, XDP_FLAGS_REPLACE, &opts);
0045     if (!ASSERT_OK(err, "fd_attach"))
0046         goto cleanup;
0047 
0048     /* validate prog ID */
0049     err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
0050     if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
0051         goto cleanup;
0052 
0053     /* BPF link is not allowed to replace prog attachment */
0054     link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);
0055     if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
0056         bpf_link__destroy(link);
0057         /* best-effort detach prog */
0058         opts.old_prog_fd = prog_fd1;
0059         bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);
0060         goto cleanup;
0061     }
0062 
0063     /* detach BPF program */
0064     opts.old_prog_fd = prog_fd1;
0065     err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);
0066     if (!ASSERT_OK(err, "prog_detach"))
0067         goto cleanup;
0068 
0069     /* now BPF link should attach successfully */
0070     link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);
0071     if (!ASSERT_OK_PTR(link, "link_attach"))
0072         goto cleanup;
0073     skel1->links.xdp_handler = link;
0074 
0075     /* validate prog ID */
0076     err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
0077     if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
0078         goto cleanup;
0079 
0080     /* BPF prog attach is not allowed to replace BPF link */
0081     opts.old_prog_fd = prog_fd1;
0082     err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, XDP_FLAGS_REPLACE, &opts);
0083     if (!ASSERT_ERR(err, "prog_attach_fail"))
0084         goto cleanup;
0085 
0086     /* Can't force-update when BPF link is active */
0087     err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, 0, NULL);
0088     if (!ASSERT_ERR(err, "prog_update_fail"))
0089         goto cleanup;
0090 
0091     /* Can't force-detach when BPF link is active */
0092     err = bpf_xdp_detach(IFINDEX_LO, 0, NULL);
0093     if (!ASSERT_ERR(err, "prog_detach_fail"))
0094         goto cleanup;
0095 
0096     /* BPF link is not allowed to replace another BPF link */
0097     link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);
0098     if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
0099         bpf_link__destroy(link);
0100         goto cleanup;
0101     }
0102 
0103     bpf_link__destroy(skel1->links.xdp_handler);
0104     skel1->links.xdp_handler = NULL;
0105 
0106     /* new link attach should succeed */
0107     link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);
0108     if (!ASSERT_OK_PTR(link, "link_attach"))
0109         goto cleanup;
0110     skel2->links.xdp_handler = link;
0111 
0112     err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
0113     if (!ASSERT_OK(err, "id2_check_err") || !ASSERT_EQ(id0, id2, "id2_check_val"))
0114         goto cleanup;
0115 
0116     /* updating program under active BPF link works as expected */
0117     err = bpf_link__update_program(link, skel1->progs.xdp_handler);
0118     if (!ASSERT_OK(err, "link_upd"))
0119         goto cleanup;
0120 
0121     memset(&link_info, 0, sizeof(link_info));
0122     err = bpf_obj_get_info_by_fd(bpf_link__fd(link), &link_info, &link_info_len);
0123     if (!ASSERT_OK(err, "link_info"))
0124         goto cleanup;
0125 
0126     ASSERT_EQ(link_info.type, BPF_LINK_TYPE_XDP, "link_type");
0127     ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");
0128     ASSERT_EQ(link_info.xdp.ifindex, IFINDEX_LO, "link_ifindex");
0129 
0130     /* updating program under active BPF link with different type fails */
0131     err = bpf_link__update_program(link, skel1->progs.tc_handler);
0132     if (!ASSERT_ERR(err, "link_upd_invalid"))
0133         goto cleanup;
0134 
0135     err = bpf_link__detach(link);
0136     if (!ASSERT_OK(err, "link_detach"))
0137         goto cleanup;
0138 
0139     memset(&link_info, 0, sizeof(link_info));
0140     err = bpf_obj_get_info_by_fd(bpf_link__fd(link), &link_info, &link_info_len);
0141 
0142     ASSERT_OK(err, "link_info");
0143     ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");
0144     /* ifindex should be zeroed out */
0145     ASSERT_EQ(link_info.xdp.ifindex, 0, "link_ifindex");
0146 
0147 cleanup:
0148     test_xdp_link__destroy(skel1);
0149     test_xdp_link__destroy(skel2);
0150 }