get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/807129/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 807129,
    "url": "http://patchwork.ozlabs.org/api/patches/807129/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/150401749138.16384.17129327124102881342.stgit@firesoul/",
    "project": {
        "id": 7,
        "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api",
        "name": "Linux network development",
        "link_name": "netdev",
        "list_id": "netdev.vger.kernel.org",
        "list_email": "netdev@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<150401749138.16384.17129327124102881342.stgit@firesoul>",
    "list_archive_url": null,
    "date": "2017-08-29T14:38:11",
    "name": "[net-next,7/7] samples/bpf: xdp_monitor tool based on tracepoints",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "a04b6a50ebb342db38e1ec8a94b544d44d8f7c97",
    "submitter": {
        "id": 13625,
        "url": "http://patchwork.ozlabs.org/api/people/13625/?format=api",
        "name": "Jesper Dangaard Brouer",
        "email": "brouer@redhat.com"
    },
    "delegate": {
        "id": 34,
        "url": "http://patchwork.ozlabs.org/api/users/34/?format=api",
        "username": "davem",
        "first_name": "David",
        "last_name": "Miller",
        "email": "davem@davemloft.net"
    },
    "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/150401749138.16384.17129327124102881342.stgit@firesoul/mbox/",
    "series": [
        {
            "id": 382,
            "url": "http://patchwork.ozlabs.org/api/series/382/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=382",
            "date": "2017-08-29T14:37:35",
            "name": "XDP redirect tracepoints",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/382/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/807129/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/807129/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<netdev-owner@vger.kernel.org>",
        "X-Original-To": "patchwork-incoming@ozlabs.org",
        "Delivered-To": "patchwork-incoming@ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
            "ext-mx03.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com",
            "ext-mx03.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=brouer@redhat.com"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xhWTR0WCrz9s7f\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 00:38:19 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S932071AbdH2OiR (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tTue, 29 Aug 2017 10:38:17 -0400",
            "from mx1.redhat.com ([209.132.183.28]:59060 \"EHLO mx1.redhat.com\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S1754556AbdH2OiP (ORCPT <rfc822;netdev@vger.kernel.org>);\n\tTue, 29 Aug 2017 10:38:15 -0400",
            "from smtp.corp.redhat.com\n\t(int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id 7029D7E424;\n\tTue, 29 Aug 2017 14:38:15 +0000 (UTC)",
            "from firesoul.localdomain (ovpn-200-32.brq.redhat.com\n\t[10.40.200.32])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id 486614F6D8;\n\tTue, 29 Aug 2017 14:38:12 +0000 (UTC)",
            "from [192.168.5.1] (localhost [IPv6:::1])\n\tby firesoul.localdomain (Postfix) with ESMTP id 743AD30F12C9F;\n\tTue, 29 Aug 2017 16:38:11 +0200 (CEST)"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.3.2 mx1.redhat.com 7029D7E424",
        "Subject": "[PATCH net-next 7/7] samples/bpf: xdp_monitor tool based on\n\ttracepoints",
        "From": "Jesper Dangaard Brouer <brouer@redhat.com>",
        "To": "netdev@vger.kernel.org",
        "Cc": "John Fastabend <john.fastabend@gmail.com>,\n\tJesper Dangaard Brouer <brouer@redhat.com>",
        "Date": "Tue, 29 Aug 2017 16:38:11 +0200",
        "Message-ID": "<150401749138.16384.17129327124102881342.stgit@firesoul>",
        "In-Reply-To": "<150401743083.16384.15778781741742858567.stgit@firesoul>",
        "References": "<150401743083.16384.15778781741742858567.stgit@firesoul>",
        "User-Agent": "StGit/0.17.1-dirty",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.14",
        "X-Greylist": "Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.27]);\n\tTue, 29 Aug 2017 14:38:15 +0000 (UTC)",
        "Sender": "netdev-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netdev.vger.kernel.org>",
        "X-Mailing-List": "netdev@vger.kernel.org"
    },
    "content": "This tool xdp_monitor demonstrate how to use the different xdp_redirect\ntracepoints xdp_redirect{,_map}{,_err} from a BPF program.\n\nThe default mode is to only monitor the error counters, to avoid\naffecting the per packet performance. Tracepoints comes with a base\noverhead of 25 nanosec for an attached bpf_prog, and 48 nanosec for\nusing a full perf record (with non-matching filter).  Thus, default\nloading the --stats mode could affect the maximum performance.\n\nThis version of the tool is very simple and count all types of errors\nas one.  It will be natural to extend this later with the different\ntypes of errors that can occur, which should help users quickly\nidentify common mistakes.\n\nBecause the TP_STRUCT was kept in sync all the tracepoints loads the\nsame BPF code.  It would also be natural to extend the map version to\ndemonstrate how the map information could be used.\n\nSigned-off-by: Jesper Dangaard Brouer <brouer@redhat.com>\n---\n samples/bpf/Makefile           |    4 +\n samples/bpf/xdp_monitor_kern.c |   88 ++++++++++++\n samples/bpf/xdp_monitor_user.c |  295 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 387 insertions(+)\n create mode 100644 samples/bpf/xdp_monitor_kern.c\n create mode 100644 samples/bpf/xdp_monitor_user.c",
    "diff": "diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile\nindex f1010fe759fe..cf17c7932a6e 100644\n--- a/samples/bpf/Makefile\n+++ b/samples/bpf/Makefile\n@@ -39,6 +39,7 @@ hostprogs-y += per_socket_stats_example\n hostprogs-y += load_sock_ops\n hostprogs-y += xdp_redirect\n hostprogs-y += xdp_redirect_map\n+hostprogs-y += xdp_monitor\n hostprogs-y += syscall_tp\n \n # Libbpf dependencies\n@@ -83,6 +84,7 @@ test_map_in_map-objs := bpf_load.o $(LIBBPF) test_map_in_map_user.o\n per_socket_stats_example-objs := $(LIBBPF) cookie_uid_helper_example.o\n xdp_redirect-objs := bpf_load.o $(LIBBPF) xdp_redirect_user.o\n xdp_redirect_map-objs := bpf_load.o $(LIBBPF) xdp_redirect_map_user.o\n+xdp_monitor-objs := bpf_load.o $(LIBBPF) xdp_monitor_user.o\n syscall_tp-objs := bpf_load.o $(LIBBPF) syscall_tp_user.o\n \n # Tell kbuild to always build the programs\n@@ -127,6 +129,7 @@ always += tcp_iw_kern.o\n always += tcp_clamp_kern.o\n always += xdp_redirect_kern.o\n always += xdp_redirect_map_kern.o\n+always += xdp_monitor_kern.o\n always += syscall_tp_kern.o\n \n HOSTCFLAGS += -I$(objtree)/usr/include\n@@ -166,6 +169,7 @@ HOSTLOADLIBES_xdp_tx_iptunnel += -lelf\n HOSTLOADLIBES_test_map_in_map += -lelf\n HOSTLOADLIBES_xdp_redirect += -lelf\n HOSTLOADLIBES_xdp_redirect_map += -lelf\n+HOSTLOADLIBES_xdp_monitor += -lelf\n HOSTLOADLIBES_syscall_tp += -lelf\n \n # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:\ndiff --git a/samples/bpf/xdp_monitor_kern.c b/samples/bpf/xdp_monitor_kern.c\nnew file mode 100644\nindex 000000000000..74f3fd8ed729\n--- /dev/null\n+++ b/samples/bpf/xdp_monitor_kern.c\n@@ -0,0 +1,88 @@\n+/* XDP monitor tool, based on tracepoints\n+ *\n+ *  Copyright(c) 2017 Jesper Dangaard Brouer, Red Hat Inc.\n+ */\n+#include <uapi/linux/bpf.h>\n+#include \"bpf_helpers.h\"\n+\n+struct bpf_map_def SEC(\"maps\") redirect_err_cnt = {\n+\t.type = BPF_MAP_TYPE_PERCPU_ARRAY,\n+\t.key_size = sizeof(u32),\n+\t.value_size = sizeof(u64),\n+\t.max_entries = 2,\n+\t/* TODO: have entries for all possible errno's */\n+};\n+\n+/* Tracepoint format: /sys/kernel/debug/tracing/events/xdp/xdp_redirect/format\n+ * Code in:                kernel/include/trace/events/xdp.h\n+ */\n+struct xdp_redirect_ctx {\n+\tunsigned short common_type;\t//\toffset:0;  size:2; signed:0;\n+\tunsigned char common_flags;\t//\toffset:2;  size:1; signed:0;\n+\tunsigned char common_preempt_count;//\toffset:3;  size:1; signed:0;\n+\tint common_pid;\t\t\t//\toffset:4;  size:4; signed:1;\n+\n+\tint prog_id;\t\t\t//\toffset:8;  size:4; signed:1;\n+\tu32 act;\t\t\t//\toffset:12  size:4; signed:0;\n+\tint ifindex;\t\t\t//\toffset:16  size:4; signed:1;\n+\tint err;\t\t\t//\toffset:20  size:4; signed:1;\n+\tint to_ifindex;\t\t\t//\toffset:24  size:4; signed:1;\n+\tu32 map_id;\t\t\t//\toffset:28  size:4; signed:0;\n+\tint map_index;\t\t\t//\toffset:32  size:4; signed:1;\n+};\t\t\t\t\t//\toffset:36\n+\n+enum {\n+\tXDP_REDIRECT_SUCCESS = 0,\n+\tXDP_REDIRECT_ERROR = 1\n+};\n+\n+static __always_inline\n+int xdp_redirect_collect_stat(struct xdp_redirect_ctx *ctx)\n+{\n+\tu32 key = XDP_REDIRECT_ERROR;\n+\tint err = ctx->err;\n+\tu64 *cnt;\n+\n+\tif (!err)\n+\t\tkey = XDP_REDIRECT_SUCCESS;\n+\n+\tcnt  = bpf_map_lookup_elem(&redirect_err_cnt, &key);\n+\tif (!cnt)\n+\t\treturn 0;\n+\t*cnt += 1;\n+\n+\treturn 0; /* Indicate event was filtered (no further processing)*/\n+\t/*\n+\t * Returning 1 here would allow e.g. a perf-record tracepoint\n+\t * to see and record these events, but it doesn't work well\n+\t * in-practice as stopping perf-record also unload this\n+\t * bpf_prog.  Plus, there is additional overhead of doing so.\n+\t */\n+}\n+\n+SEC(\"tracepoint/xdp/xdp_redirect_err\")\n+int trace_xdp_redirect_err(struct xdp_redirect_ctx *ctx)\n+{\n+\treturn xdp_redirect_collect_stat(ctx);\n+}\n+\n+\n+SEC(\"tracepoint/xdp/xdp_redirect_map_err\")\n+int trace_xdp_redirect_map_err(struct xdp_redirect_ctx *ctx)\n+{\n+\treturn xdp_redirect_collect_stat(ctx);\n+}\n+\n+/* Likely unloaded when prog starts */\n+SEC(\"tracepoint/xdp/xdp_redirect\")\n+int trace_xdp_redirect(struct xdp_redirect_ctx *ctx)\n+{\n+\treturn xdp_redirect_collect_stat(ctx);\n+}\n+\n+/* Likely unloaded when prog starts */\n+SEC(\"tracepoint/xdp/xdp_redirect_map\")\n+int trace_xdp_redirect_map(struct xdp_redirect_ctx *ctx)\n+{\n+\treturn xdp_redirect_collect_stat(ctx);\n+}\ndiff --git a/samples/bpf/xdp_monitor_user.c b/samples/bpf/xdp_monitor_user.c\nnew file mode 100644\nindex 000000000000..b51b4f5e3257\n--- /dev/null\n+++ b/samples/bpf/xdp_monitor_user.c\n@@ -0,0 +1,295 @@\n+/* Copyright(c) 2017 Jesper Dangaard Brouer, Red Hat, Inc.\n+ */\n+static const char *__doc__=\n+ \"XDP monitor tool, based on tracepoints\\n\"\n+;\n+\n+static const char *__doc_err_only__=\n+ \" NOTICE: Only tracking XDP redirect errors\\n\"\n+ \"         Enable TX success stats via '--stats'\\n\"\n+ \"         (which comes with a per packet processing overhead)\\n\"\n+;\n+\n+#include <errno.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <stdbool.h>\n+#include <stdint.h>\n+#include <string.h>\n+#include <ctype.h>\n+#include <unistd.h>\n+#include <locale.h>\n+\n+#include <getopt.h>\n+#include <net/if.h>\n+#include <time.h>\n+\n+#include \"libbpf.h\"\n+#include \"bpf_load.h\"\n+#include \"bpf_util.h\"\n+\n+static int verbose = 1;\n+static bool debug = false;\n+\n+static const struct option long_options[] = {\n+\t{\"help\",\tno_argument,\t\tNULL, 'h' },\n+\t{\"debug\",\tno_argument,\t\tNULL, 'D' },\n+\t{\"stats\",\tno_argument,\t\tNULL, 'S' },\n+\t{\"sec\", \trequired_argument,\tNULL, 's' },\n+\t{0, 0, NULL,  0 }\n+};\n+\n+static void usage(char *argv[])\n+{\n+\tint i;\n+\tprintf(\"\\nDOCUMENTATION:\\n%s\\n\", __doc__);\n+\tprintf(\"\\n\");\n+\tprintf(\" Usage: %s (options-see-below)\\n\",\n+\t       argv[0]);\n+\tprintf(\" Listing options:\\n\");\n+\tfor (i = 0; long_options[i].name != 0; i++) {\n+\t\tprintf(\" --%-15s\", long_options[i].name);\n+\t\tif (long_options[i].flag != NULL)\n+\t\t\tprintf(\" flag (internal value:%d)\",\n+\t\t\t       *long_options[i].flag);\n+\t\telse\n+\t\t\tprintf(\"(internal short-option: -%c)\",\n+\t\t\t       long_options[i].val);\n+\t\tprintf(\"\\n\");\n+\t}\n+\tprintf(\"\\n\");\n+}\n+\n+#define NANOSEC_PER_SEC 1000000000 /* 10^9 */\n+__u64 gettime(void)\n+{\n+\tstruct timespec t;\n+\tint res;\n+\n+\tres = clock_gettime(CLOCK_MONOTONIC, &t);\n+\tif (res < 0) {\n+\t\tfprintf(stderr, \"Error with gettimeofday! (%i)\\n\", res);\n+\t\texit(EXIT_FAILURE);\n+\t}\n+\treturn (__u64) t.tv_sec * NANOSEC_PER_SEC + t.tv_nsec;\n+}\n+\n+enum {\n+\tREDIR_SUCCESS = 0,\n+\tREDIR_ERROR = 1,\n+};\n+#define REDIR_RES_MAX 2\n+static const char *redir_names[REDIR_RES_MAX] = {\n+\t[REDIR_SUCCESS]\t= \"Success\",\n+\t[REDIR_ERROR]\t= \"Error\",\n+};\n+static const char *err2str(int err)\n+{\n+\tif (err < REDIR_RES_MAX)\n+\t\treturn redir_names[err];\n+\treturn NULL;\n+}\n+\n+struct record {\n+\t__u64 counter;\n+\t__u64 timestamp;\n+};\n+\n+struct stats_record {\n+\tstruct record xdp_redir[REDIR_RES_MAX];\n+};\n+\n+static void stats_print_headers(bool err_only)\n+{\n+\tif (err_only)\n+\t\tprintf(\"\\n%s\\n\", __doc_err_only__);\n+\n+\tprintf(\"%-14s %-10s %-18s %-9s\\n\",\n+\t       \"XDP_REDIRECT\", \"pps \", \"pps-human-readable\", \"measure-period\");\n+}\n+\n+static void stats_print(struct stats_record *rec,\n+\t\t\tstruct stats_record *prev,\n+\t\t\tbool err_only)\n+{\n+\tint i = 0;\n+\n+\tif (err_only)\n+\t\ti = REDIR_ERROR;\n+\n+\tfor (; i < REDIR_RES_MAX; i++) {\n+\t\tstruct record *r = &rec->xdp_redir[i];\n+\t\tstruct record *p = &prev->xdp_redir[i];\n+\t\t__u64 period  = 0;\n+\t\t__u64 packets = 0;\n+\t\tdouble pps = 0;\n+\t\tdouble period_ = 0;\n+\n+\t\tif (p->timestamp) {\n+\t\t\tpackets = r->counter - p->counter;\n+\t\t\tperiod  = r->timestamp - p->timestamp;\n+\t\t\tif (period > 0) {\n+\t\t\t\tperiod_ = ((double) period / NANOSEC_PER_SEC);\n+\t\t\t\tpps = packets / period_;\n+\t\t\t}\n+\t\t}\n+\n+\t\tprintf(\"%-14s %-10.0f %'-18.0f %f\\n\",\n+\t\t       err2str(i), pps, pps, period_);\n+\t}\n+}\n+\n+static __u64 get_key32_value64_percpu(int fd, __u32 key)\n+{\n+\t/* For percpu maps, userspace gets a value per possible CPU */\n+\tunsigned int nr_cpus = bpf_num_possible_cpus();\n+\t__u64 values[nr_cpus];\n+\t__u64 sum = 0;\n+\tint i;\n+\n+\tif ((bpf_map_lookup_elem(fd, &key, values)) != 0) {\n+\t\tfprintf(stderr,\n+\t\t\t\"ERR: bpf_map_lookup_elem failed key:0x%X\\n\", key);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Sum values from each CPU */\n+\tfor (i = 0; i < nr_cpus; i++) {\n+\t\tsum += values[i];\n+\t}\n+\treturn sum;\n+}\n+\n+static bool stats_collect(int fd, struct stats_record *rec)\n+{\n+\tint i;\n+\n+\t/* TODO: Detect if someone unloaded the perf event_fd's, as\n+\t * this can happen by someone running perf-record -e\n+\t */\n+\n+\tfor (i = 0; i < REDIR_RES_MAX; i++) {\n+\t\trec->xdp_redir[i].timestamp = gettime();\n+\t\trec->xdp_redir[i].counter = get_key32_value64_percpu(fd, i);\n+\t}\n+\treturn true;\n+}\n+\n+static void stats_poll(int interval, bool err_only)\n+{\n+\tstruct stats_record rec, prev;\n+\tint map_fd;\n+\n+\tmemset(&rec, 0, sizeof(rec));\n+\n+\t/* Trick to pretty printf with thousands separators use %' */\n+\tsetlocale(LC_NUMERIC, \"en_US\");\n+\n+\t/* Header */\n+\tif (verbose)\n+\t\tprintf(\"\\n%s\", __doc__);\n+\n+\t/* TODO Need more advanced stats on error types */\n+\tif (verbose)\n+\t\tprintf(\" - Stats map: %s\\n\", map_data[0].name);\n+\tmap_fd = map_data[0].fd;\n+\n+\tstats_print_headers(err_only);\n+\tfflush(stdout);\n+\n+\twhile (1) {\n+\t\tmemcpy(&prev, &rec, sizeof(rec));\n+\t\tstats_collect(map_fd, &rec);\n+\t\tstats_print(&rec, &prev, err_only);\n+\t\tfflush(stdout);\n+\t\tsleep(interval);\n+\t}\n+}\n+\n+void print_bpf_prog_info(void)\n+{\n+\tint i;\n+\n+\t/* Prog info */\n+\tprintf(\"Loaded BPF prog have %d bpf program(s)\\n\", prog_cnt);\n+\tfor (i = 0; i < prog_cnt; i++) {\n+\t\tprintf(\" - prog_fd[%d] = fd(%d)\\n\", i, prog_fd[i]);\n+\t}\n+\n+\t/* Maps info */\n+\tprintf(\"Loaded BPF prog have %d map(s)\\n\", map_data_count);\n+\tfor (i = 0; i < map_data_count; i++) {\n+\t\tchar *name = map_data[i].name;\n+\t\tint fd     = map_data[i].fd;\n+\n+\t\tprintf(\" - map_data[%d] = fd(%d) name:%s\\n\", i, fd, name);\n+\t}\n+\n+\t/* Event info */\n+\tprintf(\"Searching for (max:%d) event file descriptor(s)\\n\", prog_cnt);\n+\tfor (i = 0; i < prog_cnt; i++) {\n+\t\tif (event_fd[i] != -1)\n+\t\t\tprintf(\" - event_fd[%d] = fd(%d)\\n\", i, event_fd[i]);\n+\t}\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tint longindex = 0, opt;\n+\tint ret = EXIT_SUCCESS;\n+\tchar bpf_obj_file[256];\n+\n+\t/* Default settings: */\n+\tbool errors_only = true;\n+\tint interval = 2;\n+\n+\tsnprintf(bpf_obj_file, sizeof(bpf_obj_file), \"%s_kern.o\", argv[0]);\n+\n+\t/* Parse commands line args */\n+\twhile ((opt = getopt_long(argc, argv, \"h\",\n+\t\t\t\t  long_options, &longindex)) != -1) {\n+\t\tswitch (opt) {\n+\t\tcase 'D':\n+\t\t\tdebug = true;\n+\t\t\tbreak;\n+\t\tcase 'S':\n+\t\t\terrors_only = false;\n+\t\t\tbreak;\n+\t\tcase 's':\n+\t\t\tinterval = atoi(optarg);\n+\t\t\tbreak;\n+\t\tcase 'h':\n+\t\tdefault:\n+\t\t\tusage(argv);\n+\t\t\treturn EXIT_FAILURE;\n+\t\t}\n+\t}\n+\n+\tif (load_bpf_file(bpf_obj_file)) {\n+\t\tprintf(\"ERROR - bpf_log_buf: %s\", bpf_log_buf);\n+\t\treturn 1;\n+\t}\n+\tif (!prog_fd[0]) {\n+\t\tprintf(\"ERROR - load_bpf_file: %s\\n\", strerror(errno));\n+\t\treturn 1;\n+\t}\n+\n+\tif (debug) {\n+\t\tprint_bpf_prog_info();\n+\t}\n+\n+\t/* Unload/stop tracepoint event by closing fd's */\n+\tif (errors_only) {\n+\t\t/* The prog_fd[i] and event_fd[i] depend on the\n+\t\t * order the functions was defined in _kern.c\n+\t\t */\n+\t\tclose(event_fd[2]); /* tracepoint/xdp/xdp_redirect */\n+\t\tclose(prog_fd[2]);  /* func: trace_xdp_redirect */\n+\t\tclose(event_fd[3]); /* tracepoint/xdp/xdp_redirect_map */\n+\t\tclose(prog_fd[3]);  /* func: trace_xdp_redirect_map */\n+\t}\n+\n+\tstats_poll(interval, errors_only);\n+\n+\treturn ret;\n+}\n",
    "prefixes": [
        "net-next",
        "7/7"
    ]
}