* Re: [PATCH bpf-next 03/10] tools/bpf: handle __MAX_BPF_(PROG|MAP)_TYPE in switch statements
From: Arnaldo Carvalho de Melo @ 2019-08-28 21:19 UTC (permalink / raw)
To: Julia Kartseva; +Cc: rdna, bpf, ast, daniel, netdev, kernel-team
In-Reply-To: <1895f7dfe2a8067f6397ff565edf20130a28aa91.1567024943.git.hex@fb.com>
Em Wed, Aug 28, 2019 at 02:03:06PM -0700, Julia Kartseva escreveu:
> Add cases to switch statements in probe_load, bpf_prog_type__needs_kver
> bpf_probe_map_type to fix enumeration value not handled in switch
> compilation error.
> prog_type_name array in bpftool/main.h doesn't have __MAX_BPF_PROG_TYPE
> entity, same for map, so probe won't be called.
Shouldn't this be added when adding that __MAX_BPF_PROG_TYPE value to
the enum? Otherwise the build will fail when __MAX_BPF_PROG_TYPE is
added but not handled in the switches.
I.e. the tree should build patch by patch, not just at the end of patch
series.
- Arnaldo
> Signed-off-by: Julia Kartseva <hex@fb.com>
> ---
> tools/lib/bpf/libbpf.c | 1 +
> tools/lib/bpf/libbpf_probes.c | 2 ++
> 2 files changed, 3 insertions(+)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 2233f919dd88..72e6e5eb397f 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -3580,6 +3580,7 @@ static bool bpf_prog_type__needs_kver(enum bpf_prog_type type)
> case BPF_PROG_TYPE_PERF_EVENT:
> case BPF_PROG_TYPE_CGROUP_SYSCTL:
> case BPF_PROG_TYPE_CGROUP_SOCKOPT:
> + case __MAX_BPF_PROG_TYPE:
> return false;
> case BPF_PROG_TYPE_KPROBE:
> default:
> diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
> index 4b0b0364f5fc..8f2ba6a457ac 100644
> --- a/tools/lib/bpf/libbpf_probes.c
> +++ b/tools/lib/bpf/libbpf_probes.c
> @@ -102,6 +102,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
> case BPF_PROG_TYPE_FLOW_DISSECTOR:
> case BPF_PROG_TYPE_CGROUP_SYSCTL:
> case BPF_PROG_TYPE_CGROUP_SOCKOPT:
> + case __MAX_BPF_PROG_TYPE:
> default:
> break;
> }
> @@ -250,6 +251,7 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
> case BPF_MAP_TYPE_XSKMAP:
> case BPF_MAP_TYPE_SOCKHASH:
> case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
> + case __MAX_BPF_MAP_TYPE:
> default:
> break;
> }
> --
> 2.17.1
--
- Arnaldo
^ permalink raw reply
* Re: [PATCH v2 0/2] Update ethernet compatible string for SiFive FU540
From: David Miller @ 2019-08-28 21:06 UTC (permalink / raw)
To: yash.shah
Cc: netdev, devicetree, linux-kernel, linux-riscv, robh+dt,
mark.rutland, nicolas.ferre, palmer, paul.walmsley, ynezz,
sachin.ghadi
In-Reply-To: <1566882364-23891-1-git-send-email-yash.shah@sifive.com>
From: Yash Shah <yash.shah@sifive.com>
Date: Tue, 27 Aug 2019 10:36:02 +0530
> This patch series renames the compatible property to a more appropriate
> string. The patchset is based on Linux-5.3-rc6 and tested on SiFive
> Unleashed board
You should always base changes off of "net" or "net-next" and be explicitly
in your Subject lines which of those two trees your changes are for f.e.:
Subject: [PATCH v2 net-next N/M] ...
>
> Change history:
> Since v1:
> - Dropped PATCH3 because it's already merged
> - Change the reference url in the patch descriptions to point to a
> 'lore.kernel.org' link instead of 'lkml.org'
Series applied to 'net'.
^ permalink raw reply
* [PATCH bpf-next 09/10] tools/bpftool: use libbpf_(prog|map)_type_to_str helpers
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Replace lookup in (prog|map)_type_name arrays with
libbpf_(prog|map)_type_to_str helpers.
Use __MAX_BPF_(PROG|MAP)_TYPE enum values as loop bounds.
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/bpf/bpftool/feature.c | 47 ++++++++++++++--------
tools/bpf/bpftool/main.h | 33 ---------------
tools/bpf/bpftool/map.c | 80 ++++++++++---------------------------
tools/bpf/bpftool/prog.c | 11 ++---
4 files changed, 59 insertions(+), 112 deletions(-)
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index 03bdc5b3ac49..e9416005e721 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -462,7 +462,7 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
const char *define_prefix, __u32 ifindex)
{
char feat_name[128], plain_desc[128], define_name[128];
- const char *plain_comment = "eBPF program_type ";
+ const char *ptype_name, *plain_comment = "eBPF program_type ";
size_t maxlen;
bool res;
@@ -480,16 +480,21 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
supported_types[prog_type] |= res;
+ if (libbpf_prog_type_to_str(prog_type, &ptype_name)) {
+ p_info("program type name does not exist");
+ return;
+ }
+
maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
- if (strlen(prog_type_name[prog_type]) > maxlen) {
+ if (strlen(ptype_name) > maxlen) {
p_info("program type name too long");
return;
}
- sprintf(feat_name, "have_%s_prog_type", prog_type_name[prog_type]);
- sprintf(define_name, "%s_prog_type", prog_type_name[prog_type]);
+ sprintf(feat_name, "have_%s_prog_type", ptype_name);
+ sprintf(define_name, "%s_prog_type", ptype_name);
uppercase(define_name, sizeof(define_name));
- sprintf(plain_desc, "%s%s", plain_comment, prog_type_name[prog_type]);
+ sprintf(plain_desc, "%s%s", plain_comment, ptype_name);
print_bool_feature(feat_name, plain_desc, define_name, res,
define_prefix);
}
@@ -499,22 +504,27 @@ probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
__u32 ifindex)
{
char feat_name[128], plain_desc[128], define_name[128];
- const char *plain_comment = "eBPF map_type ";
+ const char *mtype_name, *plain_comment = "eBPF map_type ";
size_t maxlen;
bool res;
res = bpf_probe_map_type(map_type, ifindex);
+ if (libbpf_map_type_to_str(map_type, &mtype_name)) {
+ p_info("map type name does not exist");
+ return;
+ }
+
maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
- if (strlen(map_type_name[map_type]) > maxlen) {
+ if (strlen(mtype_name) > maxlen) {
p_info("map type name too long");
return;
}
- sprintf(feat_name, "have_%s_map_type", map_type_name[map_type]);
- sprintf(define_name, "%s_map_type", map_type_name[map_type]);
+ sprintf(feat_name, "have_%s_map_type", mtype_name);
+ sprintf(define_name, "%s_map_type", mtype_name);
uppercase(define_name, sizeof(define_name));
- sprintf(plain_desc, "%s%s", plain_comment, map_type_name[map_type]);
+ sprintf(plain_desc, "%s%s", plain_comment, mtype_name);
print_bool_feature(feat_name, plain_desc, define_name, res,
define_prefix);
}
@@ -523,11 +533,16 @@ static void
probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
const char *define_prefix, __u32 ifindex)
{
- const char *ptype_name = prog_type_name[prog_type];
+ const char *ptype_name;
char feat_name[128];
unsigned int id;
bool res;
+ if (libbpf_prog_type_to_str(prog_type, &ptype_name)) {
+ p_info("map type name does not exist");
+ return;
+ }
+
if (ifindex)
/* Only test helpers for offload-able program types */
switch (prog_type) {
@@ -689,7 +704,7 @@ static int do_probe(int argc, char **argv)
"/*** eBPF program types ***/",
define_prefix);
- for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
+ for (i = BPF_PROG_TYPE_UNSPEC + 1; i < __MAX_BPF_PROG_TYPE; i++)
probe_prog_type(i, supported_types, define_prefix, ifindex);
print_end_then_start_section("map_types",
@@ -697,7 +712,7 @@ static int do_probe(int argc, char **argv)
"/*** eBPF map types ***/",
define_prefix);
- for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
+ for (i = BPF_MAP_TYPE_UNSPEC + 1; i < __MAX_BPF_MAP_TYPE; i++)
probe_map_type(i, define_prefix, ifindex);
print_end_then_start_section("helpers",
@@ -720,9 +735,9 @@ static int do_probe(int argc, char **argv)
" %sBPF__PROG_TYPE_ ## prog_type ## __HELPER_ ## helper\n",
define_prefix, define_prefix, define_prefix,
define_prefix);
- for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
- probe_helpers_for_progtype(i, supported_types[i],
- define_prefix, ifindex);
+ for (i = BPF_PROG_TYPE_UNSPEC + 1; i <= __MAX_BPF_PROG_TYPE; i++)
+ probe_helpers_for_progtype(i, supported_types[i], define_prefix,
+ ifindex);
exit_close_json:
if (json_output) {
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index af9ad56c303a..bb840d900fb4 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -48,39 +48,6 @@
"\t {-m|--mapcompat} | {-n|--nomount} }"
#define HELP_SPEC_MAP \
"MAP := { id MAP_ID | pinned FILE }"
-
-static const char * const prog_type_name[] = {
- [BPF_PROG_TYPE_UNSPEC] = "unspec",
- [BPF_PROG_TYPE_SOCKET_FILTER] = "socket_filter",
- [BPF_PROG_TYPE_KPROBE] = "kprobe",
- [BPF_PROG_TYPE_SCHED_CLS] = "sched_cls",
- [BPF_PROG_TYPE_SCHED_ACT] = "sched_act",
- [BPF_PROG_TYPE_TRACEPOINT] = "tracepoint",
- [BPF_PROG_TYPE_XDP] = "xdp",
- [BPF_PROG_TYPE_PERF_EVENT] = "perf_event",
- [BPF_PROG_TYPE_CGROUP_SKB] = "cgroup_skb",
- [BPF_PROG_TYPE_CGROUP_SOCK] = "cgroup_sock",
- [BPF_PROG_TYPE_LWT_IN] = "lwt_in",
- [BPF_PROG_TYPE_LWT_OUT] = "lwt_out",
- [BPF_PROG_TYPE_LWT_XMIT] = "lwt_xmit",
- [BPF_PROG_TYPE_SOCK_OPS] = "sock_ops",
- [BPF_PROG_TYPE_SK_SKB] = "sk_skb",
- [BPF_PROG_TYPE_CGROUP_DEVICE] = "cgroup_device",
- [BPF_PROG_TYPE_SK_MSG] = "sk_msg",
- [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint",
- [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr",
- [BPF_PROG_TYPE_LWT_SEG6LOCAL] = "lwt_seg6local",
- [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2",
- [BPF_PROG_TYPE_SK_REUSEPORT] = "sk_reuseport",
- [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector",
- [BPF_PROG_TYPE_CGROUP_SYSCTL] = "cgroup_sysctl",
- [BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE] = "raw_tracepoint_writable",
- [BPF_PROG_TYPE_CGROUP_SOCKOPT] = "cgroup_sockopt",
-};
-
-extern const char * const map_type_name[];
-extern const size_t map_type_name_size;
-
enum bpf_obj_type {
BPF_OBJ_UNKNOWN,
BPF_OBJ_PROG,
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index de61d73b9030..ca3760b5c33e 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -16,42 +16,12 @@
#include <sys/stat.h>
#include <bpf.h>
+#include <libbpf.h>
#include "btf.h"
#include "json_writer.h"
#include "main.h"
-const char * const map_type_name[] = {
- [BPF_MAP_TYPE_UNSPEC] = "unspec",
- [BPF_MAP_TYPE_HASH] = "hash",
- [BPF_MAP_TYPE_ARRAY] = "array",
- [BPF_MAP_TYPE_PROG_ARRAY] = "prog_array",
- [BPF_MAP_TYPE_PERF_EVENT_ARRAY] = "perf_event_array",
- [BPF_MAP_TYPE_PERCPU_HASH] = "percpu_hash",
- [BPF_MAP_TYPE_PERCPU_ARRAY] = "percpu_array",
- [BPF_MAP_TYPE_STACK_TRACE] = "stack_trace",
- [BPF_MAP_TYPE_CGROUP_ARRAY] = "cgroup_array",
- [BPF_MAP_TYPE_LRU_HASH] = "lru_hash",
- [BPF_MAP_TYPE_LRU_PERCPU_HASH] = "lru_percpu_hash",
- [BPF_MAP_TYPE_LPM_TRIE] = "lpm_trie",
- [BPF_MAP_TYPE_ARRAY_OF_MAPS] = "array_of_maps",
- [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps",
- [BPF_MAP_TYPE_DEVMAP] = "devmap",
- [BPF_MAP_TYPE_DEVMAP_HASH] = "devmap_hash",
- [BPF_MAP_TYPE_SOCKMAP] = "sockmap",
- [BPF_MAP_TYPE_CPUMAP] = "cpumap",
- [BPF_MAP_TYPE_XSKMAP] = "xskmap",
- [BPF_MAP_TYPE_SOCKHASH] = "sockhash",
- [BPF_MAP_TYPE_CGROUP_STORAGE] = "cgroup_storage",
- [BPF_MAP_TYPE_REUSEPORT_SOCKARRAY] = "reuseport_sockarray",
- [BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE] = "percpu_cgroup_storage",
- [BPF_MAP_TYPE_QUEUE] = "queue",
- [BPF_MAP_TYPE_STACK] = "stack",
- [BPF_MAP_TYPE_SK_STORAGE] = "sk_storage",
-};
-
-const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
-
static bool map_is_per_cpu(__u32 type)
{
return type == BPF_MAP_TYPE_PERCPU_HASH ||
@@ -71,17 +41,6 @@ static bool map_is_map_of_progs(__u32 type)
return type == BPF_MAP_TYPE_PROG_ARRAY;
}
-static int map_type_from_str(const char *type)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(map_type_name); i++)
- /* Don't allow prefixing in case of possible future shadowing */
- if (map_type_name[i] && !strcmp(map_type_name[i], type))
- return i;
- return -1;
-}
-
static void *alloc_value(struct bpf_map_info *info)
{
if (map_is_per_cpu(info->type))
@@ -481,6 +440,8 @@ static int parse_elem(char **argv, struct bpf_map_info *info,
static int show_map_close_json(int fd, struct bpf_map_info *info)
{
+ const char *ptype_name, *mtype_name;
+ enum bpf_prog_type prog_type;
char *memlock, *frozen_str;
int frozen = 0;
@@ -488,11 +449,10 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
frozen_str = get_fdinfo(fd, "frozen");
jsonw_start_object(json_wtr);
-
jsonw_uint_field(json_wtr, "id", info->id);
- if (info->type < ARRAY_SIZE(map_type_name))
- jsonw_string_field(json_wtr, "type",
- map_type_name[info->type]);
+
+ if (!libbpf_map_type_to_str(info->type, &mtype_name))
+ jsonw_string_field(json_wtr, "type", mtype_name);
else
jsonw_uint_field(json_wtr, "type", info->type);
@@ -517,11 +477,11 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
char *owner_jited = get_fdinfo(fd, "owner_jited");
if (owner_prog_type) {
- unsigned int prog_type = atoi(owner_prog_type);
+ prog_type = atoi(owner_prog_type);
- if (prog_type < ARRAY_SIZE(prog_type_name))
+ if (!libbpf_prog_type_to_str(prog_type, &ptype_name))
jsonw_string_field(json_wtr, "owner_prog_type",
- prog_type_name[prog_type]);
+ ptype_name);
else
jsonw_uint_field(json_wtr, "owner_prog_type",
prog_type);
@@ -563,6 +523,7 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
static int show_map_close_plain(int fd, struct bpf_map_info *info)
{
+ const char *mtype_name, *ptype_name;
char *memlock, *frozen_str;
int frozen = 0;
@@ -570,8 +531,9 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
frozen_str = get_fdinfo(fd, "frozen");
printf("%u: ", info->id);
- if (info->type < ARRAY_SIZE(map_type_name))
- printf("%s ", map_type_name[info->type]);
+
+ if (!libbpf_map_type_to_str(info->type, &mtype_name))
+ printf("%s ", mtype_name);
else
printf("type %u ", info->type);
@@ -596,10 +558,8 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
printf("\n\t");
if (owner_prog_type) {
unsigned int prog_type = atoi(owner_prog_type);
-
- if (prog_type < ARRAY_SIZE(prog_type_name))
- printf("owner_prog_type %s ",
- prog_type_name[prog_type]);
+ if (!libbpf_prog_type_to_str(prog_type, &ptype_name))
+ printf("owner_prog_type %s ", ptype_name);
else
printf("owner_prog_type %d ", prog_type);
}
@@ -772,6 +732,7 @@ static int do_dump(int argc, char **argv)
unsigned int num_elems = 0;
__u32 len = sizeof(info);
json_writer_t *btf_wtr;
+ const char *mtype_name;
struct btf *btf = NULL;
int err;
int fd;
@@ -813,10 +774,14 @@ static int do_dump(int argc, char **argv)
}
}
+ if (libbpf_map_type_to_str(info.type, &mtype_name)) {
+ p_info("map type name does not exist");
+ goto exit_free;
+ }
if (info.type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY &&
info.value_size != 8)
p_info("Warning: cannot read values from %s map with value_size != 8",
- map_type_name[info.type]);
+ mtype_name);
while (true) {
err = bpf_map_get_next_key(fd, prev_key, key);
if (err) {
@@ -1150,8 +1115,7 @@ static int do_create(int argc, char **argv)
return -1;
}
- attr.map_type = map_type_from_str(*argv);
- if ((int)attr.map_type < 0) {
+ if (libbpf_map_type_from_str(*argv, &attr.map_type)) {
p_err("unrecognized map type: %s", *argv);
return -1;
}
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 66f04a4846a5..8bbb24339a52 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -196,13 +196,13 @@ static void show_prog_maps(int fd, u32 num_maps)
static void print_prog_json(struct bpf_prog_info *info, int fd)
{
+ const char *ptype_name;
char *memlock;
jsonw_start_object(json_wtr);
jsonw_uint_field(json_wtr, "id", info->id);
- if (info->type < ARRAY_SIZE(prog_type_name))
- jsonw_string_field(json_wtr, "type",
- prog_type_name[info->type]);
+ if (!libbpf_prog_type_to_str(info->type, &ptype_name))
+ jsonw_string_field(json_wtr, "type", ptype_name);
else
jsonw_uint_field(json_wtr, "type", info->type);
@@ -270,11 +270,12 @@ static void print_prog_json(struct bpf_prog_info *info, int fd)
static void print_prog_plain(struct bpf_prog_info *info, int fd)
{
+ const char *ptype_name;
char *memlock;
printf("%u: ", info->id);
- if (info->type < ARRAY_SIZE(prog_type_name))
- printf("%s ", prog_type_name[info->type]);
+ if (!libbpf_prog_type_to_str(info->type, &ptype_name))
+ printf("%s ", ptype_name);
else
printf("type %u ", info->type);
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 10/10] tools/bpftool: use libbpf_attach_type_to_str helper
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Replace lookup in `attach_type_strings` with
libbpf_attach_type_to_str helper for cgroup (cgroup.c)
and non-cgroup (prog.c) attach types.
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/bpf/bpftool/cgroup.c | 60 +++++++++++++++++++++-----------------
tools/bpf/bpftool/prog.c | 20 +++++++------
2 files changed, 45 insertions(+), 35 deletions(-)
diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c
index 1ef45e55039e..1b53218b06e7 100644
--- a/tools/bpf/bpftool/cgroup.c
+++ b/tools/bpf/bpftool/cgroup.c
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <bpf.h>
+#include <libbpf.h>
#include "main.h"
@@ -31,35 +32,37 @@
static unsigned int query_flags;
-static const char * const attach_type_strings[] = {
- [BPF_CGROUP_INET_INGRESS] = "ingress",
- [BPF_CGROUP_INET_EGRESS] = "egress",
- [BPF_CGROUP_INET_SOCK_CREATE] = "sock_create",
- [BPF_CGROUP_SOCK_OPS] = "sock_ops",
- [BPF_CGROUP_DEVICE] = "device",
- [BPF_CGROUP_INET4_BIND] = "bind4",
- [BPF_CGROUP_INET6_BIND] = "bind6",
- [BPF_CGROUP_INET4_CONNECT] = "connect4",
- [BPF_CGROUP_INET6_CONNECT] = "connect6",
- [BPF_CGROUP_INET4_POST_BIND] = "post_bind4",
- [BPF_CGROUP_INET6_POST_BIND] = "post_bind6",
- [BPF_CGROUP_UDP4_SENDMSG] = "sendmsg4",
- [BPF_CGROUP_UDP6_SENDMSG] = "sendmsg6",
- [BPF_CGROUP_SYSCTL] = "sysctl",
- [BPF_CGROUP_UDP4_RECVMSG] = "recvmsg4",
- [BPF_CGROUP_UDP6_RECVMSG] = "recvmsg6",
- [BPF_CGROUP_GETSOCKOPT] = "getsockopt",
- [BPF_CGROUP_SETSOCKOPT] = "setsockopt",
- [__MAX_BPF_ATTACH_TYPE] = NULL,
+static const enum bpf_attach_type cgroup_attach_types[] = {
+ BPF_CGROUP_INET_INGRESS,
+ BPF_CGROUP_INET_EGRESS,
+ BPF_CGROUP_INET_SOCK_CREATE,
+ BPF_CGROUP_SOCK_OPS,
+ BPF_CGROUP_DEVICE,
+ BPF_CGROUP_INET4_BIND,
+ BPF_CGROUP_INET6_BIND,
+ BPF_CGROUP_INET4_CONNECT,
+ BPF_CGROUP_INET6_CONNECT,
+ BPF_CGROUP_INET4_POST_BIND,
+ BPF_CGROUP_INET6_POST_BIND,
+ BPF_CGROUP_UDP4_SENDMSG,
+ BPF_CGROUP_UDP6_SENDMSG,
+ BPF_CGROUP_SYSCTL,
+ BPF_CGROUP_UDP4_RECVMSG,
+ BPF_CGROUP_UDP6_RECVMSG,
+ BPF_CGROUP_GETSOCKOPT,
+ BPF_CGROUP_SETSOCKOPT,
};
static enum bpf_attach_type parse_attach_type(const char *str)
{
enum bpf_attach_type type;
+ const char *atype_str;
+ unsigned int i;
- for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
- if (attach_type_strings[type] &&
- is_prefix(str, attach_type_strings[type]))
+ for (i = 0; i < ARRAY_SIZE(cgroup_attach_types); i++) {
+ type = cgroup_attach_types[i];
+ if (!libbpf_attach_type_to_str(type, &atype_str) &&
+ is_prefix(str, atype_str))
return type;
}
@@ -120,7 +123,7 @@ static int count_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type)
static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
int level)
{
- const char *attach_flags_str;
+ const char *attach_flags_str, *atype_str;
__u32 prog_ids[1024] = {0};
__u32 prog_cnt, iter;
__u32 attach_flags;
@@ -136,6 +139,11 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
if (prog_cnt == 0)
return 0;
+ ret = libbpf_attach_type_to_str(type, &atype_str);
+
+ if (ret)
+ return 0;
+
switch (attach_flags) {
case BPF_F_ALLOW_MULTI:
attach_flags_str = "multi";
@@ -152,8 +160,8 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
}
for (iter = 0; iter < prog_cnt; iter++)
- show_bpf_prog(prog_ids[iter], attach_type_strings[type],
- attach_flags_str, level);
+ show_bpf_prog(prog_ids[iter], atype_str, attach_flags_str,
+ level);
return 0;
}
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 8bbb24339a52..4dfec67e22fa 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -25,21 +25,23 @@
#include "main.h"
#include "xlated_dumper.h"
-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,
+static const enum bpf_attach_type attach_types[] = {
+ BPF_SK_SKB_STREAM_PARSER,
+ BPF_SK_SKB_STREAM_VERDICT,
+ BPF_SK_MSG_VERDICT,
+ BPF_FLOW_DISSECTOR,
};
static enum bpf_attach_type parse_attach_type(const char *str)
{
enum bpf_attach_type type;
+ const char *atype_str;
+ unsigned int i;
- for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
- if (attach_type_strings[type] &&
- is_prefix(str, attach_type_strings[type]))
+ for (i = 0; type < ARRAY_SIZE(attach_types); i++) {
+ type = attach_types[i];
+ if (!libbpf_attach_type_to_str(type, &atype_str) &&
+ is_prefix(str, atype_str))
return type;
}
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 08/10] selftests/bpf: rename test_section_names to test_section_and_type_names
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Change the test name after extending it with enum stringification
helpers.
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/testing/selftests/bpf/Makefile | 2 +-
.../bpf/test_section_and_type_names.c | 378 ++++++++++++++++++
.../selftests/bpf/test_section_names.c | 378 ------------------
3 files changed, 379 insertions(+), 379 deletions(-)
create mode 100644 tools/testing/selftests/bpf/test_section_and_type_names.c
delete mode 100644 tools/testing/selftests/bpf/test_section_names.c
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 1faad0c3c3c9..8212a6240297 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -26,7 +26,7 @@ LDLIBS += -lcap -lelf -lrt -lpthread
TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \
- test_cgroup_storage test_select_reuseport test_section_names \
+ test_cgroup_storage test_select_reuseport test_section_and_type_names \
test_netcnt test_tcpnotify_user test_sock_fields test_sysctl test_hashmap \
test_btf_dump test_cgroup_attach xdping test_sockopt test_sockopt_sk \
test_sockopt_multi test_sockopt_inherit test_tcp_rtt
diff --git a/tools/testing/selftests/bpf/test_section_and_type_names.c b/tools/testing/selftests/bpf/test_section_and_type_names.c
new file mode 100644
index 000000000000..564585a07592
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_section_and_type_names.c
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018 Facebook
+
+#include <err.h>
+#include <bpf/libbpf.h>
+
+#include "bpf_util.h"
+
+struct sec_name_test {
+ const char sec_name[32];
+ struct {
+ int rc;
+ enum bpf_prog_type prog_type;
+ enum bpf_attach_type expected_attach_type;
+ } expected_load;
+ struct {
+ int rc;
+ enum bpf_attach_type attach_type;
+ } expected_attach;
+};
+
+static struct sec_name_test tests[] = {
+ {"InvAliD", {-EINVAL, 0, 0}, {-EINVAL, 0} },
+ {"cgroup", {-EINVAL, 0, 0}, {-EINVAL, 0} },
+ {"socket", {0, BPF_PROG_TYPE_SOCKET_FILTER, 0}, {-EINVAL, 0} },
+ {"kprobe/", {0, BPF_PROG_TYPE_KPROBE, 0}, {-EINVAL, 0} },
+ {"kretprobe/", {0, BPF_PROG_TYPE_KPROBE, 0}, {-EINVAL, 0} },
+ {"classifier", {0, BPF_PROG_TYPE_SCHED_CLS, 0}, {-EINVAL, 0} },
+ {"action", {0, BPF_PROG_TYPE_SCHED_ACT, 0}, {-EINVAL, 0} },
+ {"tracepoint/", {0, BPF_PROG_TYPE_TRACEPOINT, 0}, {-EINVAL, 0} },
+ {
+ "raw_tracepoint/",
+ {0, BPF_PROG_TYPE_RAW_TRACEPOINT, 0},
+ {-EINVAL, 0},
+ },
+ {"xdp", {0, BPF_PROG_TYPE_XDP, 0}, {-EINVAL, 0} },
+ {"perf_event", {0, BPF_PROG_TYPE_PERF_EVENT, 0}, {-EINVAL, 0} },
+ {"lwt_in", {0, BPF_PROG_TYPE_LWT_IN, 0}, {-EINVAL, 0} },
+ {"lwt_out", {0, BPF_PROG_TYPE_LWT_OUT, 0}, {-EINVAL, 0} },
+ {"lwt_xmit", {0, BPF_PROG_TYPE_LWT_XMIT, 0}, {-EINVAL, 0} },
+ {"lwt_seg6local", {0, BPF_PROG_TYPE_LWT_SEG6LOCAL, 0}, {-EINVAL, 0} },
+ {
+ "cgroup_skb/ingress",
+ {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
+ {0, BPF_CGROUP_INET_INGRESS},
+ },
+ {
+ "cgroup_skb/egress",
+ {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
+ {0, BPF_CGROUP_INET_EGRESS},
+ },
+ {"cgroup/skb", {0, BPF_PROG_TYPE_CGROUP_SKB, 0}, {-EINVAL, 0} },
+ {
+ "cgroup/sock",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK, 0},
+ {0, BPF_CGROUP_INET_SOCK_CREATE},
+ },
+ {
+ "cgroup/post_bind4",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET4_POST_BIND},
+ {0, BPF_CGROUP_INET4_POST_BIND},
+ },
+ {
+ "cgroup/post_bind6",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET6_POST_BIND},
+ {0, BPF_CGROUP_INET6_POST_BIND},
+ },
+ {
+ "cgroup/dev",
+ {0, BPF_PROG_TYPE_CGROUP_DEVICE, 0},
+ {0, BPF_CGROUP_DEVICE},
+ },
+ {"sockops", {0, BPF_PROG_TYPE_SOCK_OPS, 0}, {0, BPF_CGROUP_SOCK_OPS} },
+ {
+ "sk_skb/stream_parser",
+ {0, BPF_PROG_TYPE_SK_SKB, 0},
+ {0, BPF_SK_SKB_STREAM_PARSER},
+ },
+ {
+ "sk_skb/stream_verdict",
+ {0, BPF_PROG_TYPE_SK_SKB, 0},
+ {0, BPF_SK_SKB_STREAM_VERDICT},
+ },
+ {"sk_skb", {0, BPF_PROG_TYPE_SK_SKB, 0}, {-EINVAL, 0} },
+ {"sk_msg", {0, BPF_PROG_TYPE_SK_MSG, 0}, {0, BPF_SK_MSG_VERDICT} },
+ {"lirc_mode2", {0, BPF_PROG_TYPE_LIRC_MODE2, 0}, {0, BPF_LIRC_MODE2} },
+ {
+ "flow_dissector",
+ {0, BPF_PROG_TYPE_FLOW_DISSECTOR, 0},
+ {0, BPF_FLOW_DISSECTOR},
+ },
+ {
+ "cgroup/bind4",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND},
+ {0, BPF_CGROUP_INET4_BIND},
+ },
+ {
+ "cgroup/bind6",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND},
+ {0, BPF_CGROUP_INET6_BIND},
+ },
+ {
+ "cgroup/connect4",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_CONNECT},
+ {0, BPF_CGROUP_INET4_CONNECT},
+ },
+ {
+ "cgroup/connect6",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT},
+ {0, BPF_CGROUP_INET6_CONNECT},
+ },
+ {
+ "cgroup/sendmsg4",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_SENDMSG},
+ {0, BPF_CGROUP_UDP4_SENDMSG},
+ },
+ {
+ "cgroup/sendmsg6",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
+ {0, BPF_CGROUP_UDP6_SENDMSG},
+ },
+ {
+ "cgroup/recvmsg4",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
+ {0, BPF_CGROUP_UDP4_RECVMSG},
+ },
+ {
+ "cgroup/recvmsg6",
+ {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
+ {0, BPF_CGROUP_UDP6_RECVMSG},
+ },
+ {
+ "cgroup/sysctl",
+ {0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
+ {0, BPF_CGROUP_SYSCTL},
+ },
+ {
+ "cgroup/getsockopt",
+ {0, BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_GETSOCKOPT},
+ {0, BPF_CGROUP_GETSOCKOPT},
+ },
+ {
+ "cgroup/setsockopt",
+ {0, BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_SETSOCKOPT},
+ {0, BPF_CGROUP_SETSOCKOPT},
+ },
+};
+
+static int test_prog_type_by_name(const struct sec_name_test *test)
+{
+ enum bpf_attach_type expected_attach_type;
+ enum bpf_prog_type prog_type;
+ int rc;
+
+ rc = libbpf_prog_type_by_name(test->sec_name, &prog_type,
+ &expected_attach_type);
+
+ if (rc != test->expected_load.rc) {
+ warnx("prog: unexpected rc=%d for %s", rc, test->sec_name);
+ return -1;
+ }
+
+ if (rc)
+ return 0;
+
+ if (prog_type != test->expected_load.prog_type) {
+ warnx("prog: unexpected prog_type=%d for %s", prog_type,
+ test->sec_name);
+ return -1;
+ }
+
+ if (expected_attach_type != test->expected_load.expected_attach_type) {
+ warnx("prog: unexpected expected_attach_type=%d for %s",
+ expected_attach_type, test->sec_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int test_attach_type_by_name(const struct sec_name_test *test)
+{
+ enum bpf_attach_type attach_type;
+ int rc;
+
+ rc = libbpf_attach_type_by_name(test->sec_name, &attach_type);
+
+ if (rc != test->expected_attach.rc) {
+ warnx("attach: unexpected rc=%d for %s", rc, test->sec_name);
+ return -1;
+ }
+
+ if (rc)
+ return 0;
+
+ if (attach_type != test->expected_attach.attach_type) {
+ warnx("attach: unexpected attach_type=%d for %s", attach_type,
+ test->sec_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int test_prog_type_from_to_str(void)
+{
+ enum bpf_prog_type type, actual_type;
+ const char *str;
+ int rc;
+
+ for (type = BPF_PROG_TYPE_UNSPEC; type < __MAX_BPF_PROG_TYPE; type++) {
+ rc = libbpf_prog_type_to_str(type, &str);
+ if (rc) {
+ warnx("prog_type_to_str: unexpected rc=%d for type %d",
+ rc, type);
+ return rc;
+ }
+
+ rc = libbpf_prog_type_from_str(str, &actual_type);
+ if (rc) {
+ warnx("prog_type_from_str: unexpected rc=%d for str %s",
+ rc, str);
+ return rc;
+ }
+
+ if (actual_type != type) {
+ warnx("prog: unexpected prog_type for str %s, %d != %d",
+ str, actual_type, type);
+ return -EINVAL;
+ }
+ }
+
+ rc = libbpf_prog_type_to_str(__MAX_BPF_PROG_TYPE, &str);
+ if (!rc) {
+ warnx("prog: unexpected result for __MAX_BPF_PROG_TYPE");
+ return -EINVAL;
+ }
+
+ rc = libbpf_prog_type_from_str("NonExistent", &type);
+ if (!rc) {
+ warnx("prog: unexpected result for non existent key");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int test_map_type_from_to_str(void)
+{
+ enum bpf_map_type type, actual_type;
+ const char *str;
+ int rc;
+
+ for (type = BPF_MAP_TYPE_UNSPEC; type < __MAX_BPF_MAP_TYPE; type++) {
+ rc = libbpf_map_type_to_str(type, &str);
+ if (rc) {
+ warnx("map_type_to_str: unexpected rc=%d for type %d",
+ rc, type);
+ return rc;
+ }
+
+ rc = libbpf_map_type_from_str(str, &actual_type);
+ if (rc) {
+ warnx("map_type_from_str: unexpected rc=%d for str %s",
+ rc, str);
+ return rc;
+ }
+
+ if (actual_type != type) {
+ warnx("map: unexpected map_type for str %s, %d != %d",
+ str, actual_type, type);
+ return -EINVAL;
+ }
+ }
+
+ rc = libbpf_map_type_to_str(__MAX_BPF_MAP_TYPE, &str);
+ if (!rc) {
+ warnx("map: unexpected result for __MAX_BPF_MAP_TYPE");
+ return -EINVAL;
+ }
+
+ rc = libbpf_map_type_from_str("NonExistent", &type);
+ if (!rc) {
+ warnx("map: unexpected result for non existent key");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int test_attach_type_from_to_str(void)
+{
+ enum bpf_attach_type type, actual_type;
+ const char *str;
+ int rc;
+
+ for (type = BPF_CGROUP_INET_INGRESS; type < __MAX_BPF_ATTACH_TYPE;
+ type++) {
+ rc = libbpf_attach_type_to_str(type, &str);
+ if (rc) {
+ warnx("attach: unexpected rc=%d for type %d",
+ rc, type);
+ return rc;
+ }
+
+ rc = libbpf_attach_type_from_str(str, &actual_type);
+ if (rc) {
+ warnx("attach: unexpected rc=%d for str %s",
+ rc, str);
+ return rc;
+ }
+
+ if (actual_type != type) {
+ warnx("attach: unexpected type for str %s, %d != %d",
+ str, actual_type, type);
+ return -EINVAL;
+ }
+ }
+
+ rc = libbpf_attach_type_to_str(__MAX_BPF_ATTACH_TYPE, &str);
+ if (!rc) {
+ warnx("attach: unexpected result for __MAX_BPF_ATTACH_TYPE");
+ return -EINVAL;
+ }
+
+ rc = libbpf_attach_type_from_str("NonExistent", &type);
+ if (!rc) {
+ warnx("attach: unexpected result for non existent key");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int run_sec_name_test_case(const struct sec_name_test *test)
+{
+ if (test_prog_type_by_name(test))
+ return -1;
+ if (test_attach_type_by_name(test))
+ return -1;
+ return 0;
+}
+
+static int run_tests(void)
+{
+ int passes = 0;
+ int fails = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ if (run_sec_name_test_case(&tests[i]))
+ ++fails;
+ else
+ ++passes;
+ }
+
+ if (test_prog_type_from_to_str())
+ ++fails;
+ else
+ ++passes;
+
+ if (test_map_type_from_to_str())
+ ++fails;
+ else
+ ++passes;
+
+ if (test_attach_type_from_to_str())
+ ++fails;
+ else
+ ++passes;
+ printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
+ return fails ? -1 : 0;
+}
+
+int main(int argc, char **argv)
+{
+ return run_tests();
+}
diff --git a/tools/testing/selftests/bpf/test_section_names.c b/tools/testing/selftests/bpf/test_section_names.c
deleted file mode 100644
index 564585a07592..000000000000
--- a/tools/testing/selftests/bpf/test_section_names.c
+++ /dev/null
@@ -1,378 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018 Facebook
-
-#include <err.h>
-#include <bpf/libbpf.h>
-
-#include "bpf_util.h"
-
-struct sec_name_test {
- const char sec_name[32];
- struct {
- int rc;
- enum bpf_prog_type prog_type;
- enum bpf_attach_type expected_attach_type;
- } expected_load;
- struct {
- int rc;
- enum bpf_attach_type attach_type;
- } expected_attach;
-};
-
-static struct sec_name_test tests[] = {
- {"InvAliD", {-EINVAL, 0, 0}, {-EINVAL, 0} },
- {"cgroup", {-EINVAL, 0, 0}, {-EINVAL, 0} },
- {"socket", {0, BPF_PROG_TYPE_SOCKET_FILTER, 0}, {-EINVAL, 0} },
- {"kprobe/", {0, BPF_PROG_TYPE_KPROBE, 0}, {-EINVAL, 0} },
- {"kretprobe/", {0, BPF_PROG_TYPE_KPROBE, 0}, {-EINVAL, 0} },
- {"classifier", {0, BPF_PROG_TYPE_SCHED_CLS, 0}, {-EINVAL, 0} },
- {"action", {0, BPF_PROG_TYPE_SCHED_ACT, 0}, {-EINVAL, 0} },
- {"tracepoint/", {0, BPF_PROG_TYPE_TRACEPOINT, 0}, {-EINVAL, 0} },
- {
- "raw_tracepoint/",
- {0, BPF_PROG_TYPE_RAW_TRACEPOINT, 0},
- {-EINVAL, 0},
- },
- {"xdp", {0, BPF_PROG_TYPE_XDP, 0}, {-EINVAL, 0} },
- {"perf_event", {0, BPF_PROG_TYPE_PERF_EVENT, 0}, {-EINVAL, 0} },
- {"lwt_in", {0, BPF_PROG_TYPE_LWT_IN, 0}, {-EINVAL, 0} },
- {"lwt_out", {0, BPF_PROG_TYPE_LWT_OUT, 0}, {-EINVAL, 0} },
- {"lwt_xmit", {0, BPF_PROG_TYPE_LWT_XMIT, 0}, {-EINVAL, 0} },
- {"lwt_seg6local", {0, BPF_PROG_TYPE_LWT_SEG6LOCAL, 0}, {-EINVAL, 0} },
- {
- "cgroup_skb/ingress",
- {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
- {0, BPF_CGROUP_INET_INGRESS},
- },
- {
- "cgroup_skb/egress",
- {0, BPF_PROG_TYPE_CGROUP_SKB, 0},
- {0, BPF_CGROUP_INET_EGRESS},
- },
- {"cgroup/skb", {0, BPF_PROG_TYPE_CGROUP_SKB, 0}, {-EINVAL, 0} },
- {
- "cgroup/sock",
- {0, BPF_PROG_TYPE_CGROUP_SOCK, 0},
- {0, BPF_CGROUP_INET_SOCK_CREATE},
- },
- {
- "cgroup/post_bind4",
- {0, BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET4_POST_BIND},
- {0, BPF_CGROUP_INET4_POST_BIND},
- },
- {
- "cgroup/post_bind6",
- {0, BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET6_POST_BIND},
- {0, BPF_CGROUP_INET6_POST_BIND},
- },
- {
- "cgroup/dev",
- {0, BPF_PROG_TYPE_CGROUP_DEVICE, 0},
- {0, BPF_CGROUP_DEVICE},
- },
- {"sockops", {0, BPF_PROG_TYPE_SOCK_OPS, 0}, {0, BPF_CGROUP_SOCK_OPS} },
- {
- "sk_skb/stream_parser",
- {0, BPF_PROG_TYPE_SK_SKB, 0},
- {0, BPF_SK_SKB_STREAM_PARSER},
- },
- {
- "sk_skb/stream_verdict",
- {0, BPF_PROG_TYPE_SK_SKB, 0},
- {0, BPF_SK_SKB_STREAM_VERDICT},
- },
- {"sk_skb", {0, BPF_PROG_TYPE_SK_SKB, 0}, {-EINVAL, 0} },
- {"sk_msg", {0, BPF_PROG_TYPE_SK_MSG, 0}, {0, BPF_SK_MSG_VERDICT} },
- {"lirc_mode2", {0, BPF_PROG_TYPE_LIRC_MODE2, 0}, {0, BPF_LIRC_MODE2} },
- {
- "flow_dissector",
- {0, BPF_PROG_TYPE_FLOW_DISSECTOR, 0},
- {0, BPF_FLOW_DISSECTOR},
- },
- {
- "cgroup/bind4",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND},
- {0, BPF_CGROUP_INET4_BIND},
- },
- {
- "cgroup/bind6",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND},
- {0, BPF_CGROUP_INET6_BIND},
- },
- {
- "cgroup/connect4",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_CONNECT},
- {0, BPF_CGROUP_INET4_CONNECT},
- },
- {
- "cgroup/connect6",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT},
- {0, BPF_CGROUP_INET6_CONNECT},
- },
- {
- "cgroup/sendmsg4",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_SENDMSG},
- {0, BPF_CGROUP_UDP4_SENDMSG},
- },
- {
- "cgroup/sendmsg6",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
- {0, BPF_CGROUP_UDP6_SENDMSG},
- },
- {
- "cgroup/recvmsg4",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
- {0, BPF_CGROUP_UDP4_RECVMSG},
- },
- {
- "cgroup/recvmsg6",
- {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
- {0, BPF_CGROUP_UDP6_RECVMSG},
- },
- {
- "cgroup/sysctl",
- {0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
- {0, BPF_CGROUP_SYSCTL},
- },
- {
- "cgroup/getsockopt",
- {0, BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_GETSOCKOPT},
- {0, BPF_CGROUP_GETSOCKOPT},
- },
- {
- "cgroup/setsockopt",
- {0, BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_SETSOCKOPT},
- {0, BPF_CGROUP_SETSOCKOPT},
- },
-};
-
-static int test_prog_type_by_name(const struct sec_name_test *test)
-{
- enum bpf_attach_type expected_attach_type;
- enum bpf_prog_type prog_type;
- int rc;
-
- rc = libbpf_prog_type_by_name(test->sec_name, &prog_type,
- &expected_attach_type);
-
- if (rc != test->expected_load.rc) {
- warnx("prog: unexpected rc=%d for %s", rc, test->sec_name);
- return -1;
- }
-
- if (rc)
- return 0;
-
- if (prog_type != test->expected_load.prog_type) {
- warnx("prog: unexpected prog_type=%d for %s", prog_type,
- test->sec_name);
- return -1;
- }
-
- if (expected_attach_type != test->expected_load.expected_attach_type) {
- warnx("prog: unexpected expected_attach_type=%d for %s",
- expected_attach_type, test->sec_name);
- return -1;
- }
-
- return 0;
-}
-
-static int test_attach_type_by_name(const struct sec_name_test *test)
-{
- enum bpf_attach_type attach_type;
- int rc;
-
- rc = libbpf_attach_type_by_name(test->sec_name, &attach_type);
-
- if (rc != test->expected_attach.rc) {
- warnx("attach: unexpected rc=%d for %s", rc, test->sec_name);
- return -1;
- }
-
- if (rc)
- return 0;
-
- if (attach_type != test->expected_attach.attach_type) {
- warnx("attach: unexpected attach_type=%d for %s", attach_type,
- test->sec_name);
- return -1;
- }
-
- return 0;
-}
-
-static int test_prog_type_from_to_str(void)
-{
- enum bpf_prog_type type, actual_type;
- const char *str;
- int rc;
-
- for (type = BPF_PROG_TYPE_UNSPEC; type < __MAX_BPF_PROG_TYPE; type++) {
- rc = libbpf_prog_type_to_str(type, &str);
- if (rc) {
- warnx("prog_type_to_str: unexpected rc=%d for type %d",
- rc, type);
- return rc;
- }
-
- rc = libbpf_prog_type_from_str(str, &actual_type);
- if (rc) {
- warnx("prog_type_from_str: unexpected rc=%d for str %s",
- rc, str);
- return rc;
- }
-
- if (actual_type != type) {
- warnx("prog: unexpected prog_type for str %s, %d != %d",
- str, actual_type, type);
- return -EINVAL;
- }
- }
-
- rc = libbpf_prog_type_to_str(__MAX_BPF_PROG_TYPE, &str);
- if (!rc) {
- warnx("prog: unexpected result for __MAX_BPF_PROG_TYPE");
- return -EINVAL;
- }
-
- rc = libbpf_prog_type_from_str("NonExistent", &type);
- if (!rc) {
- warnx("prog: unexpected result for non existent key");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int test_map_type_from_to_str(void)
-{
- enum bpf_map_type type, actual_type;
- const char *str;
- int rc;
-
- for (type = BPF_MAP_TYPE_UNSPEC; type < __MAX_BPF_MAP_TYPE; type++) {
- rc = libbpf_map_type_to_str(type, &str);
- if (rc) {
- warnx("map_type_to_str: unexpected rc=%d for type %d",
- rc, type);
- return rc;
- }
-
- rc = libbpf_map_type_from_str(str, &actual_type);
- if (rc) {
- warnx("map_type_from_str: unexpected rc=%d for str %s",
- rc, str);
- return rc;
- }
-
- if (actual_type != type) {
- warnx("map: unexpected map_type for str %s, %d != %d",
- str, actual_type, type);
- return -EINVAL;
- }
- }
-
- rc = libbpf_map_type_to_str(__MAX_BPF_MAP_TYPE, &str);
- if (!rc) {
- warnx("map: unexpected result for __MAX_BPF_MAP_TYPE");
- return -EINVAL;
- }
-
- rc = libbpf_map_type_from_str("NonExistent", &type);
- if (!rc) {
- warnx("map: unexpected result for non existent key");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int test_attach_type_from_to_str(void)
-{
- enum bpf_attach_type type, actual_type;
- const char *str;
- int rc;
-
- for (type = BPF_CGROUP_INET_INGRESS; type < __MAX_BPF_ATTACH_TYPE;
- type++) {
- rc = libbpf_attach_type_to_str(type, &str);
- if (rc) {
- warnx("attach: unexpected rc=%d for type %d",
- rc, type);
- return rc;
- }
-
- rc = libbpf_attach_type_from_str(str, &actual_type);
- if (rc) {
- warnx("attach: unexpected rc=%d for str %s",
- rc, str);
- return rc;
- }
-
- if (actual_type != type) {
- warnx("attach: unexpected type for str %s, %d != %d",
- str, actual_type, type);
- return -EINVAL;
- }
- }
-
- rc = libbpf_attach_type_to_str(__MAX_BPF_ATTACH_TYPE, &str);
- if (!rc) {
- warnx("attach: unexpected result for __MAX_BPF_ATTACH_TYPE");
- return -EINVAL;
- }
-
- rc = libbpf_attach_type_from_str("NonExistent", &type);
- if (!rc) {
- warnx("attach: unexpected result for non existent key");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int run_sec_name_test_case(const struct sec_name_test *test)
-{
- if (test_prog_type_by_name(test))
- return -1;
- if (test_attach_type_by_name(test))
- return -1;
- return 0;
-}
-
-static int run_tests(void)
-{
- int passes = 0;
- int fails = 0;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(tests); ++i) {
- if (run_sec_name_test_case(&tests[i]))
- ++fails;
- else
- ++passes;
- }
-
- if (test_prog_type_from_to_str())
- ++fails;
- else
- ++passes;
-
- if (test_map_type_from_to_str())
- ++fails;
- else
- ++passes;
-
- if (test_attach_type_from_to_str())
- ++fails;
- else
- ++passes;
- printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
- return fails ? -1 : 0;
-}
-
-int main(int argc, char **argv)
-{
- return run_tests();
-}
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 07/10] selftests/bpf: extend test_section_names with type_(from|to)_str
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Test bpf enum stringification helpers:
libbpf_(prog|map|attach)_type_(from|to)_str
Signed-off-by: Julia Kartseva <hex@fb.com>
---
.../selftests/bpf/test_section_names.c | 149 +++++++++++++++++-
1 file changed, 147 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_section_names.c b/tools/testing/selftests/bpf/test_section_names.c
index 29833aeaf0de..564585a07592 100644
--- a/tools/testing/selftests/bpf/test_section_names.c
+++ b/tools/testing/selftests/bpf/test_section_names.c
@@ -202,7 +202,137 @@ static int test_attach_type_by_name(const struct sec_name_test *test)
return 0;
}
-static int run_test_case(const struct sec_name_test *test)
+static int test_prog_type_from_to_str(void)
+{
+ enum bpf_prog_type type, actual_type;
+ const char *str;
+ int rc;
+
+ for (type = BPF_PROG_TYPE_UNSPEC; type < __MAX_BPF_PROG_TYPE; type++) {
+ rc = libbpf_prog_type_to_str(type, &str);
+ if (rc) {
+ warnx("prog_type_to_str: unexpected rc=%d for type %d",
+ rc, type);
+ return rc;
+ }
+
+ rc = libbpf_prog_type_from_str(str, &actual_type);
+ if (rc) {
+ warnx("prog_type_from_str: unexpected rc=%d for str %s",
+ rc, str);
+ return rc;
+ }
+
+ if (actual_type != type) {
+ warnx("prog: unexpected prog_type for str %s, %d != %d",
+ str, actual_type, type);
+ return -EINVAL;
+ }
+ }
+
+ rc = libbpf_prog_type_to_str(__MAX_BPF_PROG_TYPE, &str);
+ if (!rc) {
+ warnx("prog: unexpected result for __MAX_BPF_PROG_TYPE");
+ return -EINVAL;
+ }
+
+ rc = libbpf_prog_type_from_str("NonExistent", &type);
+ if (!rc) {
+ warnx("prog: unexpected result for non existent key");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int test_map_type_from_to_str(void)
+{
+ enum bpf_map_type type, actual_type;
+ const char *str;
+ int rc;
+
+ for (type = BPF_MAP_TYPE_UNSPEC; type < __MAX_BPF_MAP_TYPE; type++) {
+ rc = libbpf_map_type_to_str(type, &str);
+ if (rc) {
+ warnx("map_type_to_str: unexpected rc=%d for type %d",
+ rc, type);
+ return rc;
+ }
+
+ rc = libbpf_map_type_from_str(str, &actual_type);
+ if (rc) {
+ warnx("map_type_from_str: unexpected rc=%d for str %s",
+ rc, str);
+ return rc;
+ }
+
+ if (actual_type != type) {
+ warnx("map: unexpected map_type for str %s, %d != %d",
+ str, actual_type, type);
+ return -EINVAL;
+ }
+ }
+
+ rc = libbpf_map_type_to_str(__MAX_BPF_MAP_TYPE, &str);
+ if (!rc) {
+ warnx("map: unexpected result for __MAX_BPF_MAP_TYPE");
+ return -EINVAL;
+ }
+
+ rc = libbpf_map_type_from_str("NonExistent", &type);
+ if (!rc) {
+ warnx("map: unexpected result for non existent key");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int test_attach_type_from_to_str(void)
+{
+ enum bpf_attach_type type, actual_type;
+ const char *str;
+ int rc;
+
+ for (type = BPF_CGROUP_INET_INGRESS; type < __MAX_BPF_ATTACH_TYPE;
+ type++) {
+ rc = libbpf_attach_type_to_str(type, &str);
+ if (rc) {
+ warnx("attach: unexpected rc=%d for type %d",
+ rc, type);
+ return rc;
+ }
+
+ rc = libbpf_attach_type_from_str(str, &actual_type);
+ if (rc) {
+ warnx("attach: unexpected rc=%d for str %s",
+ rc, str);
+ return rc;
+ }
+
+ if (actual_type != type) {
+ warnx("attach: unexpected type for str %s, %d != %d",
+ str, actual_type, type);
+ return -EINVAL;
+ }
+ }
+
+ rc = libbpf_attach_type_to_str(__MAX_BPF_ATTACH_TYPE, &str);
+ if (!rc) {
+ warnx("attach: unexpected result for __MAX_BPF_ATTACH_TYPE");
+ return -EINVAL;
+ }
+
+ rc = libbpf_attach_type_from_str("NonExistent", &type);
+ if (!rc) {
+ warnx("attach: unexpected result for non existent key");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int run_sec_name_test_case(const struct sec_name_test *test)
{
if (test_prog_type_by_name(test))
return -1;
@@ -218,11 +348,26 @@ static int run_tests(void)
int i;
for (i = 0; i < ARRAY_SIZE(tests); ++i) {
- if (run_test_case(&tests[i]))
+ if (run_sec_name_test_case(&tests[i]))
++fails;
else
++passes;
}
+
+ if (test_prog_type_from_to_str())
+ ++fails;
+ else
+ ++passes;
+
+ if (test_map_type_from_to_str())
+ ++fails;
+ else
+ ++passes;
+
+ if (test_attach_type_from_to_str())
+ ++fails;
+ else
+ ++passes;
printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
return fails ? -1 : 0;
}
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 06/10] tools/bpf: add libbpf_attach_type_(from|to)_str
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Standardize string representation of attach types by putting commonly used
names to libbpf.
The attach_type to string mapping is taken from bpftool:
tools/bpf/bpftool/cgroup.c
tools/bpf/bpftool/prog.c
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/lib/bpf/libbpf.c | 50 ++++++++++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.h | 5 ++++
tools/lib/bpf/libbpf.map | 2 ++
3 files changed, 57 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 9c531256888b..b5b07493655f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -354,6 +354,32 @@ static const char *const map_type_strs[] = {
[BPF_MAP_TYPE_DEVMAP_HASH] = "devmap_hash"
};
+static const char *const attach_type_strs[] = {
+ [BPF_CGROUP_INET_INGRESS] = "ingress",
+ [BPF_CGROUP_INET_EGRESS] = "egress",
+ [BPF_CGROUP_INET_SOCK_CREATE] = "sock_create",
+ [BPF_CGROUP_SOCK_OPS] = "sock_ops",
+ [BPF_SK_SKB_STREAM_PARSER] = "stream_parser",
+ [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict",
+ [BPF_CGROUP_DEVICE] = "device",
+ [BPF_SK_MSG_VERDICT] = "msg_verdict",
+ [BPF_CGROUP_INET4_BIND] = "bind4",
+ [BPF_CGROUP_INET6_BIND] = "bind6",
+ [BPF_CGROUP_INET4_CONNECT] = "connect4",
+ [BPF_CGROUP_INET6_CONNECT] = "connect6",
+ [BPF_CGROUP_INET4_POST_BIND] = "post_bind4",
+ [BPF_CGROUP_INET6_POST_BIND] = "post_bind6",
+ [BPF_CGROUP_UDP4_SENDMSG] = "sendmsg4",
+ [BPF_CGROUP_UDP6_SENDMSG] = "sendmsg6",
+ [BPF_LIRC_MODE2] = "lirc_mode2",
+ [BPF_FLOW_DISSECTOR] = "flow_dissector",
+ [BPF_CGROUP_SYSCTL] = "sysctl",
+ [BPF_CGROUP_UDP4_RECVMSG] = "recvmsg4",
+ [BPF_CGROUP_UDP6_RECVMSG] = "recvmsg6",
+ [BPF_CGROUP_GETSOCKOPT] = "getsockopt",
+ [BPF_CGROUP_SETSOCKOPT] = "setsockopt"
+};
+
void bpf_program__unload(struct bpf_program *prog)
{
int i;
@@ -4734,6 +4760,30 @@ int libbpf_map_type_to_str(enum bpf_map_type type, const char **str)
return 0;
}
+int libbpf_attach_type_from_str(const char *str, enum bpf_attach_type *type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(attach_type_strs); i++)
+ if (attach_type_strs[i] &&
+ strcmp(attach_type_strs[i], str) == 0) {
+ *type = i;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+int libbpf_attach_type_to_str(enum bpf_attach_type type, const char **str)
+{
+ if (type < BPF_CGROUP_INET_INGRESS ||
+ type >= ARRAY_SIZE(attach_type_strs))
+ return -EINVAL;
+
+ *str = attach_type_strs[type];
+ return 0;
+}
+
static int
bpf_program__identify_section(struct bpf_program *prog,
enum bpf_prog_type *prog_type,
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 90daeb2cdefb..0ad941951b0d 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -139,6 +139,11 @@ LIBBPF_API int libbpf_prog_type_to_str(enum bpf_prog_type type,
LIBBPF_API int libbpf_map_type_from_str(const char *str,
enum bpf_map_type *type);
LIBBPF_API int libbpf_map_type_to_str(enum bpf_map_type type, const char **str);
+/* String representation of attach type */
+LIBBPF_API int libbpf_attach_type_from_str(const char *str,
+ enum bpf_attach_type *type);
+LIBBPF_API int libbpf_attach_type_to_str(enum bpf_attach_type type,
+ const char **str);
/* Accessors of bpf_program */
struct bpf_program;
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index e4ecf5414bb7..d87a6dc8a71f 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -192,4 +192,6 @@ LIBBPF_0.0.5 {
libbpf_prog_type_to_str;
libbpf_map_type_from_str;
libbpf_map_type_to_str;
+ libbpf_attach_type_from_str;
+ libbpf_attach_type_to_str;
} LIBBPF_0.0.4;
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 04/10] tools/bpf: add libbpf_prog_type_(from|to)_str helpers
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Standardize string representation of prog types by putting commonly used
names to libbpf.
The prog_type to string mapping is taken from bpftool:
tools/bpf/bpftool/main.h
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/lib/bpf/libbpf.c | 51 ++++++++++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.h | 8 +++++++
tools/lib/bpf/libbpf.map | 2 ++
3 files changed, 61 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 72e6e5eb397f..946a4d41f223 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -296,6 +296,35 @@ struct bpf_object {
};
#define obj_elf_valid(o) ((o)->efile.elf)
+static const char *const prog_type_strs[] = {
+ [BPF_PROG_TYPE_UNSPEC] = "unspec",
+ [BPF_PROG_TYPE_SOCKET_FILTER] = "socket_filter",
+ [BPF_PROG_TYPE_KPROBE] = "kprobe",
+ [BPF_PROG_TYPE_SCHED_CLS] = "sched_cls",
+ [BPF_PROG_TYPE_SCHED_ACT] = "sched_act",
+ [BPF_PROG_TYPE_TRACEPOINT] = "tracepoint",
+ [BPF_PROG_TYPE_XDP] = "xdp",
+ [BPF_PROG_TYPE_PERF_EVENT] = "perf_event",
+ [BPF_PROG_TYPE_CGROUP_SKB] = "cgroup_skb",
+ [BPF_PROG_TYPE_CGROUP_SOCK] = "cgroup_sock",
+ [BPF_PROG_TYPE_LWT_IN] = "lwt_in",
+ [BPF_PROG_TYPE_LWT_OUT] = "lwt_out",
+ [BPF_PROG_TYPE_LWT_XMIT] = "lwt_xmit",
+ [BPF_PROG_TYPE_SOCK_OPS] = "sock_ops",
+ [BPF_PROG_TYPE_SK_SKB] = "sk_skb",
+ [BPF_PROG_TYPE_CGROUP_DEVICE] = "cgroup_device",
+ [BPF_PROG_TYPE_SK_MSG] = "sk_msg",
+ [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint",
+ [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr",
+ [BPF_PROG_TYPE_LWT_SEG6LOCAL] = "lwt_seg6local",
+ [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2",
+ [BPF_PROG_TYPE_SK_REUSEPORT] = "sk_reuseport",
+ [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector",
+ [BPF_PROG_TYPE_CGROUP_SYSCTL] = "cgroup_sysctl",
+ [BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE] = "raw_tracepoint_writable",
+ [BPF_PROG_TYPE_CGROUP_SOCKOPT] = "cgroup_sockopt",
+};
+
void bpf_program__unload(struct bpf_program *prog)
{
int i;
@@ -4632,6 +4661,28 @@ int libbpf_attach_type_by_name(const char *name,
return -EINVAL;
}
+int libbpf_prog_type_from_str(const char *str, enum bpf_prog_type *type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(prog_type_strs); i++)
+ if (prog_type_strs[i] && strcmp(prog_type_strs[i], str) == 0) {
+ *type = i;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+int libbpf_prog_type_to_str(enum bpf_prog_type type, const char **str)
+{
+ if (type < BPF_PROG_TYPE_UNSPEC || type >= ARRAY_SIZE(prog_type_strs))
+ return -EINVAL;
+
+ *str = prog_type_strs[type];
+ return 0;
+}
+
static int
bpf_program__identify_section(struct bpf_program *prog,
enum bpf_prog_type *prog_type,
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index e8f70977d137..6846c488d8a2 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -122,12 +122,20 @@ LIBBPF_API int bpf_object__set_priv(struct bpf_object *obj, void *priv,
bpf_object_clear_priv_t clear_priv);
LIBBPF_API void *bpf_object__priv(const struct bpf_object *prog);
+/* Program and expected attach types by section name */
LIBBPF_API int
libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
enum bpf_attach_type *expected_attach_type);
+/* Attach type by section name */
LIBBPF_API int libbpf_attach_type_by_name(const char *name,
enum bpf_attach_type *attach_type);
+/* String representation of program type */
+LIBBPF_API int libbpf_prog_type_from_str(const char *str,
+ enum bpf_prog_type *type);
+LIBBPF_API int libbpf_prog_type_to_str(enum bpf_prog_type type,
+ const char **str);
+
/* Accessors of bpf_program */
struct bpf_program;
LIBBPF_API struct bpf_program *bpf_program__next(struct bpf_program *prog,
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 664ce8e7a60e..2ea7c99f1579 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -188,4 +188,6 @@ LIBBPF_0.0.4 {
LIBBPF_0.0.5 {
global:
bpf_btf_get_next_id;
+ libbpf_prog_type_from_str;
+ libbpf_prog_type_to_str;
} LIBBPF_0.0.4;
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 00/10] bpf: bpf_(prog|map|attach)_type_(from|to)_str helpers
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
Standardize commonly used bpf enum names by introducing helper methods to
libbpf.
When applications require enum to string mapping the related code is
copy-pasted from bpftool. It hardens maintenance, e.g. when new enum
values are added.
Patches 0001-0003 introduce __MAX_BPF_PROG_TYPE and __MAX_BPF_MAP_TYPE enum
type.
Patches 0004-0006 introduce helpers methods
libbpf_str_from_(prog|map|attach)_type and
libbpf_(prog|map|attach)_type_from_str.
Patches 0007-0008 extend and rename test_section_names test.
Patches 0009-0010 introduce the helpers to bpftool.
An alternative for adding __MAX_BPF_(PROG|MAP)_TYPE is using an erroneous
result of bpf_(prog|map|attach)_type_(from|to)_str as an indicator of
loop bound. The disadvantages are: tests won't fail when a string name
is not provided for a new enum value; whoever wants to loop over enum
values should be aware about this side feature of newly introduced helpers.
Julia Kartseva (10):
bpf: introduce __MAX_BPF_PROG_TYPE and __MAX_BPF_MAP_TYPE enum values
tools/bpf: sync bpf.h to tools/
tools/bpf: handle __MAX_BPF_(PROG|MAP)_TYPE in switch statements
tools/bpf: add libbpf_prog_type_(from|to)_str helpers
tools/bpf: add libbpf_map_type_(from|to)_str helpers
tools/bpf: add libbpf_attach_type_(from|to)_str
selftests/bpf: extend test_section_names with type_(from|to)_str
selftests/bpf: rename test_section_names to
test_section_and_type_names
tools/bpftool: use libbpf_(prog|map)_type_to_str helpers
tools/bpftool: use libbpf_attach_type_to_str helper
include/uapi/linux/bpf.h | 6 +
tools/bpf/bpftool/cgroup.c | 60 +--
tools/bpf/bpftool/feature.c | 47 ++-
tools/bpf/bpftool/main.h | 33 --
tools/bpf/bpftool/map.c | 80 +---
tools/bpf/bpftool/prog.c | 31 +-
tools/include/uapi/linux/bpf.h | 6 +
tools/lib/bpf/libbpf.c | 153 +++++++
tools/lib/bpf/libbpf.h | 17 +
tools/lib/bpf/libbpf.map | 6 +
tools/lib/bpf/libbpf_probes.c | 2 +
tools/testing/selftests/bpf/Makefile | 2 +-
.../bpf/test_section_and_type_names.c | 378 ++++++++++++++++++
.../selftests/bpf/test_section_names.c | 233 -----------
14 files changed, 673 insertions(+), 381 deletions(-)
create mode 100644 tools/testing/selftests/bpf/test_section_and_type_names.c
delete mode 100644 tools/testing/selftests/bpf/test_section_names.c
--
2.17.1
^ permalink raw reply
* [PATCH bpf-next 05/10] tools/bpf: add libbpf_map_type_(from|to)_str helpers
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Similar to prog_type to string mapping, standardize string representation
of map types by putting commonly used names to libbpf.
The map_type to string mapping is taken from bpftool:
tools/bpf/bpftool/map.c
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/lib/bpf/libbpf.c | 51 ++++++++++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.h | 4 ++++
tools/lib/bpf/libbpf.map | 2 ++
3 files changed, 57 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 946a4d41f223..9c531256888b 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -325,6 +325,35 @@ static const char *const prog_type_strs[] = {
[BPF_PROG_TYPE_CGROUP_SOCKOPT] = "cgroup_sockopt",
};
+static const char *const map_type_strs[] = {
+ [BPF_MAP_TYPE_UNSPEC] = "unspec",
+ [BPF_MAP_TYPE_HASH] = "hash",
+ [BPF_MAP_TYPE_ARRAY] = "array",
+ [BPF_MAP_TYPE_PROG_ARRAY] = "prog_array",
+ [BPF_MAP_TYPE_PERF_EVENT_ARRAY] = "perf_event_array",
+ [BPF_MAP_TYPE_PERCPU_HASH] = "percpu_hash",
+ [BPF_MAP_TYPE_PERCPU_ARRAY] = "percpu_array",
+ [BPF_MAP_TYPE_STACK_TRACE] = "stack_trace",
+ [BPF_MAP_TYPE_CGROUP_ARRAY] = "cgroup_array",
+ [BPF_MAP_TYPE_LRU_HASH] = "lru_hash",
+ [BPF_MAP_TYPE_LRU_PERCPU_HASH] = "lru_percpu_hash",
+ [BPF_MAP_TYPE_LPM_TRIE] = "lpm_trie",
+ [BPF_MAP_TYPE_ARRAY_OF_MAPS] = "array_of_maps",
+ [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps",
+ [BPF_MAP_TYPE_DEVMAP] = "devmap",
+ [BPF_MAP_TYPE_SOCKMAP] = "sockmap",
+ [BPF_MAP_TYPE_CPUMAP] = "cpumap",
+ [BPF_MAP_TYPE_XSKMAP] = "xskmap",
+ [BPF_MAP_TYPE_SOCKHASH] = "sockhash",
+ [BPF_MAP_TYPE_CGROUP_STORAGE] = "cgroup_storage",
+ [BPF_MAP_TYPE_REUSEPORT_SOCKARRAY] = "reuseport_sockarray",
+ [BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE] = "percpu_cgroup_storage",
+ [BPF_MAP_TYPE_QUEUE] = "queue",
+ [BPF_MAP_TYPE_STACK] = "stack",
+ [BPF_MAP_TYPE_SK_STORAGE] = "sk_storage",
+ [BPF_MAP_TYPE_DEVMAP_HASH] = "devmap_hash"
+};
+
void bpf_program__unload(struct bpf_program *prog)
{
int i;
@@ -4683,6 +4712,28 @@ int libbpf_prog_type_to_str(enum bpf_prog_type type, const char **str)
return 0;
}
+int libbpf_map_type_from_str(const char *str, enum bpf_map_type *type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(map_type_strs); i++)
+ if (map_type_strs[i] && strcmp(map_type_strs[i], str) == 0) {
+ *type = i;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+int libbpf_map_type_to_str(enum bpf_map_type type, const char **str)
+{
+ if (type < BPF_MAP_TYPE_UNSPEC || type >= ARRAY_SIZE(map_type_strs))
+ return -EINVAL;
+
+ *str = map_type_strs[type];
+ return 0;
+}
+
static int
bpf_program__identify_section(struct bpf_program *prog,
enum bpf_prog_type *prog_type,
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 6846c488d8a2..90daeb2cdefb 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -135,6 +135,10 @@ LIBBPF_API int libbpf_prog_type_from_str(const char *str,
enum bpf_prog_type *type);
LIBBPF_API int libbpf_prog_type_to_str(enum bpf_prog_type type,
const char **str);
+/* String representation of map type */
+LIBBPF_API int libbpf_map_type_from_str(const char *str,
+ enum bpf_map_type *type);
+LIBBPF_API int libbpf_map_type_to_str(enum bpf_map_type type, const char **str);
/* Accessors of bpf_program */
struct bpf_program;
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 2ea7c99f1579..e4ecf5414bb7 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -190,4 +190,6 @@ LIBBPF_0.0.5 {
bpf_btf_get_next_id;
libbpf_prog_type_from_str;
libbpf_prog_type_to_str;
+ libbpf_map_type_from_str;
+ libbpf_map_type_to_str;
} LIBBPF_0.0.4;
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 01/10] bpf: introduce __MAX_BPF_PROG_TYPE and __MAX_BPF_MAP_TYPE enum values
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Similar to __MAX_BPF_ATTACH_TYPE identifying the number of elements in
bpf_attach_type enum, add tailing enum values __MAX_BPF_PROG_TYPE
and __MAX_BPF_MAP_TYPE to simplify e.g. iteration over enums values in
the case when new values are added.
Signed-off-by: Julia Kartseva <hex@fb.com>
---
include/uapi/linux/bpf.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 5d2fb183ee2d..9b681bb82211 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -136,8 +136,11 @@ enum bpf_map_type {
BPF_MAP_TYPE_STACK,
BPF_MAP_TYPE_SK_STORAGE,
BPF_MAP_TYPE_DEVMAP_HASH,
+ __MAX_BPF_MAP_TYPE
};
+#define MAX_BPF_MAP_TYPE __MAX_BPF_MAP_TYPE
+
/* Note that tracing related programs such as
* BPF_PROG_TYPE_{KPROBE,TRACEPOINT,PERF_EVENT,RAW_TRACEPOINT}
* are not subject to a stable API since kernel internal data
@@ -173,8 +176,11 @@ enum bpf_prog_type {
BPF_PROG_TYPE_CGROUP_SYSCTL,
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
BPF_PROG_TYPE_CGROUP_SOCKOPT,
+ __MAX_BPF_PROG_TYPE
};
+#define MAX_BPF_PROG_TYPE __MAX_BPF_PROG_TYPE
+
enum bpf_attach_type {
BPF_CGROUP_INET_INGRESS,
BPF_CGROUP_INET_EGRESS,
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 03/10] tools/bpf: handle __MAX_BPF_(PROG|MAP)_TYPE in switch statements
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Add cases to switch statements in probe_load, bpf_prog_type__needs_kver
bpf_probe_map_type to fix enumeration value not handled in switch
compilation error.
prog_type_name array in bpftool/main.h doesn't have __MAX_BPF_PROG_TYPE
entity, same for map, so probe won't be called.
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/lib/bpf/libbpf.c | 1 +
tools/lib/bpf/libbpf_probes.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 2233f919dd88..72e6e5eb397f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3580,6 +3580,7 @@ static bool bpf_prog_type__needs_kver(enum bpf_prog_type type)
case BPF_PROG_TYPE_PERF_EVENT:
case BPF_PROG_TYPE_CGROUP_SYSCTL:
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
+ case __MAX_BPF_PROG_TYPE:
return false;
case BPF_PROG_TYPE_KPROBE:
default:
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index 4b0b0364f5fc..8f2ba6a457ac 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -102,6 +102,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
case BPF_PROG_TYPE_FLOW_DISSECTOR:
case BPF_PROG_TYPE_CGROUP_SYSCTL:
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
+ case __MAX_BPF_PROG_TYPE:
default:
break;
}
@@ -250,6 +251,7 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
case BPF_MAP_TYPE_XSKMAP:
case BPF_MAP_TYPE_SOCKHASH:
case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
+ case __MAX_BPF_MAP_TYPE:
default:
break;
}
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next 02/10] tools/bpf: sync bpf.h to tools/
From: Julia Kartseva @ 2019-08-28 21:03 UTC (permalink / raw)
To: rdna, bpf, ast, daniel, netdev, kernel-team; +Cc: Julia Kartseva
In-Reply-To: <cover.1567024943.git.hex@fb.com>
Introduce __MAX_BPF_MAP_TYPE and __MAX_BPF_MAP_TYPE enum values.
Signed-off-by: Julia Kartseva <hex@fb.com>
---
tools/include/uapi/linux/bpf.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 5d2fb183ee2d..9b681bb82211 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -136,8 +136,11 @@ enum bpf_map_type {
BPF_MAP_TYPE_STACK,
BPF_MAP_TYPE_SK_STORAGE,
BPF_MAP_TYPE_DEVMAP_HASH,
+ __MAX_BPF_MAP_TYPE
};
+#define MAX_BPF_MAP_TYPE __MAX_BPF_MAP_TYPE
+
/* Note that tracing related programs such as
* BPF_PROG_TYPE_{KPROBE,TRACEPOINT,PERF_EVENT,RAW_TRACEPOINT}
* are not subject to a stable API since kernel internal data
@@ -173,8 +176,11 @@ enum bpf_prog_type {
BPF_PROG_TYPE_CGROUP_SYSCTL,
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
BPF_PROG_TYPE_CGROUP_SOCKOPT,
+ __MAX_BPF_PROG_TYPE
};
+#define MAX_BPF_PROG_TYPE __MAX_BPF_PROG_TYPE
+
enum bpf_attach_type {
BPF_CGROUP_INET_INGRESS,
BPF_CGROUP_INET_EGRESS,
--
2.17.1
^ permalink raw reply related
* Re: [PATCH bpf-next V9 1/3] bpf: new helper to obtain namespace data from current task
From: Carlos Antonio Neira Bustos @ 2019-08-28 21:03 UTC (permalink / raw)
To: Yonghong Song
Cc: netdev@vger.kernel.org, Eric Biederman, brouer@redhat.com,
bpf@vger.kernel.org
In-Reply-To: <4faeb577-387a-7186-e060-f0ca76395823@fb.com>
Thanks, I'll work on the net/netif_receive_skb selftest using this helper.
I hope I could complete this work this week.
Bests.
On Wed, Aug 28, 2019 at 08:53:25PM +0000, Yonghong Song wrote:
>
>
> On 8/28/19 1:39 PM, Carlos Antonio Neira Bustos wrote:
> > Yonghong,
> >
> > Thanks for the pointer, I fixed this bug, but I found another one that's triggered
> > now the test program I included in tools/testing/selftests/bpf/test_pidns.
> > It's seemed that fname was not correctly setup when passing it to filename_lookup.
> > This is fixed now and I'm doing some more testing.
> > I think I'll remove the tests on samples/bpf as they are mostly end on -EPERM as
> > the fix intended.
> > Is ok to remove them and just focus to finish the self tests code?.
>
> Yes, the samples/bpf test case can be removed.
> Could you create a selftest with tracpoint net/netif_receive_skb, which
> also uses the proposed helper? net/netif_receive_skb will happen in
> interrupt context and it should catch the issue as well if
> filename_lookup still get called in interrupt context.
>
> >
> > Bests
> >
> > On Wed, Aug 14, 2019 at 01:25:06AM -0400, carlos antonio neira bustos wrote:
> >> Thank you very much!
> >>
> >> Bests
> >>
> >> El mié., 14 de ago. de 2019 00:50, Yonghong Song <yhs@fb.com> escribió:
> >>
> >>>
> >>>
> >>> On 8/13/19 5:56 PM, Carlos Antonio Neira Bustos wrote:
> >>>> On Tue, Aug 13, 2019 at 11:11:14PM +0000, Yonghong Song wrote:
> >>>>>
> >>>>>
> >>>>> On 8/13/19 11:47 AM, Carlos Neira wrote:
> >>>>>> From: Carlos <cneirabustos@gmail.com>
> >>>>>>
> >>>>>> New bpf helper bpf_get_current_pidns_info.
> >>>>>> This helper obtains the active namespace from current and returns
> >>>>>> pid, tgid, device and namespace id as seen from that namespace,
> >>>>>> allowing to instrument a process inside a container.
> >>>>>>
> >>>>>> Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> >>>>>> ---
> >>>>>> fs/internal.h | 2 --
> >>>>>> fs/namei.c | 1 -
> >>>>>> include/linux/bpf.h | 1 +
> >>>>>> include/linux/namei.h | 4 +++
> >>>>>> include/uapi/linux/bpf.h | 31 ++++++++++++++++++++++-
> >>>>>> kernel/bpf/core.c | 1 +
> >>>>>> kernel/bpf/helpers.c | 64
> >>> ++++++++++++++++++++++++++++++++++++++++++++++++
> >>>>>> kernel/trace/bpf_trace.c | 2 ++
> >>>>>> 8 files changed, 102 insertions(+), 4 deletions(-)
> >>>>>>
> >>> [...]
> >>>>>>
> >>>>>> +BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *,
> >>> pidns_info, u32,
> >>>>>> + size)
> >>>>>> +{
> >>>>>> + const char *pidns_path = "/proc/self/ns/pid";
> >>>>>> + struct pid_namespace *pidns = NULL;
> >>>>>> + struct filename *tmp = NULL;
> >>>>>> + struct inode *inode;
> >>>>>> + struct path kp;
> >>>>>> + pid_t tgid = 0;
> >>>>>> + pid_t pid = 0;
> >>>>>> + int ret;
> >>>>>> + int len;
> >>>>>
> >>>>
> >>>> Thank you very much for catching this!.
> >>>> Could you share how to replicate this bug?.
> >>>
> >>> The config is attached. just run trace_ns_info and you
> >>> can reproduce the issue.
> >>>
> >>>>
> >>>>> I am running your sample program and get the following kernel bug:
> >>>>>
> >>>>> ...
> >>>>> [ 26.414825] BUG: sleeping function called from invalid context at
> >>>>> /data/users/yhs/work/net-next/fs
> >>>>> /dcache.c:843
> >>>>> [ 26.416314] in_atomic(): 1, irqs_disabled(): 0, pid: 1911, name: ping
> >>>>> [ 26.417189] CPU: 0 PID: 1911 Comm: ping Tainted: G W
> >>>>> 5.3.0-rc1+ #280
> >>>>> [ 26.418182] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
> >>>>> BIOS 1.9.3-1.el7.centos 04/01/2
> >>>>> 014
> >>>>> [ 26.419393] Call Trace:
> >>>>> [ 26.419697] <IRQ>
> >>>>> [ 26.419960] dump_stack+0x46/0x5b
> >>>>> [ 26.420434] ___might_sleep+0xe4/0x110
> >>>>> [ 26.420894] dput+0x2a/0x200
> >>>>> [ 26.421265] walk_component+0x10c/0x280
> >>>>> [ 26.421773] link_path_walk+0x327/0x560
> >>>>> [ 26.422280] ? proc_ns_dir_readdir+0x1a0/0x1a0
> >>>>> [ 26.422848] ? path_init+0x232/0x330
> >>>>> [ 26.423364] path_lookupat+0x88/0x200
> >>>>> [ 26.423808] ? selinux_parse_skb.constprop.69+0x124/0x430
> >>>>> [ 26.424521] filename_lookup+0xaf/0x190
> >>>>> [ 26.425031] ? simple_attr_release+0x20/0x20
> >>>>> [ 26.425560] bpf_get_current_pidns_info+0xfa/0x190
> >>>>> [ 26.426168] bpf_prog_83627154cefed596+0xe66/0x1000
> >>>>> [ 26.426779] trace_call_bpf+0xb5/0x160
> >>>>> [ 26.427317] ? __netif_receive_skb_core+0x1/0xbb0
> >>>>> [ 26.427929] ? __netif_receive_skb_core+0x1/0xbb0
> >>>>> [ 26.428496] kprobe_perf_func+0x4d/0x280
> >>>>> [ 26.428986] ? tracing_record_taskinfo_skip+0x1a/0x30
> >>>>> [ 26.429584] ? tracing_record_taskinfo+0xe/0x80
> >>>>> [ 26.430152] ? ttwu_do_wakeup.isra.114+0xcf/0xf0
> >>>>> [ 26.430737] ? __netif_receive_skb_core+0x1/0xbb0
> >>>>> [ 26.431334] ? __netif_receive_skb_core+0x5/0xbb0
> >>>>> [ 26.431930] kprobe_ftrace_handler+0x90/0xf0
> >>>>> [ 26.432495] ftrace_ops_assist_func+0x63/0x100
> >>>>> [ 26.433060] 0xffffffffc03180bf
> >>>>> [ 26.433471] ? __netif_receive_skb_core+0x1/0xbb0
> >>>>> ...
> >>>>>
> >>>>> To prevent we are running in arbitrary task (e.g., idle task)
> >>>>> context which may introduce sleeping issues, the following
> >>>>> probably appropriate:
> >>>>>
> >>>>> if (in_nmi() || in_softirq())
> >>>>> return -EPERM;
> >>>>>
> >>>>> Anyway, if in nmi or softirq, the namespace and pid/tgid
> >>>>> we get may be just accidentally associated with the bpf running
> >>>>> context, but it could be in a different context. So such info
> >>>>> is not reliable any way.
> >>>>>
> >>>>>> +
> >>>>>> + if (unlikely(size != sizeof(struct bpf_pidns_info)))
> >>>>>> + return -EINVAL;
> >>>>>> + pidns = task_active_pid_ns(current);
> >>> [...]
> >>>
^ permalink raw reply
* Re: [PATCH bpf-next V9 1/3] bpf: new helper to obtain namespace data from current task
From: Yonghong Song @ 2019-08-28 20:53 UTC (permalink / raw)
To: Carlos Antonio Neira Bustos
Cc: netdev@vger.kernel.org, Eric Biederman, brouer@redhat.com,
bpf@vger.kernel.org
In-Reply-To: <20190828203951.qo4kaloahcnvp7nw@ebpf-metal>
On 8/28/19 1:39 PM, Carlos Antonio Neira Bustos wrote:
> Yonghong,
>
> Thanks for the pointer, I fixed this bug, but I found another one that's triggered
> now the test program I included in tools/testing/selftests/bpf/test_pidns.
> It's seemed that fname was not correctly setup when passing it to filename_lookup.
> This is fixed now and I'm doing some more testing.
> I think I'll remove the tests on samples/bpf as they are mostly end on -EPERM as
> the fix intended.
> Is ok to remove them and just focus to finish the self tests code?.
Yes, the samples/bpf test case can be removed.
Could you create a selftest with tracpoint net/netif_receive_skb, which
also uses the proposed helper? net/netif_receive_skb will happen in
interrupt context and it should catch the issue as well if
filename_lookup still get called in interrupt context.
>
> Bests
>
> On Wed, Aug 14, 2019 at 01:25:06AM -0400, carlos antonio neira bustos wrote:
>> Thank you very much!
>>
>> Bests
>>
>> El mié., 14 de ago. de 2019 00:50, Yonghong Song <yhs@fb.com> escribió:
>>
>>>
>>>
>>> On 8/13/19 5:56 PM, Carlos Antonio Neira Bustos wrote:
>>>> On Tue, Aug 13, 2019 at 11:11:14PM +0000, Yonghong Song wrote:
>>>>>
>>>>>
>>>>> On 8/13/19 11:47 AM, Carlos Neira wrote:
>>>>>> From: Carlos <cneirabustos@gmail.com>
>>>>>>
>>>>>> New bpf helper bpf_get_current_pidns_info.
>>>>>> This helper obtains the active namespace from current and returns
>>>>>> pid, tgid, device and namespace id as seen from that namespace,
>>>>>> allowing to instrument a process inside a container.
>>>>>>
>>>>>> Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
>>>>>> ---
>>>>>> fs/internal.h | 2 --
>>>>>> fs/namei.c | 1 -
>>>>>> include/linux/bpf.h | 1 +
>>>>>> include/linux/namei.h | 4 +++
>>>>>> include/uapi/linux/bpf.h | 31 ++++++++++++++++++++++-
>>>>>> kernel/bpf/core.c | 1 +
>>>>>> kernel/bpf/helpers.c | 64
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>>>> kernel/trace/bpf_trace.c | 2 ++
>>>>>> 8 files changed, 102 insertions(+), 4 deletions(-)
>>>>>>
>>> [...]
>>>>>>
>>>>>> +BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *,
>>> pidns_info, u32,
>>>>>> + size)
>>>>>> +{
>>>>>> + const char *pidns_path = "/proc/self/ns/pid";
>>>>>> + struct pid_namespace *pidns = NULL;
>>>>>> + struct filename *tmp = NULL;
>>>>>> + struct inode *inode;
>>>>>> + struct path kp;
>>>>>> + pid_t tgid = 0;
>>>>>> + pid_t pid = 0;
>>>>>> + int ret;
>>>>>> + int len;
>>>>>
>>>>
>>>> Thank you very much for catching this!.
>>>> Could you share how to replicate this bug?.
>>>
>>> The config is attached. just run trace_ns_info and you
>>> can reproduce the issue.
>>>
>>>>
>>>>> I am running your sample program and get the following kernel bug:
>>>>>
>>>>> ...
>>>>> [ 26.414825] BUG: sleeping function called from invalid context at
>>>>> /data/users/yhs/work/net-next/fs
>>>>> /dcache.c:843
>>>>> [ 26.416314] in_atomic(): 1, irqs_disabled(): 0, pid: 1911, name: ping
>>>>> [ 26.417189] CPU: 0 PID: 1911 Comm: ping Tainted: G W
>>>>> 5.3.0-rc1+ #280
>>>>> [ 26.418182] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
>>>>> BIOS 1.9.3-1.el7.centos 04/01/2
>>>>> 014
>>>>> [ 26.419393] Call Trace:
>>>>> [ 26.419697] <IRQ>
>>>>> [ 26.419960] dump_stack+0x46/0x5b
>>>>> [ 26.420434] ___might_sleep+0xe4/0x110
>>>>> [ 26.420894] dput+0x2a/0x200
>>>>> [ 26.421265] walk_component+0x10c/0x280
>>>>> [ 26.421773] link_path_walk+0x327/0x560
>>>>> [ 26.422280] ? proc_ns_dir_readdir+0x1a0/0x1a0
>>>>> [ 26.422848] ? path_init+0x232/0x330
>>>>> [ 26.423364] path_lookupat+0x88/0x200
>>>>> [ 26.423808] ? selinux_parse_skb.constprop.69+0x124/0x430
>>>>> [ 26.424521] filename_lookup+0xaf/0x190
>>>>> [ 26.425031] ? simple_attr_release+0x20/0x20
>>>>> [ 26.425560] bpf_get_current_pidns_info+0xfa/0x190
>>>>> [ 26.426168] bpf_prog_83627154cefed596+0xe66/0x1000
>>>>> [ 26.426779] trace_call_bpf+0xb5/0x160
>>>>> [ 26.427317] ? __netif_receive_skb_core+0x1/0xbb0
>>>>> [ 26.427929] ? __netif_receive_skb_core+0x1/0xbb0
>>>>> [ 26.428496] kprobe_perf_func+0x4d/0x280
>>>>> [ 26.428986] ? tracing_record_taskinfo_skip+0x1a/0x30
>>>>> [ 26.429584] ? tracing_record_taskinfo+0xe/0x80
>>>>> [ 26.430152] ? ttwu_do_wakeup.isra.114+0xcf/0xf0
>>>>> [ 26.430737] ? __netif_receive_skb_core+0x1/0xbb0
>>>>> [ 26.431334] ? __netif_receive_skb_core+0x5/0xbb0
>>>>> [ 26.431930] kprobe_ftrace_handler+0x90/0xf0
>>>>> [ 26.432495] ftrace_ops_assist_func+0x63/0x100
>>>>> [ 26.433060] 0xffffffffc03180bf
>>>>> [ 26.433471] ? __netif_receive_skb_core+0x1/0xbb0
>>>>> ...
>>>>>
>>>>> To prevent we are running in arbitrary task (e.g., idle task)
>>>>> context which may introduce sleeping issues, the following
>>>>> probably appropriate:
>>>>>
>>>>> if (in_nmi() || in_softirq())
>>>>> return -EPERM;
>>>>>
>>>>> Anyway, if in nmi or softirq, the namespace and pid/tgid
>>>>> we get may be just accidentally associated with the bpf running
>>>>> context, but it could be in a different context. So such info
>>>>> is not reliable any way.
>>>>>
>>>>>> +
>>>>>> + if (unlikely(size != sizeof(struct bpf_pidns_info)))
>>>>>> + return -EINVAL;
>>>>>> + pidns = task_active_pid_ns(current);
>>> [...]
>>>
^ permalink raw reply
* Re: [PATCH net-next 01/15] MIPS: SGI-IP27: remove ioc3 ethernet init
From: Paul Burton @ 2019-08-28 20:45 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Ralf Baechle, James Hogan, David S. Miller,
linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <20190828140315.17048-2-tbogendoerfer@suse.de>
Hi Thomas,
On Wed, Aug 28, 2019 at 04:03:00PM +0200, Thomas Bogendoerfer wrote:
> Removed not needed disabling of ethernet interrupts in IP27 platform code.
>
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Acked-by: Paul Burton <paul.burton@mips.com>
Thanks,
Paul
> ---
> arch/mips/sgi-ip27/ip27-init.c | 13 -------------
> 1 file changed, 13 deletions(-)
>
> diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
> index 066b33f50bcc..59d5375c9021 100644
> --- a/arch/mips/sgi-ip27/ip27-init.c
> +++ b/arch/mips/sgi-ip27/ip27-init.c
> @@ -130,17 +130,6 @@ cnodeid_t get_compact_nodeid(void)
> return NASID_TO_COMPACT_NODEID(get_nasid());
> }
>
> -static inline void ioc3_eth_init(void)
> -{
> - struct ioc3 *ioc3;
> - nasid_t nid;
> -
> - nid = get_nasid();
> - ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base;
> -
> - ioc3->eier = 0;
> -}
> -
> extern void ip27_reboot_setup(void);
>
> void __init plat_mem_setup(void)
> @@ -182,8 +171,6 @@ void __init plat_mem_setup(void)
> panic("Kernel compiled for N mode.");
> #endif
>
> - ioc3_eth_init();
> -
> ioport_resource.start = 0;
> ioport_resource.end = ~0UL;
> set_io_port_base(IO_BASE);
> --
> 2.13.7
>
^ permalink raw reply
* [PATCH 3/3] samples: pktgen: allow to specify destination IP range (CIDR)
From: Daniel T. Lee @ 2019-08-28 20:42 UTC (permalink / raw)
To: Jesper Dangaard Brouer, David S . Miller; +Cc: netdev
In-Reply-To: <20190828204243.16666-1-danieltimlee@gmail.com>
Currently, kernel pktgen has the feature to specify destination
address range for sending packet. (e.g. pgset "dst_min/dst_max")
But on samples, each of them doesn't have any option to achieve this.
The commit adds feature to specify destination address range with CIDR.
-d : ($DEST_IP) destination IP. CIDR (e.g. 198.18.0.0/15) is also allowed
# ./pktgen_sample01_simple.sh -6 -d fe80::20/126 -p 3000 -n 4
# tcpdump ip6 and udp
05:14:18.082285 IP6 fe80::99.71 > fe80::23.3000: UDP, length 16
05:14:18.082564 IP6 fe80::99.43 > fe80::23.3000: UDP, length 16
05:14:18.083366 IP6 fe80::99.107 > fe80::22.3000: UDP, length 16
05:14:18.083585 IP6 fe80::99.97 > fe80::21.3000: UDP, length 16
Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com>
---
samples/pktgen/README.rst | 2 +-
samples/pktgen/parameters.sh | 2 +-
.../pktgen/pktgen_bench_xmit_mode_netif_receive.sh | 4 +++-
samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh | 4 +++-
samples/pktgen/pktgen_sample01_simple.sh | 4 +++-
samples/pktgen/pktgen_sample02_multiqueue.sh | 4 +++-
samples/pktgen/pktgen_sample03_burst_single_flow.sh | 4 +++-
samples/pktgen/pktgen_sample04_many_flows.sh | 11 ++++++++---
samples/pktgen/pktgen_sample05_flow_per_thread.sh | 4 +++-
.../pktgen_sample06_numa_awared_queue_irq_affinity.sh | 4 +++-
10 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/samples/pktgen/README.rst b/samples/pktgen/README.rst
index fd39215db508..3f6483e8b2df 100644
--- a/samples/pktgen/README.rst
+++ b/samples/pktgen/README.rst
@@ -18,7 +18,7 @@ across the sample scripts. Usage example is printed on errors::
Usage: ./pktgen_sample01_simple.sh [-vx] -i ethX
-i : ($DEV) output interface/device (required)
-s : ($PKT_SIZE) packet size
- -d : ($DEST_IP) destination IP
+ -d : ($DEST_IP) destination IP. CIDR (e.g. 198.18.0.0/15) is also allowed
-m : ($DST_MAC) destination MAC-addr
-p : ($DST_PORT) destination PORT range (e.g. 433-444) is also allowed
-t : ($THREADS) threads to start
diff --git a/samples/pktgen/parameters.sh b/samples/pktgen/parameters.sh
index a06b00a0c7b6..ff0ed474fee9 100644
--- a/samples/pktgen/parameters.sh
+++ b/samples/pktgen/parameters.sh
@@ -8,7 +8,7 @@ function usage() {
echo "Usage: $0 [-vx] -i ethX"
echo " -i : (\$DEV) output interface/device (required)"
echo " -s : (\$PKT_SIZE) packet size"
- echo " -d : (\$DEST_IP) destination IP"
+ echo " -d : (\$DEST_IP) destination IP. CIDR (e.g. 198.18.0.0/15) is also allowed"
echo " -m : (\$DST_MAC) destination MAC-addr"
echo " -p : (\$DST_PORT) destination PORT range (e.g. 433-444) is also allowed"
echo " -t : (\$THREADS) threads to start"
diff --git a/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh b/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
index 9b74502c58f7..da6cb711b7f4 100755
--- a/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
+++ b/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
@@ -41,6 +41,7 @@ fi
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
[ -z "$BURST" ] && BURST=1024
[ -z "$COUNT" ] && COUNT="10000000" # Zero means indefinitely
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -71,7 +72,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
# Destination
pg_set $dev "dst_mac $DST_MAC"
- pg_set $dev "dst$IP6 $DEST_IP"
+ pg_set $dev "dst${IP6}_min $DST_MIN"
+ pg_set $dev "dst${IP6}_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
diff --git a/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh b/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh
index 0f332555b40d..355937787364 100755
--- a/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh
+++ b/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh
@@ -24,6 +24,7 @@ if [[ -n "$BURST" ]]; then
err 1 "Bursting not supported for this mode"
fi
[ -z "$COUNT" ] && COUNT="10000000" # Zero means indefinitely
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -54,7 +55,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
# Destination
pg_set $dev "dst_mac $DST_MAC"
- pg_set $dev "dst$IP6 $DEST_IP"
+ pg_set $dev "dst${IP6}_min $DST_MIN"
+ pg_set $dev "dst${IP6}_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
diff --git a/samples/pktgen/pktgen_sample01_simple.sh b/samples/pktgen/pktgen_sample01_simple.sh
index 063ec0998906..08995fa70025 100755
--- a/samples/pktgen/pktgen_sample01_simple.sh
+++ b/samples/pktgen/pktgen_sample01_simple.sh
@@ -22,6 +22,7 @@ fi
# Example enforce param "-m" for dst_mac
[ -z "$DST_MAC" ] && usage && err 2 "Must specify -m dst_mac"
[ -z "$COUNT" ] && COUNT="100000" # Zero means indefinitely
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -61,7 +62,8 @@ pg_set $DEV "flag NO_TIMESTAMP"
# Destination
pg_set $DEV "dst_mac $DST_MAC"
-pg_set $DEV "dst$IP6 $DEST_IP"
+pg_set $DEV "dst${IP6}_min $DST_MIN"
+pg_set $DEV "dst${IP6}_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
diff --git a/samples/pktgen/pktgen_sample02_multiqueue.sh b/samples/pktgen/pktgen_sample02_multiqueue.sh
index a4726fb50197..9b806e41c23a 100755
--- a/samples/pktgen/pktgen_sample02_multiqueue.sh
+++ b/samples/pktgen/pktgen_sample02_multiqueue.sh
@@ -29,6 +29,7 @@ if [ -z "$DEST_IP" ]; then
[ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1"
fi
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -62,7 +63,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
# Destination
pg_set $dev "dst_mac $DST_MAC"
- pg_set $dev "dst$IP6 $DEST_IP"
+ pg_set $dev "dst${IP6}_min $DST_MIN"
+ pg_set $dev "dst${IP6}_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
diff --git a/samples/pktgen/pktgen_sample03_burst_single_flow.sh b/samples/pktgen/pktgen_sample03_burst_single_flow.sh
index dfea91a09ccc..cb067788ceb3 100755
--- a/samples/pktgen/pktgen_sample03_burst_single_flow.sh
+++ b/samples/pktgen/pktgen_sample03_burst_single_flow.sh
@@ -33,6 +33,7 @@ fi
[ -z "$BURST" ] && BURST=32
[ -z "$CLONE_SKB" ] && CLONE_SKB="0" # No need for clones when bursting
[ -z "$COUNT" ] && COUNT="0" # Zero means indefinitely
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -62,7 +63,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
# Destination
pg_set $dev "dst_mac $DST_MAC"
- pg_set $dev "dst$IP6 $DEST_IP"
+ pg_set $dev "dst${IP6}_min $DST_MIN"
+ pg_set $dev "dst${IP6}_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
diff --git a/samples/pktgen/pktgen_sample04_many_flows.sh b/samples/pktgen/pktgen_sample04_many_flows.sh
index 7ea9b4a3acf6..626e33016869 100755
--- a/samples/pktgen/pktgen_sample04_many_flows.sh
+++ b/samples/pktgen/pktgen_sample04_many_flows.sh
@@ -17,6 +17,7 @@ source ${basedir}/parameters.sh
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
[ -z "$COUNT" ] && COUNT="0" # Zero means indefinitely
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -37,6 +38,9 @@ if [[ -n "$BURST" ]]; then
err 1 "Bursting not supported for this mode"
fi
+# 198.18.0.0 / 198.19.255.255
+read -r SRC_MIN SRC_MAX <<< $(parse_addr 198.18.0.0/15)
+
# General cleanup everything since last run
pg_ctrl "reset"
@@ -58,7 +62,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
# Single destination
pg_set $dev "dst_mac $DST_MAC"
- pg_set $dev "dst $DEST_IP"
+ pg_set $dev "dst_min $DST_MIN"
+ pg_set $dev "dst_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
@@ -69,8 +74,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
# Randomize source IP-addresses
pg_set $dev "flag IPSRC_RND"
- pg_set $dev "src_min 198.18.0.0"
- pg_set $dev "src_max 198.19.255.255"
+ pg_set $dev "src_min $SRC_MIN"
+ pg_set $dev "src_max $SRC_MAX"
# Limit number of flows (max 65535)
pg_set $dev "flows $FLOWS"
diff --git a/samples/pktgen/pktgen_sample05_flow_per_thread.sh b/samples/pktgen/pktgen_sample05_flow_per_thread.sh
index fbfafe029e11..cb79de073e9d 100755
--- a/samples/pktgen/pktgen_sample05_flow_per_thread.sh
+++ b/samples/pktgen/pktgen_sample05_flow_per_thread.sh
@@ -22,6 +22,7 @@ source ${basedir}/parameters.sh
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
[ -z "$BURST" ] && BURST=32
[ -z "$COUNT" ] && COUNT="0" # Zero means indefinitely
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -51,7 +52,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
# Single destination
pg_set $dev "dst_mac $DST_MAC"
- pg_set $dev "dst $DEST_IP"
+ pg_set $dev "dst_min $DST_MIN"
+ pg_set $dev "dst_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
diff --git a/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh b/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
index 755e662183f1..739adcda5b5f 100755
--- a/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
+++ b/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
@@ -35,6 +35,7 @@ if [ -z "$DEST_IP" ]; then
[ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1"
fi
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
+[ -n "$DEST_IP" ] && read -r DST_MIN DST_MAX <<< $(parse_addr${IP6} $DEST_IP)
if [ -n "$DST_PORT" ]; then
read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
validate_ports $UDP_DST_MIN $UDP_DST_MAX
@@ -79,7 +80,8 @@ for ((i = 0; i < $THREADS; i++)); do
# Destination
pg_set $dev "dst_mac $DST_MAC"
- pg_set $dev "dst$IP6 $DEST_IP"
+ pg_set $dev "dst${IP6}_min $DST_MIN"
+ pg_set $dev "dst${IP6}_max $DST_MAX"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
--
2.20.1
^ permalink raw reply related
* [PATCH 2/3] samples: pktgen: add helper functions for IP(v4/v6) CIDR parsing
From: Daniel T. Lee @ 2019-08-28 20:42 UTC (permalink / raw)
To: Jesper Dangaard Brouer, David S . Miller; +Cc: netdev
In-Reply-To: <20190828204243.16666-1-danieltimlee@gmail.com>
This commit adds CIDR parsing and IP validate helper function to parse
single IP or range of IP with CIDR. (e.g. 198.18.0.0/15)
Helpers will be used in prior to set target address in samples/pktgen.
Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com>
---
samples/pktgen/functions.sh | 134 ++++++++++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
diff --git a/samples/pktgen/functions.sh b/samples/pktgen/functions.sh
index 4af4046d71be..eb1c52e25018 100644
--- a/samples/pktgen/functions.sh
+++ b/samples/pktgen/functions.sh
@@ -163,6 +163,140 @@ function get_node_cpus()
echo $node_cpu_list
}
+# Extend shrunken IPv6 address.
+# fe80::42:bcff:fe84:e10a => fe80:0:0:0:42:bcff:fe84:e10a
+function extend_addr6()
+{
+ local addr=$1
+ local sep=:
+ local sep2=::
+ local sep_cnt=$(tr -cd $sep <<< $1 | wc -c)
+ local shrink
+
+ # separator count : should be between 2, 7.
+ if [[ $sep_cnt -lt 2 || $sep_cnt -gt 7 ]]; then
+ err 5 "Invalid IP6 address sep: $1"
+ fi
+
+ # if shrink '::' occurs multiple, it's malformed.
+ shrink=( $(egrep -o "$sep{2,}" <<< $addr) )
+ if [[ ${#shrink[@]} -ne 0 ]]; then
+ if [[ ${#shrink[@]} -gt 1 || ( ${shrink[0]} != $sep2 ) ]]; then
+ err 5 "Invalid IP$IP6 address shr: $1"
+ fi
+ fi
+
+ # add 0 at begin & end, and extend addr by adding :0
+ [[ ${addr:0:1} == $sep ]] && addr=0${addr}
+ [[ ${addr: -1} == $sep ]] && addr=${addr}0
+ echo "${addr/$sep2/$(printf ':0%.s' $(seq $[8-sep_cnt])):}"
+}
+
+
+# Given a single IP(v4/v6) address, whether it is valid.
+function validate_addr()
+{
+ # check function is called with (funcname)6
+ [[ ${FUNCNAME[1]: -1} == 6 ]] && local IP6=6
+ local len=$[ IP6 ? 8 : 4 ]
+ local max=$[ 2**(len*2)-1 ]
+ local addr
+ local sep
+
+ # set separator for each IP(v4/v6)
+ [[ $IP6 ]] && sep=: || sep=.
+ IFS=$sep read -a addr <<< $1
+
+ # array length
+ if [[ ${#addr[@]} != $len ]]; then
+ err 5 "Invalid IP$IP6 address: $1"
+ fi
+
+ # check each digit between 0, $max
+ for digit in "${addr[@]}"; do
+ [[ $IP6 ]] && digit=$[ 16#$digit ]
+ if [[ $digit -lt 0 || $digit -gt $max ]]; then
+ err 5 "Invalid IP$IP6 address: $1"
+ fi
+ done
+
+ return 0
+}
+
+function validate_addr6() { validate_addr $@ ; }
+
+# Given a single IP(v4/v6) or CIDR, return minimum and maximum IP addr.
+function parse_addr()
+{
+ # check function is called with (funcname)6
+ [[ ${FUNCNAME[1]: -1} == 6 ]] && local IP6=6
+ local bitlen=$[ IP6 ? 128 : 32 ]
+
+ local addr=$1
+ local net
+ local prefix
+ local min_ip
+ local max_ip
+
+ IFS='/' read net prefix <<< $addr
+ [[ $IP6 ]] && net=$(extend_addr6 $net)
+ validate_addr$IP6 $net
+
+ if [[ $prefix -gt $bitlen ]]; then
+ err 5 "Invalid prefix: $prefix"
+ elif [[ -z $prefix ]]; then
+ min_ip=$net
+ max_ip=$net
+ else
+ # defining array for converting Decimal 2 Binary
+ # 00000000 00000001 00000010 00000011 00000100 ...
+ local d2b='{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}'
+ [[ $IP6 ]] && d2b+=$d2b
+ eval local D2B=($d2b)
+
+ local shift=$[ bitlen-prefix ]
+ local ip_bit
+ local ip
+ local sep
+
+ # set separator for each IP(v4/v6)
+ [[ $IP6 ]] && sep=: || sep=.
+ IFS=$sep read -ra ip <<< $net
+
+ # build full size bit
+ for digit in "${ip[@]}"; do
+ [[ $IP6 ]] && digit=$[ 16#$digit ]
+ ip_bit+=${D2B[$digit]}
+ done
+
+ # fill 0 or 1 by $shift
+ base_bit=${ip_bit::$prefix}
+ min_bit="$base_bit$(printf '0%.s' $(seq $shift))"
+ max_bit="$base_bit$(printf '1%.s' $(seq $shift))"
+
+ bit2addr() {
+ local step=$[ IP6 ? 16 : 8 ]
+ local max=$[ bitlen-step ]
+ local result
+ local fmt
+ [[ $IP6 ]] && fmt='%X' || fmt='%d'
+
+ for i in $(seq 0 $step $max); do
+ result+=$(printf $fmt $[ 2#${1:$i:$step} ])
+ [[ $i != $max ]] && result+=$sep
+ done
+ echo $result
+ }
+
+ min_ip=$(bit2addr $min_bit)
+ max_ip=$(bit2addr $max_bit)
+ fi
+
+ echo $min_ip $max_ip
+}
+
+function parse_addr6() { parse_addr $@ ; }
+
# Given a single or range of port(s), return minimum and maximum port number.
function parse_ports()
{
--
2.20.1
^ permalink raw reply related
* [PATCH 1/3] samples: pktgen: make variable consistent with option
From: Daniel T. Lee @ 2019-08-28 20:42 UTC (permalink / raw)
To: Jesper Dangaard Brouer, David S . Miller; +Cc: netdev
This commit changes variable names that can cause confusion.
For example, variable DST_MIN is quite confusing since the
keyword 'udp_dst_min' and keyword 'dst_min' is used with pg_ctrl.
On the following commit, 'dst_min' will be used to set destination IP,
and the existing variable name DST_MIN should be changed.
Variable names are matched to the exact keyword used with pg_ctrl.
Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com>
---
.../pktgen_bench_xmit_mode_netif_receive.sh | 8 ++++----
.../pktgen/pktgen_bench_xmit_mode_queue_xmit.sh | 8 ++++----
samples/pktgen/pktgen_sample01_simple.sh | 16 ++++++++--------
samples/pktgen/pktgen_sample02_multiqueue.sh | 16 ++++++++--------
.../pktgen/pktgen_sample03_burst_single_flow.sh | 8 ++++----
samples/pktgen/pktgen_sample04_many_flows.sh | 8 ++++----
.../pktgen/pktgen_sample05_flow_per_thread.sh | 8 ++++----
...en_sample06_numa_awared_queue_irq_affinity.sh | 16 ++++++++--------
8 files changed, 44 insertions(+), 44 deletions(-)
diff --git a/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh b/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
index e14b1a9144d9..9b74502c58f7 100755
--- a/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
+++ b/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
@@ -42,8 +42,8 @@ fi
[ -z "$BURST" ] && BURST=1024
[ -z "$COUNT" ] && COUNT="10000000" # Zero means indefinitely
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# Base Config
@@ -76,8 +76,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
- pg_set $dev "udp_dst_min $DST_MIN"
- pg_set $dev "udp_dst_max $DST_MAX"
+ pg_set $dev "udp_dst_min $UDP_DST_MIN"
+ pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Inject packet into RX path of stack
diff --git a/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh b/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh
index 82c3e504e056..0f332555b40d 100755
--- a/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh
+++ b/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh
@@ -25,8 +25,8 @@ if [[ -n "$BURST" ]]; then
fi
[ -z "$COUNT" ] && COUNT="10000000" # Zero means indefinitely
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# Base Config
@@ -59,8 +59,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
- pg_set $dev "udp_dst_min $DST_MIN"
- pg_set $dev "udp_dst_max $DST_MAX"
+ pg_set $dev "udp_dst_min $UDP_DST_MIN"
+ pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Inject packet into TX qdisc egress path of stack
diff --git a/samples/pktgen/pktgen_sample01_simple.sh b/samples/pktgen/pktgen_sample01_simple.sh
index d1702fdde8f3..063ec0998906 100755
--- a/samples/pktgen/pktgen_sample01_simple.sh
+++ b/samples/pktgen/pktgen_sample01_simple.sh
@@ -23,16 +23,16 @@ fi
[ -z "$DST_MAC" ] && usage && err 2 "Must specify -m dst_mac"
[ -z "$COUNT" ] && COUNT="100000" # Zero means indefinitely
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# Base Config
DELAY="0" # Zero means max speed
# Flow variation random source port between min and max
-UDP_MIN=9
-UDP_MAX=109
+UDP_SRC_MIN=9
+UDP_SRC_MAX=109
# General cleanup everything since last run
# (especially important if other threads were configured by other scripts)
@@ -66,14 +66,14 @@ pg_set $DEV "dst$IP6 $DEST_IP"
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $DEV "flag UDPDST_RND"
- pg_set $DEV "udp_dst_min $DST_MIN"
- pg_set $DEV "udp_dst_max $DST_MAX"
+ pg_set $DEV "udp_dst_min $UDP_DST_MIN"
+ pg_set $DEV "udp_dst_max $UDP_DST_MAX"
fi
# Setup random UDP port src range
pg_set $DEV "flag UDPSRC_RND"
-pg_set $DEV "udp_src_min $UDP_MIN"
-pg_set $DEV "udp_src_max $UDP_MAX"
+pg_set $DEV "udp_src_min $UDP_SRC_MIN"
+pg_set $DEV "udp_src_max $UDP_SRC_MAX"
# start_run
echo "Running... ctrl^C to stop" >&2
diff --git a/samples/pktgen/pktgen_sample02_multiqueue.sh b/samples/pktgen/pktgen_sample02_multiqueue.sh
index 7f7a9a27548f..a4726fb50197 100755
--- a/samples/pktgen/pktgen_sample02_multiqueue.sh
+++ b/samples/pktgen/pktgen_sample02_multiqueue.sh
@@ -21,8 +21,8 @@ DELAY="0" # Zero means max speed
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
# Flow variation random source port between min and max
-UDP_MIN=9
-UDP_MAX=109
+UDP_SRC_MIN=9
+UDP_SRC_MAX=109
# (example of setting default params in your script)
if [ -z "$DEST_IP" ]; then
@@ -30,8 +30,8 @@ if [ -z "$DEST_IP" ]; then
fi
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# General cleanup everything since last run
@@ -67,14 +67,14 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
- pg_set $dev "udp_dst_min $DST_MIN"
- pg_set $dev "udp_dst_max $DST_MAX"
+ pg_set $dev "udp_dst_min $UDP_DST_MIN"
+ pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Setup random UDP port src range
pg_set $dev "flag UDPSRC_RND"
- pg_set $dev "udp_src_min $UDP_MIN"
- pg_set $dev "udp_src_max $UDP_MAX"
+ pg_set $dev "udp_src_min $UDP_SRC_MIN"
+ pg_set $dev "udp_src_max $UDP_SRC_MAX"
done
# start_run
diff --git a/samples/pktgen/pktgen_sample03_burst_single_flow.sh b/samples/pktgen/pktgen_sample03_burst_single_flow.sh
index b520637817ce..dfea91a09ccc 100755
--- a/samples/pktgen/pktgen_sample03_burst_single_flow.sh
+++ b/samples/pktgen/pktgen_sample03_burst_single_flow.sh
@@ -34,8 +34,8 @@ fi
[ -z "$CLONE_SKB" ] && CLONE_SKB="0" # No need for clones when bursting
[ -z "$COUNT" ] && COUNT="0" # Zero means indefinitely
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# Base Config
@@ -67,8 +67,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
- pg_set $dev "udp_dst_min $DST_MIN"
- pg_set $dev "udp_dst_max $DST_MAX"
+ pg_set $dev "udp_dst_min $UDP_DST_MIN"
+ pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Setup burst, for easy testing -b 0 disable bursting
diff --git a/samples/pktgen/pktgen_sample04_many_flows.sh b/samples/pktgen/pktgen_sample04_many_flows.sh
index 5b6e9d9cb5b5..7ea9b4a3acf6 100755
--- a/samples/pktgen/pktgen_sample04_many_flows.sh
+++ b/samples/pktgen/pktgen_sample04_many_flows.sh
@@ -18,8 +18,8 @@ source ${basedir}/parameters.sh
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
[ -z "$COUNT" ] && COUNT="0" # Zero means indefinitely
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# NOTICE: Script specific settings
@@ -63,8 +63,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
- pg_set $dev "udp_dst_min $DST_MIN"
- pg_set $dev "udp_dst_max $DST_MAX"
+ pg_set $dev "udp_dst_min $UDP_DST_MIN"
+ pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Randomize source IP-addresses
diff --git a/samples/pktgen/pktgen_sample05_flow_per_thread.sh b/samples/pktgen/pktgen_sample05_flow_per_thread.sh
index 0c06e63fbe97..fbfafe029e11 100755
--- a/samples/pktgen/pktgen_sample05_flow_per_thread.sh
+++ b/samples/pktgen/pktgen_sample05_flow_per_thread.sh
@@ -23,8 +23,8 @@ source ${basedir}/parameters.sh
[ -z "$BURST" ] && BURST=32
[ -z "$COUNT" ] && COUNT="0" # Zero means indefinitely
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# Base Config
@@ -56,8 +56,8 @@ for ((thread = $F_THREAD; thread <= $L_THREAD; thread++)); do
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
- pg_set $dev "udp_dst_min $DST_MIN"
- pg_set $dev "udp_dst_max $DST_MAX"
+ pg_set $dev "udp_dst_min $UDP_DST_MIN"
+ pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Setup source IP-addresses based on thread number
diff --git a/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh b/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
index 97f0266c0356..755e662183f1 100755
--- a/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
+++ b/samples/pktgen/pktgen_sample06_numa_awared_queue_irq_affinity.sh
@@ -20,8 +20,8 @@ DELAY="0" # Zero means max speed
[ -z "$CLONE_SKB" ] && CLONE_SKB="0"
# Flow variation random source port between min and max
-UDP_MIN=9
-UDP_MAX=109
+UDP_SRC_MIN=9
+UDP_SRC_MAX=109
node=`get_iface_node $DEV`
irq_array=(`get_iface_irqs $DEV`)
@@ -36,8 +36,8 @@ if [ -z "$DEST_IP" ]; then
fi
[ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff"
if [ -n "$DST_PORT" ]; then
- read -r DST_MIN DST_MAX <<< $(parse_ports $DST_PORT)
- validate_ports $DST_MIN $DST_MAX
+ read -r UDP_DST_MIN UDP_DST_MAX <<< $(parse_ports $DST_PORT)
+ validate_ports $UDP_DST_MIN $UDP_DST_MAX
fi
# General cleanup everything since last run
@@ -84,14 +84,14 @@ for ((i = 0; i < $THREADS; i++)); do
if [ -n "$DST_PORT" ]; then
# Single destination port or random port range
pg_set $dev "flag UDPDST_RND"
- pg_set $dev "udp_dst_min $DST_MIN"
- pg_set $dev "udp_dst_max $DST_MAX"
+ pg_set $dev "udp_dst_min $UDP_DST_MIN"
+ pg_set $dev "udp_dst_max $UDP_DST_MAX"
fi
# Setup random UDP port src range
pg_set $dev "flag UDPSRC_RND"
- pg_set $dev "udp_src_min $UDP_MIN"
- pg_set $dev "udp_src_max $UDP_MAX"
+ pg_set $dev "udp_src_min $UDP_SRC_MIN"
+ pg_set $dev "udp_src_max $UDP_SRC_MAX"
done
# start_run
--
2.20.1
^ permalink raw reply related
* Re: [RFC bpf-next 0/5] Convert iproute2 to use libbpf (WIP)
From: Andrii Nakryiko @ 2019-08-28 20:40 UTC (permalink / raw)
To: Toke Høiland-Jørgensen
Cc: Daniel Borkmann, Stephen Hemminger, Alexei Starovoitov,
Martin KaFai Lau, Song Liu, Yonghong Song, David Miller,
Jesper Dangaard Brouer, Networking, bpf
In-Reply-To: <87tva8m85t.fsf@toke.dk>
On Fri, Aug 23, 2019 at 4:29 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>
> [ ... snip ...]
>
> > E.g., today's API is essentially three steps:
> >
> > 1. open and parse ELF: collect relos, programs, map definitions
> > 2. load: create maps from collected defs, do program/global data/CO-RE
> > relocs, load and verify BPF programs
> > 3. attach programs one by one.
> >
> > Between step 1 and 2 user has flexibility to create more maps, set up
> > map-in-map, etc. Between 2 and 3 you can fill in global data, fill in
> > tail call maps, etc. That's already pretty flexible. But we can tune
> > and break apart those steps even further, if necessary.
>
> Today, steps 1 and 2 can be collapsed into a single call to
> bpf_prog_load_xattr(). As Jesper's mail explains, for XDP we don't
> generally want to do all the fancy rewriting stuff, we just want a
> simple way to load a program and get reusable pinning of maps.
I agree. See my response to Jesper's message. Note also my view of
bpf_prog_load_xattr() existence.
> Preferably in a way that is compatible with the iproute2 loader.
>
> So I really think we need two things:
>
> (1) a flexible API that splits up all the various steps in a way that
> allows programs to inject their own map definitions before
> relocations and loading
>
> (2) a simple convenience wrapper that loads an object file, does
> something sensible with pinning and map-in-map definitions, and loads
> everything into the kernel.
I agree. I think this wrapper is bpf_object__open + bpf_object__load
(bpf_prog_load_xattr will do as well, if you don't need to do anything
between open and load). I think pinning is simple to add in minimal
form and is pretty non-controversial (there is some ambiguity as to
how to handle merging of prog array maps, or maybe not just prog array
maps, but that can be controlled later through extra flags/attributes,
so I'd start with something sensible as a default behavior).
>
> I'd go so far as to say that (2) should even support system-wide
> configuration, similar to the /etc/iproute2/bpf_pinning file. E.g., an
> /etc/libbpf/pinning.conf file that sets the default pinning directory,
> and makes it possible to set up pin-value-to-subdir mappings like what
> iproute2 does today.
This I'm a bit hesitant about. It feels like it's not library's job to
read some system-wide configs modifying its behavior. We have all
those _xattr methods, which allow to override sensible defaults, I'd
try to go as far as possible with just that before doing
libbpf-specific /etc configs.
>
> Having (2) makes it more likely that all the different custom loaders
> will be compatible with each other, while still allowing people to do
> their own custom thing with (1). And of course, (2) could be implemented
> in terms of (1) internally in libbpf.
>
> In my ideal world, (2) would just use the definition format already in
> iproute2 (this is basically what I implemented already), but if you guys
> don't want to put this into libbpf, I can probably live with the default
I want to avoid having legacy-at-the-time-it-was-added code in libbpf
that we'd need to support for a long time, that solves only iproute2
cases, which is why I'm pushing back. With BTF we can support same
functionality in better form, which is what I want to prioritize and
which will be beneficial to the whole BPF ecosystem.
But I also want to make libbpf useful to iproute2 and other custom
loaders that have to support existing formats, and thus my proposal to
have libbpf provide granular enough APIs to augment default format in
non-intrusive way. Should this be callback-based or not is secondary,
though important to API design, concern.
> format being BTF-based instead. Which would mean that iproute2 I would
> end up with a flow like this:
>
> - When given an elf file, try to run it through the "standard loader"
> (2). If this works, great, proceed to program attach.
>
> - If using (2) fails because it doesn't understand the map definition,
> fall back to a compatibility loader that parses the legacy iproute2
> map definition format and uses (1) to load that.
>
>
> Does the above make sense? :)
It does, yes. Also, with BTF enabled it should be easy to distinguish
between those two (e.g., was bpf_elf_map type used? if yes, then it's
a compatibility format) and not do extra work.
>
> -Toke
^ permalink raw reply
* Re: [PATCH bpf-next V9 1/3] bpf: new helper to obtain namespace data from current task
From: Carlos Antonio Neira Bustos @ 2019-08-28 20:39 UTC (permalink / raw)
To: Yonghong Song
Cc: netdev, Eric Biederman, brouer@redhat.com, bpf@vger.kernel.org
In-Reply-To: <CACiB22jyN9=0ATWWE+x=BoWD6u+8KO+MvBfsFQmcNfkmANb2_w@mail.gmail.com>
Yonghong,
Thanks for the pointer, I fixed this bug, but I found another one that's triggered
now the test program I included in tools/testing/selftests/bpf/test_pidns.
It's seemed that fname was not correctly setup when passing it to filename_lookup.
This is fixed now and I'm doing some more testing.
I think I'll remove the tests on samples/bpf as they are mostly end on -EPERM as
the fix intended.
Is ok to remove them and just focus to finish the self tests code?.
Bests
On Wed, Aug 14, 2019 at 01:25:06AM -0400, carlos antonio neira bustos wrote:
> Thank you very much!
>
> Bests
>
> El mié., 14 de ago. de 2019 00:50, Yonghong Song <yhs@fb.com> escribió:
>
> >
> >
> > On 8/13/19 5:56 PM, Carlos Antonio Neira Bustos wrote:
> > > On Tue, Aug 13, 2019 at 11:11:14PM +0000, Yonghong Song wrote:
> > >>
> > >>
> > >> On 8/13/19 11:47 AM, Carlos Neira wrote:
> > >>> From: Carlos <cneirabustos@gmail.com>
> > >>>
> > >>> New bpf helper bpf_get_current_pidns_info.
> > >>> This helper obtains the active namespace from current and returns
> > >>> pid, tgid, device and namespace id as seen from that namespace,
> > >>> allowing to instrument a process inside a container.
> > >>>
> > >>> Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> > >>> ---
> > >>> fs/internal.h | 2 --
> > >>> fs/namei.c | 1 -
> > >>> include/linux/bpf.h | 1 +
> > >>> include/linux/namei.h | 4 +++
> > >>> include/uapi/linux/bpf.h | 31 ++++++++++++++++++++++-
> > >>> kernel/bpf/core.c | 1 +
> > >>> kernel/bpf/helpers.c | 64
> > ++++++++++++++++++++++++++++++++++++++++++++++++
> > >>> kernel/trace/bpf_trace.c | 2 ++
> > >>> 8 files changed, 102 insertions(+), 4 deletions(-)
> > >>>
> > [...]
> > >>>
> > >>> +BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *,
> > pidns_info, u32,
> > >>> + size)
> > >>> +{
> > >>> + const char *pidns_path = "/proc/self/ns/pid";
> > >>> + struct pid_namespace *pidns = NULL;
> > >>> + struct filename *tmp = NULL;
> > >>> + struct inode *inode;
> > >>> + struct path kp;
> > >>> + pid_t tgid = 0;
> > >>> + pid_t pid = 0;
> > >>> + int ret;
> > >>> + int len;
> > >>
> > >
> > > Thank you very much for catching this!.
> > > Could you share how to replicate this bug?.
> >
> > The config is attached. just run trace_ns_info and you
> > can reproduce the issue.
> >
> > >
> > >> I am running your sample program and get the following kernel bug:
> > >>
> > >> ...
> > >> [ 26.414825] BUG: sleeping function called from invalid context at
> > >> /data/users/yhs/work/net-next/fs
> > >> /dcache.c:843
> > >> [ 26.416314] in_atomic(): 1, irqs_disabled(): 0, pid: 1911, name: ping
> > >> [ 26.417189] CPU: 0 PID: 1911 Comm: ping Tainted: G W
> > >> 5.3.0-rc1+ #280
> > >> [ 26.418182] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
> > >> BIOS 1.9.3-1.el7.centos 04/01/2
> > >> 014
> > >> [ 26.419393] Call Trace:
> > >> [ 26.419697] <IRQ>
> > >> [ 26.419960] dump_stack+0x46/0x5b
> > >> [ 26.420434] ___might_sleep+0xe4/0x110
> > >> [ 26.420894] dput+0x2a/0x200
> > >> [ 26.421265] walk_component+0x10c/0x280
> > >> [ 26.421773] link_path_walk+0x327/0x560
> > >> [ 26.422280] ? proc_ns_dir_readdir+0x1a0/0x1a0
> > >> [ 26.422848] ? path_init+0x232/0x330
> > >> [ 26.423364] path_lookupat+0x88/0x200
> > >> [ 26.423808] ? selinux_parse_skb.constprop.69+0x124/0x430
> > >> [ 26.424521] filename_lookup+0xaf/0x190
> > >> [ 26.425031] ? simple_attr_release+0x20/0x20
> > >> [ 26.425560] bpf_get_current_pidns_info+0xfa/0x190
> > >> [ 26.426168] bpf_prog_83627154cefed596+0xe66/0x1000
> > >> [ 26.426779] trace_call_bpf+0xb5/0x160
> > >> [ 26.427317] ? __netif_receive_skb_core+0x1/0xbb0
> > >> [ 26.427929] ? __netif_receive_skb_core+0x1/0xbb0
> > >> [ 26.428496] kprobe_perf_func+0x4d/0x280
> > >> [ 26.428986] ? tracing_record_taskinfo_skip+0x1a/0x30
> > >> [ 26.429584] ? tracing_record_taskinfo+0xe/0x80
> > >> [ 26.430152] ? ttwu_do_wakeup.isra.114+0xcf/0xf0
> > >> [ 26.430737] ? __netif_receive_skb_core+0x1/0xbb0
> > >> [ 26.431334] ? __netif_receive_skb_core+0x5/0xbb0
> > >> [ 26.431930] kprobe_ftrace_handler+0x90/0xf0
> > >> [ 26.432495] ftrace_ops_assist_func+0x63/0x100
> > >> [ 26.433060] 0xffffffffc03180bf
> > >> [ 26.433471] ? __netif_receive_skb_core+0x1/0xbb0
> > >> ...
> > >>
> > >> To prevent we are running in arbitrary task (e.g., idle task)
> > >> context which may introduce sleeping issues, the following
> > >> probably appropriate:
> > >>
> > >> if (in_nmi() || in_softirq())
> > >> return -EPERM;
> > >>
> > >> Anyway, if in nmi or softirq, the namespace and pid/tgid
> > >> we get may be just accidentally associated with the bpf running
> > >> context, but it could be in a different context. So such info
> > >> is not reliable any way.
> > >>
> > >>> +
> > >>> + if (unlikely(size != sizeof(struct bpf_pidns_info)))
> > >>> + return -EINVAL;
> > >>> + pidns = task_active_pid_ns(current);
> > [...]
> >
^ permalink raw reply
* Re: [PATCH v1 net-next] net: stmmac: Add support for MDIO interrupts
From: David Miller @ 2019-08-28 20:33 UTC (permalink / raw)
To: weifeng.voon
Cc: mcoquelin.stm32, netdev, linux-kernel, joabreu, peppe.cavallaro,
andrew, alexandre.torgue, boon.leong.ong
In-Reply-To: <1566870320-9825-1-git-send-email-weifeng.voon@intel.com>
From: Voon Weifeng <weifeng.voon@intel.com>
Date: Tue, 27 Aug 2019 09:45:20 +0800
> From: "Chuah, Kim Tatt" <kim.tatt.chuah@intel.com>
>
> DW EQoS v5.xx controllers added capability for interrupt generation
> when MDIO interface is done (GMII Busy bit is cleared).
> This patch adds support for this interrupt on supported HW to avoid
> polling on GMII Busy bit.
>
> stmmac_mdio_read() & stmmac_mdio_write() will sleep until wake_up() is
> called by the interrupt handler.
>
> Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
> Reviewed-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
> Reviewed-by: Ong Boon Leong <boon.leong.ong@intel.com>
> Signed-off-by: Chuah, Kim Tatt <kim.tatt.chuah@intel.com>
> Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
> Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
I know there are some design changes that will occur with this patch but
coding style wise:
> @@ -276,6 +284,10 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
> mac->mode = mac->mode ? : entry->mode;
> mac->tc = mac->tc ? : entry->tc;
> mac->mmc = mac->mmc ? : entry->mmc;
> + mac->mdio_intr_en = mac->mdio_intr_en ? : entry->mdio_intr_en;
> +
> + if (mac->mdio_intr_en)
> + init_waitqueue_head(&mac->mdio_busy_wait);
I'd say always unconditionally initialize wait queues, mutexes, etc.
> +static bool stmmac_mdio_intr_done(struct mii_bus *bus)
> +{
> + struct net_device *ndev = bus->priv;
> + struct stmmac_priv *priv = netdev_priv(ndev);
> + unsigned int mii_address = priv->hw->mii.addr;
Reverse christmas tree here, please.
^ permalink raw reply
* [PATCH net-next v2 4/9] r8169: move disabling interrupt coalescing to RTL8169/RTL8168 init
From: Heiner Kallweit @ 2019-08-28 20:26 UTC (permalink / raw)
To: Realtek linux nic maintainers, David Miller
Cc: netdev@vger.kernel.org, Chun-Hao Lin
In-Reply-To: <8181244b-24ac-73e2-bac7-d01f644ebb3f@gmail.com>
RTL8125 doesn't support the same coalescing registers, therefore move
this initialization to the 8168/6169-specific init.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
drivers/net/ethernet/realtek/r8169_main.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 7d89826cb..dc799528f 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5087,6 +5087,9 @@ static void rtl_hw_start_8168(struct rtl8169_private *tp)
RTL_W8(tp, MaxTxPacketSize, TxPacketMax);
rtl_hw_config(tp);
+
+ /* disable interrupt coalescing */
+ RTL_W16(tp, IntrMitigate, 0x0000);
}
static void rtl_hw_start_8169(struct rtl8169_private *tp)
@@ -5110,6 +5113,9 @@ static void rtl_hw_start_8169(struct rtl8169_private *tp)
rtl8169_set_magic_reg(tp, tp->mac_version);
RTL_W32(tp, RxMissed, 0);
+
+ /* disable interrupt coalescing */
+ RTL_W16(tp, IntrMitigate, 0x0000);
}
static void rtl_hw_start(struct rtl8169_private *tp)
@@ -5128,8 +5134,6 @@ static void rtl_hw_start(struct rtl8169_private *tp)
rtl_set_rx_tx_desc_registers(tp);
rtl_lock_config_regs(tp);
- /* disable interrupt coalescing */
- RTL_W16(tp, IntrMitigate, 0x0000);
/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
RTL_R8(tp, IntrMask);
RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb);
--
2.23.0
^ permalink raw reply related
* [PATCH net-next v2 3/9] r8169: factor out reading MAC address from registers
From: Heiner Kallweit @ 2019-08-28 20:25 UTC (permalink / raw)
To: Realtek linux nic maintainers, David Miller
Cc: netdev@vger.kernel.org, Chun-Hao Lin
In-Reply-To: <8181244b-24ac-73e2-bac7-d01f644ebb3f@gmail.com>
For RTL8125 we will have to read the MAC address also from another
register range, therefore create a small helper.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
drivers/net/ethernet/realtek/r8169_main.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index e9d900c11..7d89826cb 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -741,6 +741,14 @@ static bool rtl_supports_eee(struct rtl8169_private *tp)
tp->mac_version != RTL_GIGA_MAC_VER_39;
}
+static void rtl_read_mac_from_reg(struct rtl8169_private *tp, u8 *mac, int reg)
+{
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ mac[i] = RTL_R8(tp, reg + i);
+}
+
struct rtl_cond {
bool (*check)(struct rtl8169_private *);
const char *msg;
@@ -6630,7 +6638,7 @@ static void rtl_init_mac_address(struct rtl8169_private *tp)
{
struct net_device *dev = tp->dev;
u8 *mac_addr = dev->dev_addr;
- int rc, i;
+ int rc;
rc = eth_platform_get_mac_address(tp_to_dev(tp), mac_addr);
if (!rc)
@@ -6640,8 +6648,7 @@ static void rtl_init_mac_address(struct rtl8169_private *tp)
if (is_valid_ether_addr(mac_addr))
goto done;
- for (i = 0; i < ETH_ALEN; i++)
- mac_addr[i] = RTL_R8(tp, MAC0 + i);
+ rtl_read_mac_from_reg(tp, mac_addr, MAC0);
if (is_valid_ether_addr(mac_addr))
goto done;
--
2.23.0
^ permalink raw reply related
* [PATCH net-next v2 9/9] r8169: add support for EEE on RTL8125
From: Heiner Kallweit @ 2019-08-28 20:29 UTC (permalink / raw)
To: Realtek linux nic maintainers, David Miller
Cc: netdev@vger.kernel.org, Chun-Hao Lin
In-Reply-To: <8181244b-24ac-73e2-bac7-d01f644ebb3f@gmail.com>
This adds EEE support for RTL8125 based on the vendor driver.
Supported is EEE for 100Mbps and 1Gbps. Realtek recommended to not yet
enable EEE for 2.5Gbps due to potential compatibility issues. Also
ethtool doesn't support yet controlling EEE for 2.5Gbps and 5Gbps.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
drivers/net/ethernet/realtek/r8169_main.c | 24 +++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 99176a9a8..f337f81e4 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2271,6 +2271,12 @@ static void rtl8168_config_eee_mac(struct rtl8169_private *tp)
rtl_eri_set_bits(tp, 0x1b0, ERIAR_MASK_1111, 0x0003);
}
+static void rtl8125_config_eee_mac(struct rtl8169_private *tp)
+{
+ r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
+ r8168_mac_ocp_modify(tp, 0xeb62, 0, BIT(2) | BIT(1));
+}
+
static void rtl8168f_config_eee_phy(struct rtl8169_private *tp)
{
struct phy_device *phydev = tp->phydev;
@@ -2301,6 +2307,16 @@ static void rtl8168h_config_eee_phy(struct rtl8169_private *tp)
phy_modify_paged(phydev, 0xa42, 0x14, 0x0000, 0x0080);
}
+static void rtl8125_config_eee_phy(struct rtl8169_private *tp)
+{
+ struct phy_device *phydev = tp->phydev;
+
+ rtl8168h_config_eee_phy(tp);
+
+ phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000);
+ phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000);
+}
+
static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -3672,6 +3688,9 @@ static void rtl8125_1_hw_phy_config(struct rtl8169_private *tp)
phy_modify_paged(phydev, 0xbf0, 0x15, 0x0e00, 0x0a00);
phy_modify_paged(phydev, 0xa5c, 0x10, 0x0400, 0x0000);
phy_modify_paged(phydev, 0xa44, 0x11, 0x0000, 0x0800);
+
+ rtl8125_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8125_2_hw_phy_config(struct rtl8169_private *tp)
@@ -3741,6 +3760,9 @@ static void rtl8125_2_hw_phy_config(struct rtl8169_private *tp)
phy_modify_paged(phydev, 0xad4, 0x17, 0x0010, 0x0000);
phy_modify_paged(phydev, 0xa86, 0x15, 0x0001, 0x0000);
phy_modify_paged(phydev, 0xa44, 0x11, 0x0000, 0x0800);
+
+ rtl8125_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl_hw_phy_config(struct net_device *dev)
@@ -5263,6 +5285,8 @@ static void rtl_hw_start_8125_common(struct rtl8169_private *tp)
rtl_udelay_loop_wait_low(tp, &rtl_mac_ocp_e00e_cond, 1000, 10);
+ rtl8125_config_eee_mac(tp);
+
RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
udelay(10);
}
--
2.23.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox