From patchwork Thu Nov 8 05:39:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 10673497 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9B4DC109C for ; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8AE7B2D4AF for ; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7EDF62D4B6; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2715D2D4AE for ; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727038AbeKHPNs (ORCPT ); Thu, 8 Nov 2018 10:13:48 -0500 Received: from mail-pg1-f202.google.com ([209.85.215.202]:44475 "EHLO mail-pg1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726145AbeKHPNs (ORCPT ); Thu, 8 Nov 2018 10:13:48 -0500 Received: by mail-pg1-f202.google.com with SMTP id a2so10461618pgt.11 for ; Wed, 07 Nov 2018 21:40:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=ORL5j8b/m1OmB7Hasq8yWBseIa8g/+0VcfbWrTQqk8U=; b=HYKfN6nnRiuotEqcHL/GXE/+4bQiqiAvblXYM534L+5wEp/XnDeqnqt+O2XkCQziRo kfSQDPV+Czmeg0vRzEyLOkI9NomS0sn3GLQf4oh6CLwMdazr0YQ3O9PKPTvw+RnM9kXD L2ANC57m2c83w8ZdwBe6FSETvyeFVIUK6E7bc01vkzxYk7+LBzVMe2wyoRxWBqoPP2ik I2o1IEOmhpZnkA6w4nULFvRZncJFFtw1H3FQN/S3ZzKGuYuYIa0fTprMcO7GCU97porS wK3hQhYjkYq5GvThaZ9KFGe4OxOVLDYdNHyVDja0inqG+seAy8s0bMhOPXmblZPAMSwK M1yA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ORL5j8b/m1OmB7Hasq8yWBseIa8g/+0VcfbWrTQqk8U=; b=F+FQW6QokdAKGibOrVElbbcIZh0tK7Ybz2FQBHISMqRsSyzwY7i4SpH16yX0h6RWkR Z8+xeZwmHnmhJDGEXzv0mwFF4oheLjnkWYYoNYzQ/A++36/j3P52syn2V1KWjXMqVIvc /FN0iYUr9pmB+3AjcKL1hGOrIpjs/Z3HhajsU06a1rXDZNMs5DeSj7QTP7voMfJPniFO g1UM03WVOyRVdJKZg3MuAoZsx9yZTYfU8IamZVe0UJoYO8Hx2YLA+YSbgX84CFfI5816 7AEnAZUxhSAl3d0Hmr0J8kqTCY+4DY/eDqy59+Pdo9uqky2tm9pqdv5tlmeCvAkzpXKD Vxug== X-Gm-Message-State: AGRZ1gKLEgD92AWR54/UH+vQm+IIUdVFwEhZ/uvX9rglWN6bVev+6zal PNaVF/CR4aChKC4+aI0a/uVTrWc= X-Google-Smtp-Source: AJdET5dQQWQH4pMNXS9L0u+aoBhF7Eu2FiRRE5FW9EwqgTspLuYFgZtAZpEndQZ5Yv8rhWWRSwvYE/E= X-Received: by 2002:a62:9f83:: with SMTP id v3-v6mr1413870pfk.53.1541655603034; Wed, 07 Nov 2018 21:40:03 -0800 (PST) Date: Wed, 7 Nov 2018 21:39:54 -0800 In-Reply-To: <20181108053957.205681-1-sdf@google.com> Message-Id: <20181108053957.205681-2-sdf@google.com> Mime-Version: 1.0 References: <20181108053957.205681-1-sdf@google.com> X-Mailer: git-send-email 2.19.1.930.g4563a0d9d0-goog Subject: [PATCH v3 bpf-next 1/4] selftests/bpf: rename flow dissector section to flow_dissector From: Stanislav Fomichev To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, shuah@kernel.org, jakub.kicinski@netronome.com, quentin.monnet@netronome.com Cc: guro@fb.com, jiong.wang@netronome.com, sdf@google.com, bhole_prashant_q7@lab.ntt.co.jp, john.fastabend@gmail.com, jbenc@redhat.com, treeze.taeung@gmail.com, yhs@fb.com, osk@fb.com, sandipan@linux.vnet.ibm.com Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Makes it compatible with the logic that derives program type from section name in libbpf_prog_type_by_name. Signed-off-by: Stanislav Fomichev --- tools/testing/selftests/bpf/bpf_flow.c | 2 +- tools/testing/selftests/bpf/test_flow_dissector.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/bpf_flow.c b/tools/testing/selftests/bpf/bpf_flow.c index 107350a7821d..b9798f558ca7 100644 --- a/tools/testing/selftests/bpf/bpf_flow.c +++ b/tools/testing/selftests/bpf/bpf_flow.c @@ -116,7 +116,7 @@ static __always_inline int parse_eth_proto(struct __sk_buff *skb, __be16 proto) return BPF_DROP; } -SEC("dissect") +SEC("flow_dissector") int _dissect(struct __sk_buff *skb) { if (!skb->vlan_present) diff --git a/tools/testing/selftests/bpf/test_flow_dissector.sh b/tools/testing/selftests/bpf/test_flow_dissector.sh index c0fb073b5eab..d23d4da66b83 100755 --- a/tools/testing/selftests/bpf/test_flow_dissector.sh +++ b/tools/testing/selftests/bpf/test_flow_dissector.sh @@ -59,7 +59,7 @@ else fi # Attach BPF program -./flow_dissector_load -p bpf_flow.o -s dissect +./flow_dissector_load -p bpf_flow.o -s flow_dissector # Setup tc qdisc add dev lo ingress From patchwork Thu Nov 8 05:39:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 10673501 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4454C1923 for ; Thu, 8 Nov 2018 05:40:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 343622D4AE for ; Thu, 8 Nov 2018 05:40:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 288912D4C9; Thu, 8 Nov 2018 05:40:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4CC852D4B5 for ; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726377AbeKHPNv (ORCPT ); Thu, 8 Nov 2018 10:13:51 -0500 Received: from mail-pf1-f201.google.com ([209.85.210.201]:43401 "EHLO mail-pf1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726469AbeKHPNv (ORCPT ); Thu, 8 Nov 2018 10:13:51 -0500 Received: by mail-pf1-f201.google.com with SMTP id y144-v6so17409767pfb.10 for ; Wed, 07 Nov 2018 21:40:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=y+CE7xptS2jvSi7wQmaLROa5t0xpeXNkfsvR2sR+DGk=; b=El7TIu7syyQxFTyEcEiHwPQnuwO9pMpgNWLzfnD8B5poEFr7Z66H2OCvkQ/bKRdiXb w2mTdcBDjaslTw/fsJUr+YPTvtLIRe9YLUe1XTH6VdYfDGcGkB+9s9pxXxH9kfnfDEsj jqvkPlFse2PscYu6opmjDVcVpZJy4lXEdqrMCvYQTDp+13ViO5+D6qGZVSH6wTZxNMtk EXNQNKUmp6mDVx225ZmRqSF7N/FiaFu9j1dt+y0SmtX2iW3K1S0VBkj1AAcwhyh9MSxE 3WHIZYd19+1+fef7l6TzQOOTAjDzz6hynEiZJ0lpDoIPjlCOsHqgU7a/KLOfz8BF0s1p pZJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=y+CE7xptS2jvSi7wQmaLROa5t0xpeXNkfsvR2sR+DGk=; b=AVnSXeLNKqAGvTKcpkcP6cM4bolQPzdTuHdVH0EJa/GsaiT/QlEQG2+zbkmkwJlgzB 8sCRfigF6sYHBhXObI4xZR4yPs2n27qfaZpQucj4QVZGdn8oSZR+C0xQwKREJmR+3lHU sYLrIVn1R3rokTmb3E+KGECGCe86ApBxE1/VpcTKv9jihOCuo2qgifjiM+OhyOmgPf8G xTnYn0IBsEF0lOyOWfsfIQrW5hE9IYG4yQVOQrzEnRNARhfyoEUKcfPKz2Ztxa4wnb6E lvZScze7t9cn1rew3GwRodYi/SlA+tJfqvQUZMawmLTdhYOsuf0U4wGclIhVDK2RAoiD mkRw== X-Gm-Message-State: AGRZ1gIYyd1nTGL0N/FgBX5Mu7zFpOtvbkkXrRfAEFYvMPtEuCD7bjjd oFQmVw3xYs2+CEhQNtRUr2smwow= X-Google-Smtp-Source: AJdET5c3OlhOJjZneIwmuU4DV9bCAQftU3OXdziBL4EGQo3WDM2M3J2zf9uraNjNgnxNf20+6rc94jI= X-Received: by 2002:a63:a05a:: with SMTP id u26mr1369635pgn.25.1541655605226; Wed, 07 Nov 2018 21:40:05 -0800 (PST) Date: Wed, 7 Nov 2018 21:39:55 -0800 In-Reply-To: <20181108053957.205681-1-sdf@google.com> Message-Id: <20181108053957.205681-3-sdf@google.com> Mime-Version: 1.0 References: <20181108053957.205681-1-sdf@google.com> X-Mailer: git-send-email 2.19.1.930.g4563a0d9d0-goog Subject: [PATCH v3 bpf-next 2/4] libbpf: cleanup after partial failure in bpf_object__pin From: Stanislav Fomichev To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, shuah@kernel.org, jakub.kicinski@netronome.com, quentin.monnet@netronome.com Cc: guro@fb.com, jiong.wang@netronome.com, sdf@google.com, bhole_prashant_q7@lab.ntt.co.jp, john.fastabend@gmail.com, jbenc@redhat.com, treeze.taeung@gmail.com, yhs@fb.com, osk@fb.com, sandipan@linux.vnet.ibm.com Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP bpftool will use bpf_object__pin in the next commit to pin all programs and maps from the file; in case of a partial failure, we need to get back to the clean state (undo previous program/map pins). Signed-off-by: Stanislav Fomichev --- tools/lib/bpf/libbpf.c | 248 ++++++++++++++++++++++++++++++++++++----- tools/lib/bpf/libbpf.h | 11 ++ 2 files changed, 230 insertions(+), 29 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index d6e62e90e8d4..db84c85554e7 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -1699,6 +1699,34 @@ int bpf_program__pin_instance(struct bpf_program *prog, const char *path, return 0; } +int bpf_program__unpin_instance(struct bpf_program *prog, const char *path, + int instance) +{ + int err; + + err = check_path(path); + if (err) + return err; + + if (prog == NULL) { + pr_warning("invalid program pointer\n"); + return -EINVAL; + } + + if (instance < 0 || instance >= prog->instances.nr) { + pr_warning("invalid prog instance %d of prog %s (max %d)\n", + instance, prog->section_name, prog->instances.nr); + return -EINVAL; + } + + err = unlink(path); + if (err != 0) + return -errno; + pr_debug("unpinned program '%s'\n", path); + + return 0; +} + static int make_dir(const char *path) { char *cp, errmsg[STRERR_BUFSIZE]; @@ -1737,6 +1765,64 @@ int bpf_program__pin(struct bpf_program *prog, const char *path) if (err) return err; + for (i = 0; i < prog->instances.nr; i++) { + char buf[PATH_MAX]; + int len; + + len = snprintf(buf, PATH_MAX, "%s/%d", path, i); + if (len < 0) { + err = -EINVAL; + goto err_unpin; + } else if (len >= PATH_MAX) { + err = -ENAMETOOLONG; + goto err_unpin; + } + + err = bpf_program__pin_instance(prog, buf, i); + if (err) + goto err_unpin; + } + + return 0; + +err_unpin: + for (i = i - 1; i >= 0; i--) { + char buf[PATH_MAX]; + int len; + + len = snprintf(buf, PATH_MAX, "%s/%d", path, i); + if (len < 0) + continue; + else if (len >= PATH_MAX) + continue; + + bpf_program__unpin_instance(prog, buf, i); + } + + rmdir(path); + + return err; +} + +int bpf_program__unpin(struct bpf_program *prog, const char *path) +{ + int i, err; + + err = check_path(path); + if (err) + return err; + + if (prog == NULL) { + pr_warning("invalid program pointer\n"); + return -EINVAL; + } + + if (prog->instances.nr <= 0) { + pr_warning("no instances of prog %s to pin\n", + prog->section_name); + return -EINVAL; + } + for (i = 0; i < prog->instances.nr; i++) { char buf[PATH_MAX]; int len; @@ -1747,11 +1833,15 @@ int bpf_program__pin(struct bpf_program *prog, const char *path) else if (len >= PATH_MAX) return -ENAMETOOLONG; - err = bpf_program__pin_instance(prog, buf, i); + err = bpf_program__unpin_instance(prog, buf, i); if (err) return err; } + err = rmdir(path); + if (err) + return -errno; + return 0; } @@ -1776,6 +1866,28 @@ int bpf_map__pin(struct bpf_map *map, const char *path) } pr_debug("pinned map '%s'\n", path); + + return 0; +} + +int bpf_map__unpin(struct bpf_map *map, const char *path) +{ + int err; + + err = check_path(path); + if (err) + return err; + + if (map == NULL) { + pr_warning("invalid map pointer\n"); + return -EINVAL; + } + + err = unlink(path); + if (err != 0) + return -errno; + pr_debug("unpinned map '%s'\n", path); + return 0; } @@ -1803,14 +1915,17 @@ int bpf_object__pin(struct bpf_object *obj, const char *path) len = snprintf(buf, PATH_MAX, "%s/%s", path, bpf_map__name(map)); - if (len < 0) - return -EINVAL; - else if (len >= PATH_MAX) - return -ENAMETOOLONG; + if (len < 0) { + err = -EINVAL; + goto err_unpin_maps; + } else if (len >= PATH_MAX) { + err = -ENAMETOOLONG; + goto err_unpin_maps; + } err = bpf_map__pin(map, buf); if (err) - return err; + goto err_unpin_maps; } bpf_object__for_each_program(prog, obj) { @@ -1819,17 +1934,56 @@ int bpf_object__pin(struct bpf_object *obj, const char *path) len = snprintf(buf, PATH_MAX, "%s/%s", path, prog->section_name); - if (len < 0) - return -EINVAL; - else if (len >= PATH_MAX) - return -ENAMETOOLONG; + if (len < 0) { + err = -EINVAL; + goto err_unpin_programs; + } else if (len >= PATH_MAX) { + err = -ENAMETOOLONG; + goto err_unpin_programs; + } err = bpf_program__pin(prog, buf); if (err) - return err; + goto err_unpin_programs; } return 0; + +err_unpin_programs: + for (prog = bpf_program__prev(prog, obj); + prog != NULL; + prog = bpf_program__prev(prog, obj)) { + char buf[PATH_MAX]; + int len; + + len = snprintf(buf, PATH_MAX, "%s/%s", path, + prog->section_name); + if (len < 0) + continue; + else if (len >= PATH_MAX) + continue; + + bpf_program__unpin(prog, buf); + } + +err_unpin_maps: + for (map = bpf_map__prev(map, obj); + map != NULL; + map = bpf_map__prev(map, obj)) { + char buf[PATH_MAX]; + int len; + + len = snprintf(buf, PATH_MAX, "%s/%s", path, + bpf_map__name(map)); + if (len < 0) + continue; + else if (len >= PATH_MAX) + continue; + + bpf_map__unpin(map, buf); + } + + return err; } void bpf_object__close(struct bpf_object *obj) @@ -1918,23 +2072,20 @@ void *bpf_object__priv(struct bpf_object *obj) } static struct bpf_program * -__bpf_program__next(struct bpf_program *prev, struct bpf_object *obj) +__bpf_program__iter(struct bpf_program *p, struct bpf_object *obj, int i) { - size_t idx; + ssize_t idx; if (!obj->programs) return NULL; - /* First handler */ - if (prev == NULL) - return &obj->programs[0]; - if (prev->obj != obj) { + if (p->obj != obj) { pr_warning("error: program handler doesn't match object\n"); return NULL; } - idx = (prev - obj->programs) + 1; - if (idx >= obj->nr_programs) + idx = (p - obj->programs) + i; + if (idx >= obj->nr_programs || idx < 0) return NULL; return &obj->programs[idx]; } @@ -1944,8 +2095,29 @@ bpf_program__next(struct bpf_program *prev, struct bpf_object *obj) { struct bpf_program *prog = prev; + if (prev == NULL) + return obj->programs; + + do { + prog = __bpf_program__iter(prog, obj, 1); + } while (prog && bpf_program__is_function_storage(prog, obj)); + + return prog; +} + +struct bpf_program * +bpf_program__prev(struct bpf_program *next, struct bpf_object *obj) +{ + struct bpf_program *prog = next; + + if (next == NULL) { + if (!obj->nr_programs) + return NULL; + return obj->programs + obj->nr_programs - 1; + } + do { - prog = __bpf_program__next(prog, obj); + prog = __bpf_program__iter(prog, obj, -1); } while (prog && bpf_program__is_function_storage(prog, obj)); return prog; @@ -2272,10 +2444,10 @@ void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex) map->map_ifindex = ifindex; } -struct bpf_map * -bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) +static struct bpf_map * +__bpf_map__iter(struct bpf_map *m, struct bpf_object *obj, int i) { - size_t idx; + ssize_t idx; struct bpf_map *s, *e; if (!obj || !obj->maps) @@ -2284,21 +2456,39 @@ bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) s = obj->maps; e = obj->maps + obj->nr_maps; - if (prev == NULL) - return s; - - if ((prev < s) || (prev >= e)) { + if ((m < s) || (m >= e)) { pr_warning("error in %s: map handler doesn't belong to object\n", __func__); return NULL; } - idx = (prev - obj->maps) + 1; - if (idx >= obj->nr_maps) + idx = (m - obj->maps) + i; + if (idx >= obj->nr_maps || idx < 0) return NULL; return &obj->maps[idx]; } +struct bpf_map * +bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) +{ + if (prev == NULL) + return obj->maps; + + return __bpf_map__iter(prev, obj, 1); +} + +struct bpf_map * +bpf_map__prev(struct bpf_map *next, struct bpf_object *obj) +{ + if (next == NULL) { + if (!obj->nr_maps) + return NULL; + return obj->maps + obj->nr_maps - 1; + } + + return __bpf_map__iter(next, obj, -1); +} + struct bpf_map * bpf_object__find_map_by_name(struct bpf_object *obj, const char *name) { diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 1f3468dad8b2..785b27f761de 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -112,6 +112,9 @@ LIBBPF_API struct bpf_program *bpf_program__next(struct bpf_program *prog, (pos) != NULL; \ (pos) = bpf_program__next((pos), (obj))) +LIBBPF_API struct bpf_program *bpf_program__prev(struct bpf_program *prog, + struct bpf_object *obj); + typedef void (*bpf_program_clear_priv_t)(struct bpf_program *, void *); @@ -131,7 +134,11 @@ LIBBPF_API int bpf_program__fd(struct bpf_program *prog); LIBBPF_API int bpf_program__pin_instance(struct bpf_program *prog, const char *path, int instance); +LIBBPF_API int bpf_program__unpin_instance(struct bpf_program *prog, + const char *path, + int instance); LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path); +LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path); LIBBPF_API void bpf_program__unload(struct bpf_program *prog); struct bpf_insn; @@ -260,6 +267,9 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj); (pos) != NULL; \ (pos) = bpf_map__next((pos), (obj))) +LIBBPF_API struct bpf_map * +bpf_map__prev(struct bpf_map *map, struct bpf_object *obj); + LIBBPF_API int bpf_map__fd(struct bpf_map *map); LIBBPF_API const struct bpf_map_def *bpf_map__def(struct bpf_map *map); LIBBPF_API const char *bpf_map__name(struct bpf_map *map); @@ -274,6 +284,7 @@ LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd); LIBBPF_API bool bpf_map__is_offload_neutral(struct bpf_map *map); LIBBPF_API void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex); LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path); +LIBBPF_API int bpf_map__unpin(struct bpf_map *map, const char *path); LIBBPF_API long libbpf_get_error(const void *ptr); From patchwork Thu Nov 8 05:39:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 10673499 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0F8C217D4 for ; Thu, 8 Nov 2018 05:40:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F41932D4AE for ; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E728B2D4C9; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 857A12D4AE for ; Thu, 8 Nov 2018 05:40:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726380AbeKHPNx (ORCPT ); Thu, 8 Nov 2018 10:13:53 -0500 Received: from mail-qk1-f202.google.com ([209.85.222.202]:56078 "EHLO mail-qk1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725953AbeKHPNx (ORCPT ); Thu, 8 Nov 2018 10:13:53 -0500 Received: by mail-qk1-f202.google.com with SMTP id 98so35138869qkp.22 for ; Wed, 07 Nov 2018 21:40:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=vZDnnf7d4plZ5CEpRHCwyr8Cwk/MsYOzuas7G00pfkM=; b=Pm9j5Ebid7v3PZiXy6iqzPrLQMRGt5fSBdVsAsPE3g/72TmP5uY6c0bsCmMuGqdpiU 05eA0UJA0XrTDllV0M7p/Oycr8eWedcgYojQTk1bThx40VrvWaS3415WhqppAKZLwtN3 aNYrjKm/aS7gMAdAcC3S+ZhGfS78KJzcBEMKx8A71YOoFcvWY4RTHeXqHsMYefvv+LCA SlCt/jwg5BF8huw6lWg6sqsKEW/qBWt6yfvxf7cyefMx1NqMSUzPruyzvnaaS6L0ieLs uCwhA/g3jvS411nbCbVzDmAkuZzNy3SYiiRTJthBYkdzTpoUk8Z5V3OA+wbEQOH2Ov0B ly3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=vZDnnf7d4plZ5CEpRHCwyr8Cwk/MsYOzuas7G00pfkM=; b=gkcK29Ec5KnAu9ODNDAQj48cuX4YO3JaQvkGM8XcbuJjbev7zcK3Xgj+EiPAAPVbYX Ubw9JCvPg4ggxDXjJIDg4xqBBgmYp15em4G9Y2pW3Tmz35yQViXy+OeMEc6UdLplnIQM 8iJDHSvavueK91Vc65FvjNqaDcEfbEXTMTnqTZ44lBYtXwMKuRTlRF7m5kNSRamMbdn+ dAcfwvOFPGvTspAuzDSPq/+uoPLIcP4aIVSgweZxTdOtq8ZXZES6hzaPt3DOFMvJ6hZm E9pvl415EgHBLJWeqNFUxbqvmjS6e5zHp5PXxkPhvJ7gxyjZm7oF2lnrf8Wbg4XqrcOT dH4Q== X-Gm-Message-State: AGRZ1gJYn7v3WLPaV2yYsWxejtmECyZWzGNABy3uDvYnpmjAiqYlRMC3 vfTJ2+57FXIHve8rFw5+5MxFTKY= X-Google-Smtp-Source: AJdET5fh37Z45ODiXBIFNZhvGhUd4koR//FRoNK3WkeHXS/khV0r/0P+ZMcm2tQluZSpPcn1+Vl9p38= X-Received: by 2002:a37:f4b:: with SMTP id z72mr2023249qkg.20.1541655607572; Wed, 07 Nov 2018 21:40:07 -0800 (PST) Date: Wed, 7 Nov 2018 21:39:56 -0800 In-Reply-To: <20181108053957.205681-1-sdf@google.com> Message-Id: <20181108053957.205681-4-sdf@google.com> Mime-Version: 1.0 References: <20181108053957.205681-1-sdf@google.com> X-Mailer: git-send-email 2.19.1.930.g4563a0d9d0-goog Subject: [PATCH v3 bpf-next 3/4] libbpf: bpf_program__pin: add special case for instances.nr == 1 From: Stanislav Fomichev To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, shuah@kernel.org, jakub.kicinski@netronome.com, quentin.monnet@netronome.com Cc: guro@fb.com, jiong.wang@netronome.com, sdf@google.com, bhole_prashant_q7@lab.ntt.co.jp, john.fastabend@gmail.com, jbenc@redhat.com, treeze.taeung@gmail.com, yhs@fb.com, osk@fb.com, sandipan@linux.vnet.ibm.com Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When bpf_program has only one instance, don't create a subdirectory with per-instance pin files (/0). Instead, just create a single pin file for that single instance. This simplifies object pinning by not creating unnecessary subdirectories. This can potentially break existing users that depend on the case where '/0' is always created. However, I couldn't find any serious usage of bpf_program__pin inside the kernel tree and I suppose there should be none outside. Signed-off-by: Stanislav Fomichev --- tools/lib/bpf/libbpf.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index db84c85554e7..8407a880acbe 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -1761,6 +1761,11 @@ int bpf_program__pin(struct bpf_program *prog, const char *path) return -EINVAL; } + if (prog->instances.nr == 1) { + /* don't create subdirs when pinning single instance */ + return bpf_program__pin_instance(prog, path, 0); + } + err = make_dir(path); if (err) return err; @@ -1823,6 +1828,11 @@ int bpf_program__unpin(struct bpf_program *prog, const char *path) return -EINVAL; } + if (prog->instances.nr == 1) { + /* don't create subdirs when pinning single instance */ + return bpf_program__unpin_instance(prog, path, 0); + } + for (i = 0; i < prog->instances.nr; i++) { char buf[PATH_MAX]; int len; From patchwork Thu Nov 8 05:39:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 10673503 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5F422109C for ; Thu, 8 Nov 2018 05:40:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4AF412D4DC for ; Thu, 8 Nov 2018 05:40:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 35A762D49C; Thu, 8 Nov 2018 05:40:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0B6082D4DA for ; Thu, 8 Nov 2018 05:40:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726535AbeKHPN4 (ORCPT ); Thu, 8 Nov 2018 10:13:56 -0500 Received: from mail-pg1-f202.google.com ([209.85.215.202]:49980 "EHLO mail-pg1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726292AbeKHPNz (ORCPT ); Thu, 8 Nov 2018 10:13:55 -0500 Received: by mail-pg1-f202.google.com with SMTP id a18so3989629pga.16 for ; Wed, 07 Nov 2018 21:40:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=fhi7SbOZOjl2fk4v5etA9feDbvBizLJ6PaEolhS8D2c=; b=ZSQeKx93orBRnLIW3f5+8vgt65BgYkSXcaD6GD0ikrTy6botvVBHhS9nBbNufBlqv5 kLW+kRAWny/fB0KSXhz3gV5fDMVRZ4fzptMEV2t08Wk0P2BsPMFAPC8+FFtdnSnil0vc W2qc0IrCdWjogC9vfSBbc6oOzTz7Q2Vxkw6zG9DpSli4xqJ2lvy1Q+thid6yRYbh3/mQ dd2v2Q+BEcQkmlbuGhNDcYYWQE1hcBRLjbzfrfclOTlL0vOuCNjcL2qkxgAcgdWNrU1r kxM1FS/jUO4px9p8a8wxZTmNd8m5nNnBSYAze2biZK+MpdUHPx+d6KlEnLypVPHPLUzk oYWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=fhi7SbOZOjl2fk4v5etA9feDbvBizLJ6PaEolhS8D2c=; b=O3kaBwOJWblk9CLSCYegKwuv1mq895rjBsOyNsfYDdXc99aELIEf2jAw9p+bsKWmRv K50Mc9SoUY34z4i3usb3FxF/ej/cV13klDgcxv1OfFncPai7thGjKu8PLqL3DtuPhQBU tZZCyUeQmRt8Oozj8ZzxRD+wMFvzko4c786vrI3BlRFBJ0ZlZFJHVkLRMnxCel6J7tJ0 NAuD1VJdGZ7nbojF2JCTioo4+U0vjWjtJhpBxd+wk3cUF1fhxyQuKNzLY9AAvEyG1HmX dQTfYnuF0tAA/qyqXt3CxMVk4RIEVxE9AFJa54+sYt9dQrqDVz6BX2MmM4sPROdYZEZt 34RA== X-Gm-Message-State: AGRZ1gLZQJjAccF1NspEk12kdH8VLsV4aSNloNoHlC0BRlVarwY7I/Mv /p6+KoONzgtFrIrdY5AlvFhGe6I= X-Google-Smtp-Source: AJdET5f2929gnDcE2NOuDc2ZyZBbKeUNMSqyyfL76iKEUSXgUu/mjGqkADOncU9IwFXFcpHT1Z2bcIU= X-Received: by 2002:a63:36c1:: with SMTP id d184-v6mr97828pga.73.1541655609916; Wed, 07 Nov 2018 21:40:09 -0800 (PST) Date: Wed, 7 Nov 2018 21:39:57 -0800 In-Reply-To: <20181108053957.205681-1-sdf@google.com> Message-Id: <20181108053957.205681-5-sdf@google.com> Mime-Version: 1.0 References: <20181108053957.205681-1-sdf@google.com> X-Mailer: git-send-email 2.19.1.930.g4563a0d9d0-goog Subject: [PATCH v3 bpf-next 4/4] bpftool: support loading flow dissector From: Stanislav Fomichev To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, shuah@kernel.org, jakub.kicinski@netronome.com, quentin.monnet@netronome.com Cc: guro@fb.com, jiong.wang@netronome.com, sdf@google.com, bhole_prashant_q7@lab.ntt.co.jp, john.fastabend@gmail.com, jbenc@redhat.com, treeze.taeung@gmail.com, yhs@fb.com, osk@fb.com, sandipan@linux.vnet.ibm.com Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This commit adds support for loading/attaching/detaching flow dissector program. The structure of the flow dissector program is assumed to be the same as in the selftests: * flow_dissector section with the main entry point * a bunch of tail call progs * a jmp_table map that is populated with the tail call progs When `bpftool load` is called with a flow_dissector prog (i.e. when the first section is flow_dissector of 'type flow_dissector' argument is passed), we load and pin all the programs/maps. User is responsible to construct the jump table for the tail calls. The last argument of `bpftool attach` is made optional for this use case. Example: bpftool prog load tools/testing/selftests/bpf/bpf_flow.o \ /sys/fs/bpf/flow type flow_dissector bpftool map update pinned /sys/fs/bpf/flow/jmp_table \ key 0 0 0 0 \ value pinned /sys/fs/bpf/flow/IP bpftool map update pinned /sys/fs/bpf/flow/jmp_table \ key 1 0 0 0 \ value pinned /sys/fs/bpf/flow/IPV6 bpftool map update pinned /sys/fs/bpf/flow/jmp_table \ key 2 0 0 0 \ value pinned /sys/fs/bpf/flow/IPV6OP bpftool map update pinned /sys/fs/bpf/flow/jmp_table \ key 3 0 0 0 \ value pinned /sys/fs/bpf/flow/IPV6FR bpftool map update pinned /sys/fs/bpf/flow/jmp_table \ key 4 0 0 0 \ value pinned /sys/fs/bpf/flow/MPLS bpftool map update pinned /sys/fs/bpf/flow/jmp_table \ key 5 0 0 0 \ value pinned /sys/fs/bpf/flow/VLAN bpftool prog attach pinned /sys/fs/bpf/flow/flow_dissector flow_dissector Tested by using the above lines to load the prog in the test_flow_dissector.sh selftest. Signed-off-by: Stanislav Fomichev --- .../bpftool/Documentation/bpftool-prog.rst | 36 ++++-- tools/bpf/bpftool/bash-completion/bpftool | 6 +- tools/bpf/bpftool/common.c | 30 ++--- tools/bpf/bpftool/main.h | 1 + tools/bpf/bpftool/prog.c | 112 +++++++++++++----- 5 files changed, 126 insertions(+), 59 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst index ac4e904b10fb..0374634c3087 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst @@ -15,7 +15,8 @@ SYNOPSIS *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } } *COMMANDS* := - { **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** | **help** } + { **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** + | **loadall** | **help** } MAP COMMANDS ============= @@ -24,9 +25,9 @@ MAP COMMANDS | **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual**}] | **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] | **bpftool** **prog pin** *PROG* *FILE* -| **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] -| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* *MAP* -| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* *MAP* +| **bpftool** **prog { load | loadall }** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] +| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*] +| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* [*MAP*] | **bpftool** **prog help** | | *MAP* := { **id** *MAP_ID* | **pinned** *FILE* } @@ -39,7 +40,9 @@ MAP COMMANDS | **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** | | **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** | } -| *ATTACH_TYPE* := { **msg_verdict** | **skb_verdict** | **skb_parse** } +| *ATTACH_TYPE* := { +| **msg_verdict** | **skb_verdict** | **skb_parse** | **flow_dissector** +| } DESCRIPTION @@ -79,8 +82,11 @@ DESCRIPTION contain a dot character ('.'), which is reserved for future extensions of *bpffs*. - **bpftool prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] + **bpftool prog { load | loadall }** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] Load bpf program from binary *OBJ* and pin as *FILE*. + **bpftool prog load** will pin only the first bpf program + from the *OBJ*, **bpftool prog loadall** will pin all maps + and programs from the *OBJ*. **type** is optional, if not specified program type will be inferred from section names. By default bpftool will create new maps as declared in the ELF @@ -97,13 +103,17 @@ DESCRIPTION contain a dot character ('.'), which is reserved for future extensions of *bpffs*. - **bpftool prog attach** *PROG* *ATTACH_TYPE* *MAP* - Attach bpf program *PROG* (with type specified by *ATTACH_TYPE*) - to the map *MAP*. - - **bpftool prog detach** *PROG* *ATTACH_TYPE* *MAP* - Detach bpf program *PROG* (with type specified by *ATTACH_TYPE*) - from the map *MAP*. + **bpftool prog attach** *PROG* *ATTACH_TYPE* [*MAP*] + Attach bpf program *PROG* (with type specified by + *ATTACH_TYPE*). Most *ATTACH_TYPEs* require a *MAP* + parameter, with the exception of *flow_dissector* which is + attached to current networking name space. + + **bpftool prog detach** *PROG* *ATTACH_TYPE* [*MAP*] + Detach bpf program *PROG* (with type specified by + *ATTACH_TYPE*). Most *ATTACH_TYPEs* require a *MAP* + parameter, with the exception of *flow_dissector* which is + detached from the current networking name space. **bpftool prog help** Print short help message. diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 3f78e6404589..ad0fc919f7ec 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -243,7 +243,7 @@ _bpftool() # Completion depends on object and command in use case $object in prog) - if [[ $command != "load" ]]; then + if [[ $command != "load" && $command != "loadall" ]]; then case $prev in id) _bpftool_get_prog_ids @@ -299,7 +299,7 @@ _bpftool() fi if [[ ${#words[@]} == 6 ]]; then - COMPREPLY=( $( compgen -W "msg_verdict skb_verdict skb_parse" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "msg_verdict skb_verdict skb_parse flow_dissector" -- "$cur" ) ) return 0 fi @@ -309,7 +309,7 @@ _bpftool() fi return 0 ;; - load) + load|loadall) local obj if [[ ${#words[@]} -lt 6 ]]; then diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index 25af85304ebe..f671a921dec5 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c @@ -169,34 +169,24 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type) return fd; } -int do_pin_fd(int fd, const char *name) +int mount_bpffs_for_pin(const char *name) { char err_str[ERR_MAX_LEN]; char *file; char *dir; int err = 0; - err = bpf_obj_pin(fd, name); - if (!err) - goto out; - file = malloc(strlen(name) + 1); strcpy(file, name); dir = dirname(file); - if (errno != EPERM || is_bpffs(dir)) { - p_err("can't pin the object (%s): %s", name, strerror(errno)); + if (is_bpffs(dir)) { + /* nothing to do if already mounted */ goto out_free; } - /* Attempt to mount bpffs, then retry pinning. */ err = mnt_bpffs(dir, err_str, ERR_MAX_LEN); - if (!err) { - err = bpf_obj_pin(fd, name); - if (err) - p_err("can't pin the object (%s): %s", name, - strerror(errno)); - } else { + if (err) { err_str[ERR_MAX_LEN - 1] = '\0'; p_err("can't mount BPF file system to pin the object (%s): %s", name, err_str); @@ -204,10 +194,20 @@ int do_pin_fd(int fd, const char *name) out_free: free(file); -out: return err; } +int do_pin_fd(int fd, const char *name) +{ + int err; + + err = mount_bpffs_for_pin(name); + if (err) + return err; + + return bpf_obj_pin(fd, name); +} + int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)) { unsigned int id; diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 28322ace2856..1383824c9baf 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -129,6 +129,7 @@ const char *get_fd_type_name(enum bpf_obj_type type); char *get_fdinfo(int fd, const char *key); int open_obj_pinned(char *path); int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type); +int mount_bpffs_for_pin(const char *name); int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)); int do_pin_fd(int fd, const char *name); diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 5302ee282409..a4346dd673b1 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -81,6 +81,7 @@ static const char * const attach_type_strings[] = { [BPF_SK_SKB_STREAM_PARSER] = "stream_parser", [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict", [BPF_SK_MSG_VERDICT] = "msg_verdict", + [BPF_FLOW_DISSECTOR] = "flow_dissector", [__MAX_BPF_ATTACH_TYPE] = NULL, }; @@ -724,10 +725,11 @@ int map_replace_compar(const void *p1, const void *p2) static int do_attach(int argc, char **argv) { enum bpf_attach_type attach_type; - int err, mapfd, progfd; + int err, progfd; + int mapfd = 0; - if (!REQ_ARGS(5)) { - p_err("too few parameters for map attach"); + if (!REQ_ARGS(3)) { + p_err("too few parameters for attach"); return -EINVAL; } @@ -740,11 +742,17 @@ static int do_attach(int argc, char **argv) p_err("invalid attach type"); return -EINVAL; } - NEXT_ARG(); + if (attach_type != BPF_FLOW_DISSECTOR) { + NEXT_ARG(); + if (!REQ_ARGS(2)) { + p_err("too few parameters for map attach"); + return -EINVAL; + } - mapfd = map_parse_fd(&argc, &argv); - if (mapfd < 0) - return mapfd; + mapfd = map_parse_fd(&argc, &argv); + if (mapfd < 0) + return mapfd; + } err = bpf_prog_attach(progfd, mapfd, attach_type, 0); if (err) { @@ -760,10 +768,11 @@ static int do_attach(int argc, char **argv) static int do_detach(int argc, char **argv) { enum bpf_attach_type attach_type; - int err, mapfd, progfd; + int err, progfd; + int mapfd = 0; - if (!REQ_ARGS(5)) { - p_err("too few parameters for map detach"); + if (!REQ_ARGS(3)) { + p_err("too few parameters for detach"); return -EINVAL; } @@ -776,11 +785,17 @@ static int do_detach(int argc, char **argv) p_err("invalid attach type"); return -EINVAL; } - NEXT_ARG(); + if (attach_type != BPF_FLOW_DISSECTOR) { + NEXT_ARG(); + if (!REQ_ARGS(2)) { + p_err("too few parameters for map detach"); + return -EINVAL; + } - mapfd = map_parse_fd(&argc, &argv); - if (mapfd < 0) - return mapfd; + mapfd = map_parse_fd(&argc, &argv); + if (mapfd < 0) + return mapfd; + } err = bpf_prog_detach2(progfd, mapfd, attach_type); if (err) { @@ -792,15 +807,16 @@ static int do_detach(int argc, char **argv) jsonw_null(json_wtr); return 0; } -static int do_load(int argc, char **argv) + +static int load_with_options(int argc, char **argv, bool first_prog_only) { enum bpf_attach_type expected_attach_type; struct bpf_object_open_attr attr = { .prog_type = BPF_PROG_TYPE_UNSPEC, }; struct map_replace *map_replace = NULL; + struct bpf_program *prog = NULL, *pos; unsigned int old_map_fds = 0; - struct bpf_program *prog; struct bpf_object *obj; struct bpf_map *map; const char *pinfile; @@ -918,14 +934,20 @@ static int do_load(int argc, char **argv) goto err_free_reuse_maps; } - prog = bpf_program__next(NULL, obj); - if (!prog) { - p_err("object file doesn't contain any bpf program"); - goto err_close_obj; + if (first_prog_only) { + prog = bpf_program__next(NULL, obj); + if (!prog) { + p_err("object file doesn't contain any bpf program"); + goto err_close_obj; + } } - bpf_program__set_ifindex(prog, ifindex); if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) { + if (!prog) { + p_err("can not guess program type when loading all programs\n"); + goto err_close_obj; + } + const char *sec_name = bpf_program__title(prog, false); err = libbpf_prog_type_by_name(sec_name, &attr.prog_type, @@ -936,8 +958,13 @@ static int do_load(int argc, char **argv) goto err_close_obj; } } - bpf_program__set_type(prog, attr.prog_type); - bpf_program__set_expected_attach_type(prog, expected_attach_type); + + bpf_object__for_each_program(pos, obj) { + bpf_program__set_ifindex(pos, ifindex); + bpf_program__set_type(pos, attr.prog_type); + bpf_program__set_expected_attach_type(pos, + expected_attach_type); + } qsort(map_replace, old_map_fds, sizeof(*map_replace), map_replace_compar); @@ -1001,9 +1028,25 @@ static int do_load(int argc, char **argv) goto err_close_obj; } - if (do_pin_fd(bpf_program__fd(prog), pinfile)) + err = mount_bpffs_for_pin(pinfile); + if (err) goto err_close_obj; + if (prog) { + err = bpf_obj_pin(bpf_program__fd(prog), pinfile); + if (err) { + p_err("failed to pin program %s", + bpf_program__title(prog, false)); + goto err_close_obj; + } + } else { + err = bpf_object__pin(obj, pinfile); + if (err) { + p_err("failed to pin all programs"); + goto err_close_obj; + } + } + if (json_output) jsonw_null(json_wtr); @@ -1023,6 +1066,16 @@ static int do_load(int argc, char **argv) return -1; } +static int do_load(int argc, char **argv) +{ + return load_with_options(argc, argv, true); +} + +static int do_loadall(int argc, char **argv) +{ + return load_with_options(argc, argv, false); +} + static int do_help(int argc, char **argv) { if (json_output) { @@ -1035,10 +1088,11 @@ static int do_help(int argc, char **argv) " %s %s dump xlated PROG [{ file FILE | opcodes | visual }]\n" " %s %s dump jited PROG [{ file FILE | opcodes }]\n" " %s %s pin PROG FILE\n" - " %s %s load OBJ FILE [type TYPE] [dev NAME] \\\n" + " %s %s { load | loadall } OBJ FILE \\\n" + " [type TYPE] [dev NAME] \\\n" " [map { idx IDX | name NAME } MAP]\n" - " %s %s attach PROG ATTACH_TYPE MAP\n" - " %s %s detach PROG ATTACH_TYPE MAP\n" + " %s %s attach PROG ATTACH_TYPE [MAP]\n" + " %s %s detach PROG ATTACH_TYPE [MAP]\n" " %s %s help\n" "\n" " " HELP_SPEC_MAP "\n" @@ -1050,7 +1104,8 @@ static int do_help(int argc, char **argv) " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" " cgroup/sendmsg4 | cgroup/sendmsg6 }\n" - " ATTACH_TYPE := { msg_verdict | skb_verdict | skb_parse }\n" + " ATTACH_TYPE := { msg_verdict | skb_verdict | skb_parse |\n" + " flow_dissector }\n" " " HELP_SPEC_OPTIONS "\n" "", bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], @@ -1067,6 +1122,7 @@ static const struct cmd cmds[] = { { "dump", do_dump }, { "pin", do_pin }, { "load", do_load }, + { "loadall", do_loadall }, { "attach", do_attach }, { "detach", do_detach }, { 0 }