* [PATCH bpf-next 2/3] bpf: btf: add pretty print for hash/lru_hash maps
From: Yonghong Song @ 2018-08-09 15:55 UTC (permalink / raw)
To: ast, daniel, netdev; +Cc: kernel-team
In-Reply-To: <20180809155521.1544888-1-yhs@fb.com>
Commit a26ca7c982cb ("bpf: btf: Add pretty print support to
the basic arraymap") added pretty print support to array map.
This patch adds pretty print for hash and lru_hash maps.
The following example shows the pretty-print result of
a pinned hashmap:
struct map_value {
int count_a;
int count_b;
};
cat /sys/fs/bpf/pinned_hash_map:
87907: {87907,87908}
57354: {37354,57355}
76625: {76625,76626}
...
Signed-off-by: Yonghong Song <yhs@fb.com>
---
kernel/bpf/hashtab.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 513d9dfcf4ee..d6110042e0d9 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -11,9 +11,11 @@
* General Public License for more details.
*/
#include <linux/bpf.h>
+#include <linux/btf.h>
#include <linux/jhash.h>
#include <linux/filter.h>
#include <linux/rculist_nulls.h>
+#include <uapi/linux/btf.h>
#include "percpu_freelist.h"
#include "bpf_lru_list.h"
#include "map_in_map.h"
@@ -1162,6 +1164,44 @@ static void htab_map_free(struct bpf_map *map)
kfree(htab);
}
+static void htab_map_seq_show_elem(struct bpf_map *map, void *key,
+ struct seq_file *m)
+{
+ void *value;
+
+ rcu_read_lock();
+
+ value = htab_map_lookup_elem(map, key);
+ if (!value) {
+ rcu_read_unlock();
+ return;
+ }
+
+ btf_type_seq_show(map->btf, map->btf_key_type_id, key, m);
+ seq_puts(m, ": ");
+ btf_type_seq_show(map->btf, map->btf_value_type_id, value, m);
+ seq_puts(m, "\n");
+
+ rcu_read_unlock();
+}
+
+static int htab_map_check_btf(const struct bpf_map *map, const struct btf *btf,
+ u32 btf_key_id, u32 btf_value_id)
+{
+ const struct btf_type *key_type, *value_type;
+ u32 key_size, value_size;
+
+ key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
+ if (!key_type || key_size != map->key_size)
+ return -EINVAL;
+
+ value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
+ if (!value_type || value_size != map->value_size)
+ return -EINVAL;
+
+ return 0;
+}
+
const struct bpf_map_ops htab_map_ops = {
.map_alloc_check = htab_map_alloc_check,
.map_alloc = htab_map_alloc,
@@ -1171,6 +1211,8 @@ const struct bpf_map_ops htab_map_ops = {
.map_update_elem = htab_map_update_elem,
.map_delete_elem = htab_map_delete_elem,
.map_gen_lookup = htab_map_gen_lookup,
+ .map_seq_show_elem = htab_map_seq_show_elem,
+ .map_check_btf = htab_map_check_btf,
};
const struct bpf_map_ops htab_lru_map_ops = {
@@ -1182,6 +1224,8 @@ const struct bpf_map_ops htab_lru_map_ops = {
.map_update_elem = htab_lru_map_update_elem,
.map_delete_elem = htab_lru_map_delete_elem,
.map_gen_lookup = htab_lru_map_gen_lookup,
+ .map_seq_show_elem = htab_map_seq_show_elem,
+ .map_check_btf = htab_map_check_btf,
};
/* Called from eBPF program */
--
2.14.3
^ permalink raw reply related
* [PATCH bpf-next 0/3] bpf: add bpffs pretty print for hash/lru_hash maps
From: Yonghong Song @ 2018-08-09 15:55 UTC (permalink / raw)
To: ast, daniel, netdev; +Cc: kernel-team
Commit a26ca7c982cb ("bpf: btf: Add pretty print support to
the basic arraymap") added pretty print support to array map.
This patch adds pretty print for hash and lru_hash maps.
The following example shows the pretty-print result of a pinned hashmap.
Without this patch set, user will get an error instead.
struct map_value {
int count_a;
int count_b;
};
cat /sys/fs/bpf/pinned_hash_map:
87907: {87907,87908}
57354: {37354,57355}
76625: {76625,76626}
...
Patch #1 fixed a bug in bpffs map_seq_next() function so that
all elements in the hash table will be traversed.
Patch #2 implemented map_seq_show_elem() and map_check_btf()
callback functions for hash and lru hash maps.
Patch #3 enhanced tools/testing/selftests/bpf/test_btf.c to
test bpffs hash and lru hash map pretty print.
Yonghong Song (3):
bpf: fix bpffs non-array map seq_show issue
bpf: btf: add pretty print for hash/lru_hash maps
tools/bpf: add bpffs pretty print btf test for hash/lru_hash maps
kernel/bpf/hashtab.c | 44 +++++++++++++++++
kernel/bpf/inode.c | 8 ++--
tools/testing/selftests/bpf/test_btf.c | 87 ++++++++++++++++++++++++++++------
3 files changed, 121 insertions(+), 18 deletions(-)
--
2.14.3
^ permalink raw reply
* [PATCH bpf-next 3/3] tools/bpf: add bpffs pretty print btf test for hash/lru_hash maps
From: Yonghong Song @ 2018-08-09 15:55 UTC (permalink / raw)
To: ast, daniel, netdev; +Cc: kernel-team
In-Reply-To: <20180809155521.1544888-1-yhs@fb.com>
Pretty print tests for hash/lru_hash maps are added in test_btf.c.
The btf type blob is the same as pretty print array map test.
The test result:
$ mount -t bpf bpf /sys/fs/bpf
$ ./test_btf -p
BTF pretty print array......OK
BTF pretty print hash......OK
BTF pretty print lru hash......OK
PASS:3 SKIP:0 FAIL:0
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/testing/selftests/bpf/test_btf.c | 87 ++++++++++++++++++++++++++++------
1 file changed, 72 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c
index ffdd27737c9e..7fa8c800c540 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -131,6 +131,8 @@ struct btf_raw_test {
__u32 max_entries;
bool btf_load_err;
bool map_create_err;
+ bool ordered_map;
+ bool lossless_map;
int hdr_len_delta;
int type_off_delta;
int str_off_delta;
@@ -2093,8 +2095,7 @@ struct pprint_mapv {
} aenum;
};
-static struct btf_raw_test pprint_test = {
- .descr = "BTF pretty print test #1",
+static struct btf_raw_test pprint_test_template = {
.raw_types = {
/* unsighed char */ /* [1] */
BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1),
@@ -2146,8 +2147,6 @@ static struct btf_raw_test pprint_test = {
},
.str_sec = "\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum",
.str_sec_size = sizeof("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"),
- .map_type = BPF_MAP_TYPE_ARRAY,
- .map_name = "pprint_test",
.key_size = sizeof(unsigned int),
.value_size = sizeof(struct pprint_mapv),
.key_type_id = 3, /* unsigned int */
@@ -2155,6 +2154,40 @@ static struct btf_raw_test pprint_test = {
.max_entries = 128 * 1024,
};
+static struct btf_pprint_test_meta {
+ const char *descr;
+ enum bpf_map_type map_type;
+ const char *map_name;
+ bool ordered_map;
+ bool lossless_map;
+} pprint_tests_meta[] = {
+{
+ .descr = "BTF pretty print array",
+ .map_type = BPF_MAP_TYPE_ARRAY,
+ .map_name = "pprint_test_array",
+ .ordered_map = true,
+ .lossless_map = true,
+},
+
+{
+ .descr = "BTF pretty print hash",
+ .map_type = BPF_MAP_TYPE_HASH,
+ .map_name = "pprint_test_hash",
+ .ordered_map = false,
+ .lossless_map = true,
+},
+
+{
+ .descr = "BTF pretty print lru hash",
+ .map_type = BPF_MAP_TYPE_LRU_HASH,
+ .map_name = "pprint_test_lru_hash",
+ .ordered_map = false,
+ .lossless_map = false,
+},
+
+};
+
+
static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i)
{
v->ui32 = i;
@@ -2166,10 +2199,12 @@ static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i)
v->aenum = i & 0x03;
}
-static int test_pprint(void)
+static int do_test_pprint(void)
{
- const struct btf_raw_test *test = &pprint_test;
+ const struct btf_raw_test *test = &pprint_test_template;
struct bpf_create_map_attr create_attr = {};
+ unsigned int key, nr_read_elems;
+ bool ordered_map, lossless_map;
int map_fd = -1, btf_fd = -1;
struct pprint_mapv mapv = {};
unsigned int raw_btf_size;
@@ -2178,7 +2213,6 @@ static int test_pprint(void)
char pin_path[255];
size_t line_len = 0;
char *line = NULL;
- unsigned int key;
uint8_t *raw_btf;
ssize_t nread;
int err, ret;
@@ -2251,14 +2285,18 @@ static int test_pprint(void)
goto done;
}
- key = 0;
+ nr_read_elems = 0;
+ ordered_map = test->ordered_map;
+ lossless_map = test->lossless_map;
do {
ssize_t nexpected_line;
+ unsigned int next_key;
- set_pprint_mapv(&mapv, key);
+ next_key = ordered_map ? nr_read_elems : atoi(line);
+ set_pprint_mapv(&mapv, next_key);
nexpected_line = snprintf(expected_line, sizeof(expected_line),
"%u: {%u,0,%d,0x%x,0x%x,0x%x,{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n",
- key,
+ next_key,
mapv.ui32, mapv.si32,
mapv.unused_bits2a, mapv.bits28, mapv.unused_bits2b,
mapv.ui64,
@@ -2281,11 +2319,12 @@ static int test_pprint(void)
}
nread = getline(&line, &line_len, pin_file);
- } while (++key < test->max_entries && nread > 0);
+ } while (++nr_read_elems < test->max_entries && nread > 0);
- if (CHECK(key < test->max_entries,
- "Unexpected EOF. key:%u test->max_entries:%u",
- key, test->max_entries)) {
+ if (lossless_map &&
+ CHECK(nr_read_elems < test->max_entries,
+ "Unexpected EOF. nr_read_elems:%u test->max_entries:%u",
+ nr_read_elems, test->max_entries)) {
err = -1;
goto done;
}
@@ -2314,6 +2353,24 @@ static int test_pprint(void)
return err;
}
+static int test_pprint(void)
+{
+ unsigned int i;
+ int err = 0;
+
+ for (i = 0; i < ARRAY_SIZE(pprint_tests_meta); i++) {
+ pprint_test_template.descr = pprint_tests_meta[i].descr;
+ pprint_test_template.map_type = pprint_tests_meta[i].map_type;
+ pprint_test_template.map_name = pprint_tests_meta[i].map_name;
+ pprint_test_template.ordered_map = pprint_tests_meta[i].ordered_map;
+ pprint_test_template.lossless_map = pprint_tests_meta[i].lossless_map;
+
+ err |= count_result(do_test_pprint());
+ }
+
+ return err;
+}
+
static void usage(const char *cmd)
{
fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] | [-g test_num (1 - %zu)] | [-f test_num (1 - %zu)] | [-p]]\n",
@@ -2409,7 +2466,7 @@ int main(int argc, char **argv)
err |= test_file();
if (args.pprint_test)
- err |= count_result(test_pprint());
+ err |= test_pprint();
if (args.raw_test || args.get_info_test || args.file_test ||
args.pprint_test)
--
2.14.3
^ permalink raw reply related
* [PATCH bpf-next 1/3] bpf: fix bpffs non-array map seq_show issue
From: Yonghong Song @ 2018-08-09 15:55 UTC (permalink / raw)
To: ast, daniel, netdev; +Cc: kernel-team
In-Reply-To: <20180809155521.1544888-1-yhs@fb.com>
In function map_seq_next() of kernel/bpf/inode.c,
the first key will be the "0" regardless of the map type.
This works for array. But for hash type, if it happens
key "0" is in the map, the bpffs map show will miss
some items if the key "0" is not the first element of
the first bucket.
This patch fixed the issue by guaranteeing to get
the first element, if the seq_show is just started,
by passing NULL pointer key to map_get_next_key() callback.
This way, no missing elements will occur for
bpffs hash table show even if key "0" is in the map.
Fixes: a26ca7c982cb5 ("bpf: btf: Add pretty print support to the basic arraymap")
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Yonghong Song <yhs@fb.com>
---
kernel/bpf/inode.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index 76efe9a183f5..fc5b103512e7 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -196,19 +196,21 @@ static void *map_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
struct bpf_map *map = seq_file_to_map(m);
void *key = map_iter(m)->key;
+ void *prev_key;
if (map_iter(m)->done)
return NULL;
if (unlikely(v == SEQ_START_TOKEN))
- goto done;
+ prev_key = NULL;
+ else
+ prev_key = key;
- if (map->ops->map_get_next_key(map, key, key)) {
+ if (map->ops->map_get_next_key(map, prev_key, key)) {
map_iter(m)->done = true;
return NULL;
}
-done:
++(*pos);
return key;
}
--
2.14.3
^ permalink raw reply related
* Re: [PATCH bpf] bpf: fix bpffs non-array map seq_show issue
From: Daniel Borkmann @ 2018-08-09 15:59 UTC (permalink / raw)
To: Yonghong Song, Alexei Starovoitov
Cc: ast, netdev, kernel-team, jakub.kicinski
In-Reply-To: <e984a0f6-16f4-73f3-70bb-177e787529a4@fb.com>
On 08/09/2018 05:15 PM, Yonghong Song wrote:
> On 8/9/18 7:24 AM, Daniel Borkmann wrote:
>> On 08/09/2018 05:55 AM, Yonghong Song wrote:
>>> On 8/8/18 7:25 PM, Alexei Starovoitov wrote:
>>>> On Wed, Aug 08, 2018 at 06:25:19PM -0700, Yonghong Song wrote:
>>>>> In function map_seq_next() of kernel/bpf/inode.c,
>>>>> the first key will be the "0" regardless of the map type.
>>>>> This works for array. But for hash type, if it happens
>>>>> key "0" is in the map, the bpffs map show will miss
>>>>> some items if the key "0" is not the first element of
>>>>> the first bucket.
>>>>>
>>>>> This patch fixed the issue by guaranteeing to get
>>>>> the first element, if the seq_show is just started,
>>>>> by passing NULL pointer key to map_get_next_key() callback.
>>>>> This way, no missing elements will occur for
>>>>> bpffs hash table show even if key "0" is in the map.
>>>
>>> Currently, map_seq_show_elem callback is only implemented
>>> for arraymap. So the problem actually is not exposed.
>>>
>>> The issue is discovered when I tried to implement
>>> map_seq_show_elem for hash maps, and I will have followup
>>> patches for it.
Btw, on that note, I would also prefer if we could decouple
BTF from the map_seq_show_elem() as there is really no reason
to have it on a per-map. I had a patch below which would enable
it for all map types generically, and bpftool works out of the
box for it. Also, array doesn't really have to be 'int' type
enforced as long as it's some data structure with 4 bytes, it's
all fine, so this can be made fully generic (we only eventually
care about the match in size).
>From 0a8be27cbc2ac0c6fc2632865b5afe37222a1fc7 Mon Sep 17 00:00:00 2001
Message-Id: <0a8be27cbc2ac0c6fc2632865b5afe37222a1fc7.1533830053.git.daniel@iogearbox.net>
From: Daniel Borkmann <daniel@iogearbox.net>
Date: Thu, 9 Aug 2018 16:50:21 +0200
Subject: [PATCH bpf-next] bpf, btf: enable for all maps
# bpftool m dump id 19
[{
"key": {
"": {
"vip": 0,
"vipv6": []
},
"port": 0,
"family": 0,
"proto": 0
},
"value": {
"flags": 0,
"vip_num": 0
}
}
]
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/bpf.h | 4 +---
kernel/bpf/arraymap.c | 27 ---------------------------
kernel/bpf/inode.c | 3 ++-
kernel/bpf/syscall.c | 24 ++++++++++++++++++++----
4 files changed, 23 insertions(+), 35 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index cd8790d..91aa4be 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -48,8 +48,6 @@ struct bpf_map_ops {
u32 (*map_fd_sys_lookup_elem)(void *ptr);
void (*map_seq_show_elem)(struct bpf_map *map, void *key,
struct seq_file *m);
- int (*map_check_btf)(const struct bpf_map *map, const struct btf *btf,
- u32 key_type_id, u32 value_type_id);
};
struct bpf_map {
@@ -118,7 +116,7 @@ static inline bool bpf_map_offload_neutral(const struct bpf_map *map)
static inline bool bpf_map_support_seq_show(const struct bpf_map *map)
{
- return map->ops->map_seq_show_elem && map->ops->map_check_btf;
+ return map->ops->map_seq_show_elem;
}
extern const struct bpf_map_ops bpf_map_offload_ops;
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 2aa55d030..67f0bdf 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -358,32 +358,6 @@ static void array_map_seq_show_elem(struct bpf_map *map, void *key,
rcu_read_unlock();
}
-static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
- u32 btf_key_id, u32 btf_value_id)
-{
- const struct btf_type *key_type, *value_type;
- u32 key_size, value_size;
- u32 int_data;
-
- key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
- if (!key_type || BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
- return -EINVAL;
-
- int_data = *(u32 *)(key_type + 1);
- /* bpf array can only take a u32 key. This check makes
- * sure that the btf matches the attr used during map_create.
- */
- if (BTF_INT_BITS(int_data) != 32 || key_size != 4 ||
- BTF_INT_OFFSET(int_data))
- return -EINVAL;
-
- value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
- if (!value_type || value_size != map->value_size)
- return -EINVAL;
-
- return 0;
-}
-
const struct bpf_map_ops array_map_ops = {
.map_alloc_check = array_map_alloc_check,
.map_alloc = array_map_alloc,
@@ -394,7 +368,6 @@ const struct bpf_map_ops array_map_ops = {
.map_delete_elem = array_map_delete_elem,
.map_gen_lookup = array_map_gen_lookup,
.map_seq_show_elem = array_map_seq_show_elem,
- .map_check_btf = array_map_check_btf,
};
const struct bpf_map_ops percpu_array_map_ops = {
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index 76efe9a..400f27d 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -332,7 +332,8 @@ static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
struct bpf_map *map = arg;
return bpf_mkobj_ops(dentry, mode, arg, &bpf_map_iops,
- map->btf ? &bpffs_map_fops : &bpffs_obj_fops);
+ bpf_map_support_seq_show(map) ?
+ &bpffs_map_fops : &bpffs_obj_fops);
}
static struct dentry *
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 5af4e9e..0b6f6e8 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -455,6 +455,23 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
return 0;
}
+static int map_check_btf(const struct bpf_map *map, const struct btf *btf,
+ u32 btf_key_id, u32 btf_value_id)
+{
+ const struct btf_type *key_type, *value_type;
+ u32 key_size, value_size;
+
+ key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
+ if (!key_type || key_size != map->key_size)
+ return -EINVAL;
+
+ value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
+ if (!value_type || value_size != map->value_size)
+ return -EINVAL;
+
+ return 0;
+}
+
#define BPF_MAP_CREATE_LAST_FIELD btf_value_type_id
/* called via syscall */
static int map_create(union bpf_attr *attr)
@@ -489,8 +506,7 @@ static int map_create(union bpf_attr *attr)
atomic_set(&map->refcnt, 1);
atomic_set(&map->usercnt, 1);
- if (bpf_map_support_seq_show(map) &&
- (attr->btf_key_type_id || attr->btf_value_type_id)) {
+ if (attr->btf_key_type_id || attr->btf_value_type_id) {
struct btf *btf;
if (!attr->btf_key_type_id || !attr->btf_value_type_id) {
@@ -504,8 +520,8 @@ static int map_create(union bpf_attr *attr)
goto free_map_nouncharge;
}
- err = map->ops->map_check_btf(map, btf, attr->btf_key_type_id,
- attr->btf_value_type_id);
+ err = map_check_btf(map, btf, attr->btf_key_type_id,
+ attr->btf_value_type_id);
if (err) {
btf_put(btf);
goto free_map_nouncharge;
--
2.9.5
^ permalink raw reply related
* Re: [Query]: DSA Understanding
From: Lad, Prabhakar @ 2018-08-09 16:03 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev
In-Reply-To: <20180809153543.GD20006@lunn.ch>
[-- Attachment #1: Type: text/plain, Size: 2567 bytes --]
Hi Andrew,
Thanks for your support.
On Thu, Aug 9, 2018 at 4:35 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > > > The received packets captured on the PC are MDNS and DHPC, these MDNS
> > > > are causing the rx
> > > > packet counter go up:
> > >
> > > And where are these packets coming from? The target device? Or some
> > > other device on your network?
> > >
> > AFIK, MDNS is also kind of a bcast its sending MDNS requests and
> > receiving itself,
> > that’s the reason rx packets are incrementing (correct me if I am wrong)
>
> Your Ethernet device should not be receiving its own
> transmissions. Looping back for broadcast and multicast packets
> happens higher up in the network stack.
>
> Look at the source MAC address for these packets. Where are the coming
> from?
>
Its coming from the switch lan4 I have attached the png, where
C4:F3:12:08:FE:7F is
the mac of lan4, which is broadcast to ff:ff:ff:ff:ff:ff, which is
causing rx counter on
PC to go up.
> > ~$ ethtool -S lan4
> > NIC statistics:
> ...
> > tx_hi: 0
> > tx_late_col: 0
> > tx_pause: 0
> > tx_bcast: 749
> > tx_mcast: 212
>
> This suggest the switch is putting packets onto the wire.
>
> > Only weird thing I notice on target, when its replying for ping
> > requests ( (oui Unknown) is that something which is causing issues ?
>
> These are not ping requests. These are ARP requests/replies.
>
Yes my bad.
> > 08:11:20.230704 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has
> > VB4-SN00000000 tell tango-charlie.local, length 46
> > 08:11:20.230749 ARP, Ethernet (len 6), IPv4 (len 4), Reply
> > VB4-SN00000000 is-at c4:f3:12:08:fe:7f (oui Unknown), length 28
> > 08:11:21.230629 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has
> > VB4-SN00000000 tell tango-charlie.local, length 46
> > 08:11:21.230657 ARP, Ethernet (len 6), IPv4 (len 4), Reply
> > VB4-SN00000000 is-at c4:f3:12:08:fe:7f (oui Unknown), length 28
> > 08:11:22.247831 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has
> > VB4-SN00000000 tell tango-charlie.local, length 46
> > 08:11:22.247857 ARP, Ethernet (len 6), IPv4 (len 4), Reply
> > VB4-SN00000000 is-at c4:f3:12:08:fe:7f (oui Unknown), length 28
>
> c4:f3:12 is the OUI. It is actually registers to TI:
>
> https://aruljohn.com/mac/C4F312
>
> But tcpdump probably does not know this, or the build you have has the
> oui table removed to keep the binary small.
>
Yes I built it on yocto, probably to reduce they have small build.
Cheers,
--Prabhakar
[-- Attachment #2: frame.png --]
[-- Type: image/png, Size: 1281475 bytes --]
^ permalink raw reply
* Re: [PATCH bpf-next] BPF: helpers: New helper to obtain namespace data from current task
From: Carlos Neira @ 2018-08-09 16:07 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Carlos Neira, netdev, ebiederm, quentin.monnet, ys114321
In-Reply-To: <20180809154653.40396ce3@redhat.com>
Jesper,
Here is the updated patch.
>From 92633f6819423093932e8d04aa3dc99a5913f6fd Mon Sep 17 00:00:00 2001
From: Carlos Neira <cneirabustos@gmail.com>
Date: Thu, 9 Aug 2018 09:55:32 -0400
Subject: [PATCH bpf-next] BPF: helpers: New helper to obtain namespace
data from current task
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.
Device is read from /proc/self/ns/pid, as in the future it's possible that
different pid_ns files may belong to different devices, according
to the discussion between Eric Biederman and Yonghong in 2017 linux plumbers
conference.
Currently bpf_get_current_pid_tgid(), is used to do pid filtering in bcc's
scripts but this helper returns the pid as seen by the root namespace which is
fine when a bcc script is not executed inside a container.
When the process of interest is inside a container, pid filtering will not work
if bpf_get_current_pid_tgid() is used. This helper addresses this limitation
returning the pid as it's seen by the current namespace where the script is
executing.
This helper has the same use cases as bpf_get_current_pid_tgid() as it can be
used to do pid filtering even inside a container.
For example a bcc script using bpf_get_current_pid_tgid() (tools/funccount.py):
u32 pid = bpf_get_current_pid_tgid() >> 32;
if (pid != <pid_arg_passed_in>)
return 0;
Could be modified to use bpf_get_current_pidns_info() as follows:
struct bpf_pidns pidns;
bpf_get_current_pidns_info(&pidns, sizeof(struct bpf_pidns));
u32 pid = pidns.tgid;
u32 nsid = pidns.nsid;
if ((pid != <pid_arg_passed_in>) && (nsid != <nsid_arg_passed_in>))
return 0;
To find out the name PID namespace id of a process, you could use this command:
$ ps -h -o pidns -p <pid_of_interest>
Or this other command:
$ ls -Li /proc/<pid_of_interest>/ns/pid
Signed-off-by: Carlos Antonio Neira Bustos <cneirabustos@gmail.com>
---
include/linux/bpf.h | 1 +
include/uapi/linux/bpf.h | 24 +++++++++++-
kernel/bpf/core.c | 1 +
kernel/bpf/helpers.c | 64 +++++++++++++++++++++++++++++++
kernel/trace/bpf_trace.c | 2 +
samples/bpf/Makefile | 3 ++
samples/bpf/trace_ns_info_user.c | 35 +++++++++++++++++
samples/bpf/trace_ns_info_user_kern.c | 45 ++++++++++++++++++++++
tools/include/uapi/linux/bpf.h | 24 +++++++++++-
tools/testing/selftests/bpf/bpf_helpers.h | 3 ++
10 files changed, 200 insertions(+), 2 deletions(-)
create mode 100644 samples/bpf/trace_ns_info_user.c
create mode 100644 samples/bpf/trace_ns_info_user_kern.c
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index cd8790d2c6ed..3f4b999f7c99 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -787,6 +787,7 @@ extern const struct bpf_func_proto bpf_get_stack_proto;
extern const struct bpf_func_proto bpf_sock_map_update_proto;
extern const struct bpf_func_proto bpf_sock_hash_update_proto;
extern const struct bpf_func_proto bpf_get_current_cgroup_id_proto;
+extern const struct bpf_func_proto bpf_get_current_pidns_info_proto;
extern const struct bpf_func_proto bpf_get_local_storage_proto;
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index dd5758dc35d3..8462f9881465 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2113,6 +2113,18 @@ union bpf_attr {
* the shared data.
* Return
* Pointer to the local storage area.
+ *
+ * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 size_of_pidns)
+ * Description
+ * Copies into *pidns* pid, namespace id and tgid as seen by the
+ * current namespace and also device from /proc/self/ns/pid.
+ * *size_of_pidns* must be the size of *pidns*
+ *
+ * This helper is used when pid filtering is needed inside a
+ * container as bpf_get_current_tgid() helper returns always the
+ * pid id as seen by the root namespace.
+ * Return
+ * 0 on success -EINVAL on error.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -2196,7 +2208,8 @@ union bpf_attr {
FN(rc_keydown), \
FN(skb_cgroup_id), \
FN(get_current_cgroup_id), \
- FN(get_local_storage),
+ FN(get_local_storage), \
+ FN(get_current_pidns_info),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
@@ -2724,4 +2737,13 @@ enum bpf_task_fd_type {
BPF_FD_TYPE_URETPROBE, /* filename + offset */
};
+/* helper bpf_get_current_pidns_info will store the following
+ * data, dev will contain major/minor from /proc/self/ns/pid.
+ */
+struct bpf_pidns_info {
+ __u32 dev;
+ __u32 nsid;
+ __u32 tgid;
+ __u32 pid;
+};
#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 4d09e610777f..98ce53ce2ea6 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1796,6 +1796,7 @@ const struct bpf_func_proto bpf_sock_map_update_proto __weak;
const struct bpf_func_proto bpf_sock_hash_update_proto __weak;
const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
const struct bpf_func_proto bpf_get_local_storage_proto __weak;
+const struct bpf_func_proto bpf_get_current_pidns_info __weak;
const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
{
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 1991466b8327..d06d723b9cff 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -18,6 +18,9 @@
#include <linux/sched.h>
#include <linux/uidgid.h>
#include <linux/filter.h>
+#include <linux/pid_namespace.h>
+#include <linux/major.h>
+#include <linux/stat.h>
/* If kernel subsystem is allowing eBPF programs to call this function,
* inside its own verifier_ops->get_func_proto() callback it should return
@@ -214,3 +217,64 @@ const struct bpf_func_proto bpf_get_local_storage_proto = {
.arg2_type = ARG_ANYTHING,
};
#endif
+
+BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *, pidns_info, u32,
+ size)
+{
+ const char *ppath = "/proc/self/ns/pid";
+ struct pid_namespace *pidns = NULL;
+ mm_segment_t oldsegfs;
+ struct kstat stat;
+ pid_t tgid = 0;
+ pid_t pid = 0;
+ int res = 0;
+
+ if (unlikely(size != sizeof(struct bpf_pidns_info)))
+ goto clear;
+
+ pidns = task_active_pid_ns(current);
+
+ if (unlikely(!pidns))
+ goto clear;
+
+ pidns_info->nsid = pidns->ns.inum;
+ pid = task_pid_nr_ns(current, pidns);
+
+ if (unlikely(!pid))
+ goto clear;
+
+ tgid = task_tgid_nr_ns(current, pidns);
+
+ if (unlikely(!tgid))
+ goto clear;
+
+ pidns_info->tgid = (u32) tgid;
+ pidns_info->pid = (u32) pid;
+
+ oldsegfs = get_fs();
+ set_fs(KERNEL_DS);
+ res = vfs_stat((const char __user *)ppath, &stat);
+ set_fs(oldsegfs);
+
+ if (unlikely(res))
+ goto clear;
+
+ pidns_info->dev = stat.dev;
+
+ return 0;
+
+clear:
+ if (pidns_info)
+ memset((void *)pidns, 0, (size_t) size);
+
+ return -EINVAL;
+}
+
+const struct bpf_func_proto bpf_get_current_pidns_info_proto = {
+ .func = bpf_get_current_pidns_info,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_UNINIT_MEM,
+ .arg2_type = ARG_CONST_SIZE,
+};
+
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 0ae6829804bc..f70be29e49ab 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -568,6 +568,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
case BPF_FUNC_get_current_cgroup_id:
return &bpf_get_current_cgroup_id_proto;
#endif
+ case BPF_FUNC_get_current_pidns_info:
+ return &bpf_get_current_pidns_info_proto;
default:
return NULL;
}
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index f88d5683d6ee..fdcde00554ce 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -53,6 +53,7 @@ hostprogs-y += xdpsock
hostprogs-y += xdp_fwd
hostprogs-y += task_fd_query
hostprogs-y += xdp_sample_pkts
+hostprogs-y += trace_ns_info
# Libbpf dependencies
LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
@@ -109,6 +110,7 @@ xdpsock-objs := xdpsock_user.o
xdp_fwd-objs := xdp_fwd_user.o
task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
+trace_ns_info-objs := bpf_load.o trace_ns_info_user.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
@@ -166,6 +168,7 @@ always += xdpsock_kern.o
always += xdp_fwd_kern.o
always += task_fd_query_kern.o
always += xdp_sample_pkts_kern.o
+always += trace_ns_info_user_kern.o
HOSTCFLAGS += -I$(objtree)/usr/include
HOSTCFLAGS += -I$(srctree)/tools/lib/
diff --git a/samples/bpf/trace_ns_info_user.c b/samples/bpf/trace_ns_info_user.c
new file mode 100644
index 000000000000..e06d08db6f30
--- /dev/null
+++ b/samples/bpf/trace_ns_info_user.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <linux/bpf.h>
+#include <unistd.h>
+#include "bpf/libbpf.h"
+#include "bpf_load.h"
+
+/* This code was taken verbatim from tracex1_user.c, it's used
+ * to exercize bpf_get_current_pidns_info() helper call.
+ */
+int main(int ac, char **argv)
+{
+ FILE *f;
+ char filename[256];
+
+ snprintf(filename, sizeof(filename), "%s_user_kern.o", argv[0]);
+ printf("loading %s\n", filename);
+
+ if (load_bpf_file(filename)) {
+ printf("%s", bpf_log_buf);
+ return 1;
+ }
+
+ f = popen("taskset 1 ping localhost", "r");
+ (void) f;
+ read_trace_pipe();
+ return 0;
+}
diff --git a/samples/bpf/trace_ns_info_user_kern.c b/samples/bpf/trace_ns_info_user_kern.c
new file mode 100644
index 000000000000..ceaf3e83c8e7
--- /dev/null
+++ b/samples/bpf/trace_ns_info_user_kern.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+typedef __u64 u64;
+typedef __u32 u32;
+
+
+/* kprobe is NOT a stable ABI
+ * kernel functions can be removed, renamed or completely change semantics.
+ * Number of arguments and their positions can change, etc.
+ * In such case this bpf+kprobe example will no longer be meaningful
+ */
+
+/* This will call bpf_get_current_pidns_info() to display pid and ns values
+ * as seen by the current namespace, on the far left you will see the pid as
+ * seen as by the root namespace.
+ */
+
+SEC("kprobe/__netif_receive_skb_core")
+int bpf_prog1(struct pt_regs *ctx)
+{
+ char fmt[] = "nsid:%u, dev: %u, pid:%u\n";
+ struct bpf_pidns_info nsinfo;
+ int ok = 0;
+
+ ok = bpf_get_current_pidns_info(&nsinfo, sizeof(nsinfo));
+ if (ok == 0)
+ bpf_trace_printk(fmt, sizeof(fmt), (u32)nsinfo.nsid,
+ (u32) nsinfo.dev, (u32)nsinfo.pid);
+
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index dd5758dc35d3..8462f9881465 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2113,6 +2113,18 @@ union bpf_attr {
* the shared data.
* Return
* Pointer to the local storage area.
+ *
+ * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 size_of_pidns)
+ * Description
+ * Copies into *pidns* pid, namespace id and tgid as seen by the
+ * current namespace and also device from /proc/self/ns/pid.
+ * *size_of_pidns* must be the size of *pidns*
+ *
+ * This helper is used when pid filtering is needed inside a
+ * container as bpf_get_current_tgid() helper returns always the
+ * pid id as seen by the root namespace.
+ * Return
+ * 0 on success -EINVAL on error.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -2196,7 +2208,8 @@ union bpf_attr {
FN(rc_keydown), \
FN(skb_cgroup_id), \
FN(get_current_cgroup_id), \
- FN(get_local_storage),
+ FN(get_local_storage), \
+ FN(get_current_pidns_info),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
@@ -2724,4 +2737,13 @@ enum bpf_task_fd_type {
BPF_FD_TYPE_URETPROBE, /* filename + offset */
};
+/* helper bpf_get_current_pidns_info will store the following
+ * data, dev will contain major/minor from /proc/self/ns/pid.
+ */
+struct bpf_pidns_info {
+ __u32 dev;
+ __u32 nsid;
+ __u32 tgid;
+ __u32 pid;
+};
#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index cb9fcfbc9307..c3060f3284e0 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -137,6 +137,9 @@ static unsigned long long (*bpf_get_current_cgroup_id)(void) =
(void *) BPF_FUNC_get_current_cgroup_id;
static void *(*bpf_get_local_storage)(void *map, unsigned long long flags) =
(void *) BPF_FUNC_get_local_storage;
+static int (*bpf_get_current_pidns_info)(struct bpf_pidns_info *buf,
+ unsigned int buf_size) =
+ (void *) BPF_FUNC_get_current_pidns_info;
/* llvm builtin functions that eBPF C program may use to
* emit BPF_LD_ABS and BPF_LD_IND instructions
--
2.11.0
On Thu, Aug 09, 2018 at 03:46:53PM +0200, Jesper Dangaard Brouer wrote:
> On Thu, 9 Aug 2018 09:18:00 -0400
> Carlos Neira <cneirabustos@gmail.com> wrote:
>
> > From: cneira <cneirabustos@gmail.com>
> >
> > 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.
> > Device is read from /proc/self/ns/pid, as in the future it's possible that
> > different pid_ns files may belong to different devices, according
> > to the discussion between Eric Biederman and Yonghong in 2017 linux plumbers
> > conference.
> >
> > Currently bpf_get_current_pid_tgid(), is used to do pid filtering in bcc's
> > scripts but this helper returns the pid as seen by the root namespace which is
> > fine when a bcc script is not executed inside a container.
> > When the process of interest is inside a container, pid filtering will not work
> > if bpf_get_current_pid_tgid() is used. This helper addresses this limitation
> > returning the pid as it's seen by the current namespace where the script is
> > executing.
> >
> > This helper has the same use cases as bpf_get_current_pid_tgid() as it can be
> > used to do pid filtering even inside a container.
> >
> > For example a bcc script using bpf_get_current_pid_tgid() (tools/funccount.py):
> >
> > u32 pid = bpf_get_current_pid_tgid() >> 32;
> > if (pid != <pid_arg_passed_in>)
> > return 0;
> >
> > Could be modified to use bpf_get_current_pidns_info() as follows:
> >
> > struct bpf_pidns pidns;
> > bpf_get_current_pid_tgid(&pidns, sizeof(struct bpf_pidns));
> ^^^^^^^^^^^^^^^^^^^^^^^^
>
> Shouldn't this be:
> bpf_get_current_pidns_info(...)
>
> > u32 pid = pidns.tgid;
> > u32 nsid = pidns.nsid;
> > if ((pid != <pid_arg_passed_in>) && (nsid != <nsid_arg_passed_in>))
> > return 0;
> >
>
> [...]
>
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index dd5758dc35d3..031e7d9dba09 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -2113,6 +2113,18 @@ union bpf_attr {
> > * the shared data.
> > * Return
> > * Pointer to the local storage area.
> > + *
> > + * int bpf_get_current_pidns(struct bpf_pidns_info *pidns, u32 size_of_pidns)
>
> Should this be:
> bpf_get_current_pidns_info(...)
>
> > + * Description
> > + * Copies into *pidns* pid, namespace id and tgid as seen by the
> > + * current namespace and also device from /proc/self/ns/pid.
> > + * *size_of_pidns* must be the size of *pidns*
> > + *
> > + * This helper is used when pid filtering is needed inside a
> > + * container as bpf_get_current_tgid() helper returns always the
> > + * pid id as seen by the root namespace.
> > + * Return
> > + * 0 on success -EINVAL on error.
> > */
> > #define __BPF_FUNC_MAPPER(FN) \
> > FN(unspec), \
> > @@ -2196,7 +2208,8 @@ union bpf_attr {
> > FN(rc_keydown), \
> > FN(skb_cgroup_id), \
> > FN(get_current_cgroup_id), \
> > - FN(get_local_storage),
> > + FN(get_local_storage), \
> > + FN(get_current_pidns_info),
>
> --
> Best regards,
> Jesper Dangaard Brouer
> MSc.CS, Principal Kernel Engineer at Red Hat
> LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply related
* Re: [PATCH iproute2/net-next] tc_util: Add support for showing TCA_STATS_BASIC_HW statistics
From: Stephen Hemminger @ 2018-08-09 16:07 UTC (permalink / raw)
To: Eelco Chaudron; +Cc: netdev, davem
In-Reply-To: <20180809151602.5951.21421.stgit@wsfd-netdev20.ntdv.lab.eng.bos.redhat.com>
On Thu, 9 Aug 2018 11:16:02 -0400
Eelco Chaudron <echaudro@redhat.com> wrote:
>
> +static void print_tcstats_basic_hw(struct rtattr **tbs, char *prefix)
> +{
> + struct gnet_stats_basic bs = {0};
If not present don't print it rather than printing zero.
> + struct gnet_stats_basic bs_hw = {0};
This initialization is unnecessary since you always overwrite it.
> +
> + if (!tbs[TCA_STATS_BASIC_HW])
> + return;
> +
> + memcpy(&bs_hw, RTA_DATA(tbs[TCA_STATS_BASIC_HW]),
> + MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC_HW]), sizeof(bs_hw)));
> +
> + if (bs_hw.bytes == 0 && bs_hw.packets == 0)
> + return;
> +
> + if (tbs[TCA_STATS_BASIC]) {
> + memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]),
> + MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]),
> + sizeof(bs)));
> + }
> +
> + if (bs.bytes >= bs_hw.bytes && bs.packets >= bs_hw.packets) {
> + print_string(PRINT_FP, NULL, "\n%s", prefix);
Please use the magic string _SL_ to allow supporting single line output mode.
> + print_lluint(PRINT_ANY, "sw_bytes",
> + "Sent software %llu bytes",
> + bs.bytes - bs_hw.bytes);
> + print_uint(PRINT_ANY, "sw_packets", " %u pkt",
> + bs.packets - bs_hw.packets);
> + }
> +
> + print_string(PRINT_FP, NULL, "\n%s", prefix);
> + print_lluint(PRINT_ANY, "hw_bytes", "Sent hardware %llu bytes",
> + bs_hw.bytes);
> + print_uint(PRINT_ANY, "hw_packets", " %u pkt", bs_hw.packets);
> +}
^ permalink raw reply
* we found that
From: Tony @ 2018-08-09 13:43 UTC (permalink / raw)
To: netdev
We just found that you need image editing.
We are an image studio, we do all kinds of image editing such as for
e-commerce photos, jewelry images
and portrait mages.
Our service includes cutting out and clipping path etc , we also do
retouching.
You may send us a photo, testing will be provided to check our quality
Thanks,
Tony Glenn
^ permalink raw reply
* in our studio
From: Tony @ 2018-08-09 14:01 UTC (permalink / raw)
To: netdev
We just found that you need image editing.
We are an image studio, we do all kinds of image editing such as for
e-commerce photos, jewelry images
and portrait mages.
Our service includes cutting out and clipping path etc , we also do
retouching.
You may send us a photo, testing will be provided to check our quality
Thanks,
Tony Glenn
^ permalink raw reply
* provide image solutions
From: Tony @ 2018-08-09 12:13 UTC (permalink / raw)
To: netdev
We just found that you need image editing.
We are an image studio, we do all kinds of image editing such as for
e-commerce photos, jewelry images
and portrait mages.
Our service includes cutting out and clipping path etc , we also do
retouching.
You may send us a photo, testing will be provided to check our quality
Thanks,
Tony Glenn
^ permalink raw reply
* Re: [PATCH net-next v2 1/1] net/tls: Combined memory allocation for decryption request
From: Dave Watson @ 2018-08-09 16:25 UTC (permalink / raw)
To: Vakul Garg; +Cc: netdev, borisp, aviadye, davem
In-Reply-To: <20180808232623.18075-2-vakul.garg@nxp.com>
On 08/09/18 04:56 AM, Vakul Garg wrote:
> For preparing decryption request, several memory chunks are required
> (aead_req, sgin, sgout, iv, aad). For submitting the decrypt request to
> an accelerator, it is required that the buffers which are read by the
> accelerator must be dma-able and not come from stack. The buffers for
> aad and iv can be separately kmalloced each, but it is inefficient.
> This patch does a combined allocation for preparing decryption request
> and then segments into aead_req || sgin || sgout || iv || aad.
>
> Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Reviewed-by: Dave Watson <davejwatson@fb.com>
Thanks, looks good to me now.
^ permalink raw reply
* Re: [PATCH bpf-next 1/3] bpf: add bpf queue map
From: Alexei Starovoitov @ 2018-08-09 16:23 UTC (permalink / raw)
To: Mauricio Vasquez; +Cc: Daniel Borkmann, Alexei Starovoitov, netdev
In-Reply-To: <867e95e1-cb45-54c8-ce66-d3e49161d5e6@polito.it>
On Thu, Aug 09, 2018 at 09:51:49AM -0500, Mauricio Vasquez wrote:
>
> > Agree that existing ops are not the right alias, but deferring to user
> > space as inline function also doesn't really seem like a good fit, imho,
> > so I'd prefer rather to have something native. (Aside from that, the
> > above inline bpf_pop() would also race between CPUs.)
>
> I think we should have push/pop/peek syscalls as well, having a bpf_pop()
> that is race prone would create problems. Users expected maps operations to
> be safe, so having one that is not will confuse them.
agree the races are not acceptable.
How about a mixed solution:
- introduce bpf_push/pop/peak helpers that programs will use, so
they don't need to pass useless key=NULL
- introduce map->ops->lookup_and_delete and map->ops->lookup_or_init
that prog-side helpers can use and syscall has 1-1 mapping for
Native lookup_or_init() helper for programs and syscall is badly missing.
Most of the bcc scripts use it and bcc has a racy workaround.
Similarly lookup_and_delete() syscall is 1-1 to pop() for stack/queue
and useful for regular hash maps.
At the end for stack/queue map the programs will use:
int bpf_push(map, value);
value_or_null = bpf_pop(map); // guaranteed non-racy for multi-cpu
value_or_null = bpf_peak(map); // racy if 2+ cpus doing it
from syscall:
bpf_map_lookup_elem(map, NULL, &value); // returns top of stack
bpf_map_lookup_and_delete_elem(map, NULL, &value); // returns top and deletes top atomically
bpf_map_update_elem(map, NULL, &value); // pushes new value into stack atomically
Eventually hash and other maps will implement bpf_map_lookup_and_delete()
for both bpf progs and syscall.
The main point that prog-side api doesn't have to match 1-1 to syscall-side,
since they're different enough already.
Like lookup_or_init() is badly needed for programs, but unnecessary for syscall.
Thoughts?
^ permalink raw reply
* [PATCH net-next 0/4] new mechanism to ACK immediately
From: Yuchung Cheng @ 2018-08-09 16:38 UTC (permalink / raw)
To: davem, edumazet; +Cc: netdev, ncardwell, brakmo, weiwan, Yuchung Cheng
This patch is a follow-up feature improvement to the recent fixes on
the performance issues in ECN (delayed) ACKs. Many of the fixes use
tcp_enter_quickack_mode routine to force immediate ACKs. However the
routine also reset tracking interactive session. This is not ideal
because these immediate ACKs are required by protocol specifics
unrelated to the interactiveness nature of the application.
This patch set introduces a new flag to send a one-time immediate ACK
without changing the status of interactive session tracking. With this
patch set the immediate ACKs are generated upon these protocol states:
1) When a hole is repaired
2) When CE status changes between subsequent data packets received
3) When a data packet carries CWR flag
Yuchung Cheng (4):
tcp: mandate a one-time immediate ACK
tcp: avoid resetting ACK timer in DCTCP
tcp: always ACK immediately on hole repairs
tcp: avoid resetting ACK timer upon receiving packet with ECN CWR flag
include/net/inet_connection_sock.h | 3 ++-
net/ipv4/tcp_dctcp.c | 4 ++--
net/ipv4/tcp_input.c | 16 +++++++++-------
3 files changed, 13 insertions(+), 10 deletions(-)
--
2.18.0.597.ga71716f1ad-goog
^ permalink raw reply
* [PATCH net-next 1/4] tcp: mandate a one-time immediate ACK
From: Yuchung Cheng @ 2018-08-09 16:38 UTC (permalink / raw)
To: davem, edumazet; +Cc: netdev, ncardwell, brakmo, weiwan, Yuchung Cheng
In-Reply-To: <20180809163812.58365-1-ycheng@google.com>
Add a new flag to indicate a one-time immediate ACK. This flag is
occasionaly set under specific TCP protocol states in addition to
the more common quickack mechanism for interactive application.
In several cases in the TCP code we want to force an immediate ACK
but do not want to call tcp_enter_quickack_mode() because we do
not want to forget the icsk_ack.pingpong or icsk_ack.ato state.
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Wei Wang <weiwan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/net/inet_connection_sock.h | 3 ++-
net/ipv4/tcp_input.c | 4 +++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 0a6c9e0f2b5a..fa43b82607d9 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -167,7 +167,8 @@ enum inet_csk_ack_state_t {
ICSK_ACK_SCHED = 1,
ICSK_ACK_TIMER = 2,
ICSK_ACK_PUSHED = 4,
- ICSK_ACK_PUSHED2 = 8
+ ICSK_ACK_PUSHED2 = 8,
+ ICSK_ACK_NOW = 16 /* Send the next ACK immediately (once) */
};
void inet_csk_init_xmit_timers(struct sock *sk,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 715d541b52dd..b8849588c440 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5179,7 +5179,9 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
(tp->rcv_nxt - tp->copied_seq < sk->sk_rcvlowat ||
__tcp_select_window(sk) >= tp->rcv_wnd)) ||
/* We ACK each frame or... */
- tcp_in_quickack_mode(sk)) {
+ tcp_in_quickack_mode(sk) ||
+ /* Protocol state mandates a one-time immediate ACK */
+ inet_csk(sk)->icsk_ack.pending & ICSK_ACK_NOW) {
send_now:
tcp_send_ack(sk);
return;
--
2.18.0.597.ga71716f1ad-goog
^ permalink raw reply related
* [PATCH net-next 2/4] tcp: avoid resetting ACK timer in DCTCP
From: Yuchung Cheng @ 2018-08-09 16:38 UTC (permalink / raw)
To: davem, edumazet; +Cc: netdev, ncardwell, brakmo, weiwan, Yuchung Cheng
In-Reply-To: <20180809163812.58365-1-ycheng@google.com>
The recent fix of acking immediately in DCTCP on CE status change
has an undesirable side-effect: it also resets TCP ack timer and
disables pingpong mode (interactive session). But the CE status
change has nothing to do with them. This patch addresses that by
using the new one-time immediate ACK flag instead of calling
tcp_enter_quickack_mode().
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Wei Wang <weiwan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp_dctcp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c
index 8b637f9f23a2..ca61e2a659e7 100644
--- a/net/ipv4/tcp_dctcp.c
+++ b/net/ipv4/tcp_dctcp.c
@@ -136,7 +136,7 @@ static void dctcp_ce_state_0_to_1(struct sock *sk)
*/
if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER)
__tcp_send_ack(sk, ca->prior_rcv_nxt);
- tcp_enter_quickack_mode(sk, 1);
+ inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
}
ca->prior_rcv_nxt = tp->rcv_nxt;
@@ -157,7 +157,7 @@ static void dctcp_ce_state_1_to_0(struct sock *sk)
*/
if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER)
__tcp_send_ack(sk, ca->prior_rcv_nxt);
- tcp_enter_quickack_mode(sk, 1);
+ inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
}
ca->prior_rcv_nxt = tp->rcv_nxt;
--
2.18.0.597.ga71716f1ad-goog
^ permalink raw reply related
* [PATCH net-next 3/4] tcp: always ACK immediately on hole repairs
From: Yuchung Cheng @ 2018-08-09 16:38 UTC (permalink / raw)
To: davem, edumazet; +Cc: netdev, ncardwell, brakmo, weiwan, Yuchung Cheng
In-Reply-To: <20180809163812.58365-1-ycheng@google.com>
RFC 5681 sec 4.2:
To provide feedback to senders recovering from losses, the receiver
SHOULD send an immediate ACK when it receives a data segment that
fills in all or part of a gap in the sequence space.
When a gap is partially filled, __tcp_ack_snd_check already checks
the out-of-order queue and correctly send an immediate ACK. However
when a gap is fully filled, the previous implementation only resets
pingpong mode which does not guarantee an immediate ACK because the
quick ACK counter may be zero. This patch addresses this issue by
marking the one-time immediate ACK flag instead.
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Wei Wang <weiwan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp_input.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b8849588c440..9a09ff3afef2 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4735,11 +4735,11 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
if (!RB_EMPTY_ROOT(&tp->out_of_order_queue)) {
tcp_ofo_queue(sk);
- /* RFC2581. 4.2. SHOULD send immediate ACK, when
+ /* RFC5681. 4.2. SHOULD send immediate ACK, when
* gap in queue is filled.
*/
if (RB_EMPTY_ROOT(&tp->out_of_order_queue))
- inet_csk(sk)->icsk_ack.pingpong = 0;
+ inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
}
if (tp->rx_opt.num_sacks)
--
2.18.0.597.ga71716f1ad-goog
^ permalink raw reply related
* [PATCH net-next 4/4] tcp: avoid resetting ACK timer upon receiving packet with ECN CWR flag
From: Yuchung Cheng @ 2018-08-09 16:38 UTC (permalink / raw)
To: davem, edumazet; +Cc: netdev, ncardwell, brakmo, weiwan, Yuchung Cheng
In-Reply-To: <20180809163812.58365-1-ycheng@google.com>
Previously commit 9aee40006190 ("tcp: ack immediately when a cwr
packet arrives") calls tcp_enter_quickack_mode to force sending
two immediate ACKs upon receiving a packet w/ CWR flag. The side
effect is it'll also reset the delayed ACK timer and interactive
session tracking. This patch removes that side effect by using the
new ACK_NOW flag to force an immmediate ACK.
Packetdrill to demonstrate:
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_CONGESTION, "dctcp", 5) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [ect0] SEW 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > SE. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.1 < [ect0] . 1:1(0) ack 1 win 257
+0 accept(3, ..., ...) = 4
+0 < [ect0] . 1:1001(1000) ack 1 win 257
+0 > [ect01] . 1:1(0) ack 1001
+0 write(4, ..., 1) = 1
+0 > [ect01] P. 1:2(1) ack 1001
+0 < [ect0] . 1001:2001(1000) ack 2 win 257
+0 write(4, ..., 1) = 1
+0 > [ect01] P. 2:3(1) ack 2001
+0 < [ect0] . 2001:3001(1000) ack 3 win 257
+0 < [ect0] . 3001:4001(1000) ack 3 win 257
// Ack delayed ...
+.01 < [ce] P. 4001:4501(500) ack 3 win 257
+0 > [ect01] . 3:3(0) ack 4001
+0 > [ect01] E. 3:3(0) ack 4501
+.001 read(4, ..., 4500) = 4500
+0 write(4, ..., 1) = 1
+0 > [ect01] PE. 3:4(1) ack 4501 win 100
+.01 < [ect0] W. 4501:5501(1000) ack 4 win 257
// No delayed ACK on CWR flag
+0 > [ect01] . 4:4(0) ack 5501
+.31 < [ect0] . 5501:6501(1000) ack 4 win 257
+0 > [ect01] . 4:4(0) ack 6501
Fixes: 9aee40006190 ("tcp: ack immediately when a cwr packet arrives")
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
---
net/ipv4/tcp_input.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9a09ff3afef2..4c2dd9f863f7 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -245,16 +245,16 @@ static void tcp_ecn_queue_cwr(struct tcp_sock *tp)
tp->ecn_flags |= TCP_ECN_QUEUE_CWR;
}
-static void tcp_ecn_accept_cwr(struct tcp_sock *tp, const struct sk_buff *skb)
+static void tcp_ecn_accept_cwr(struct sock *sk, const struct sk_buff *skb)
{
if (tcp_hdr(skb)->cwr) {
- tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR;
+ tcp_sk(sk)->ecn_flags &= ~TCP_ECN_DEMAND_CWR;
/* If the sender is telling us it has entered CWR, then its
* cwnd may be very low (even just 1 packet), so we should ACK
* immediately.
*/
- tcp_enter_quickack_mode((struct sock *)tp, 2);
+ inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
}
}
@@ -4703,7 +4703,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
skb_dst_drop(skb);
__skb_pull(skb, tcp_hdr(skb)->doff * 4);
- tcp_ecn_accept_cwr(tp, skb);
+ tcp_ecn_accept_cwr(sk, skb);
tp->rx_opt.dsack = 0;
--
2.18.0.597.ga71716f1ad-goog
^ permalink raw reply related
* Re: [DO NOT MERGE] ARM: dts: vf610-zii-dev-rev-c: add support for SFF modules
From: Marek Behún @ 2018-08-09 16:44 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, Russell King, Florian Fainelli, nikita.yoush, Chris Healy,
Russell King
In-Reply-To: <1533822210-20633-1-git-send-email-andrew@lunn.ch>
Hi Andres,
I tried your patches on Turris Mox with one 6190 marvell switch with
port 9 connected to CPU and port 10 to SFP cage.
Seems it works :)
Thank you.
Marek
^ permalink raw reply
* Error running AF_XDP sample application
From: kdjimeli @ 2018-08-09 16:18 UTC (permalink / raw)
To: netdev
Hello,
I have been trying to test a sample AF_XDP program, but I have been
experiencing some issues.
After building the sample code
https://github.com/torvalds/linux/tree/master/samples/bpf,
when running the xdpsock binary, I get the errors
"libbpf: failed to create map (name: 'xsks_map'): Invalid argument"
"libbpf: failed to load object './xdpsock_kern.o"
I tried to figure out the cause of the error but all I know is that it
occurs at line 910 with the function
call "bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)".
Please I would like to inquire what could be a possible for this error.
Thanks
Konrad
^ permalink raw reply
* Re: [PATCH bpf] bpf: fix bpffs non-array map seq_show issue
From: Yonghong Song @ 2018-08-09 16:55 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: ast, netdev, kernel-team, jakub.kicinski
In-Reply-To: <9b44c0d6-d236-75ed-abb6-2d945ceb6b81@iogearbox.net>
On 8/9/18 8:59 AM, Daniel Borkmann wrote:
> On 08/09/2018 05:15 PM, Yonghong Song wrote:
>> On 8/9/18 7:24 AM, Daniel Borkmann wrote:
>>> On 08/09/2018 05:55 AM, Yonghong Song wrote:
>>>> On 8/8/18 7:25 PM, Alexei Starovoitov wrote:
>>>>> On Wed, Aug 08, 2018 at 06:25:19PM -0700, Yonghong Song wrote:
>>>>>> In function map_seq_next() of kernel/bpf/inode.c,
>>>>>> the first key will be the "0" regardless of the map type.
>>>>>> This works for array. But for hash type, if it happens
>>>>>> key "0" is in the map, the bpffs map show will miss
>>>>>> some items if the key "0" is not the first element of
>>>>>> the first bucket.
>>>>>>
>>>>>> This patch fixed the issue by guaranteeing to get
>>>>>> the first element, if the seq_show is just started,
>>>>>> by passing NULL pointer key to map_get_next_key() callback.
>>>>>> This way, no missing elements will occur for
>>>>>> bpffs hash table show even if key "0" is in the map.
>>>>
>>>> Currently, map_seq_show_elem callback is only implemented
>>>> for arraymap. So the problem actually is not exposed.
>>>>
>>>> The issue is discovered when I tried to implement
>>>> map_seq_show_elem for hash maps, and I will have followup
>>>> patches for it.
>
> Btw, on that note, I would also prefer if we could decouple
> BTF from the map_seq_show_elem() as there is really no reason
> to have it on a per-map. I had a patch below which would enable
> it for all map types generically, and bpftool works out of the
> box for it. Also, array doesn't really have to be 'int' type
> enforced as long as it's some data structure with 4 bytes, it's
> all fine, so this can be made fully generic (we only eventually
> care about the match in size).
I agree with a generic map_check_btf as mostly we only care about size
and this change should enable btftool btf based pretty print for
hash/lru_hash tables.
>
> From 0a8be27cbc2ac0c6fc2632865b5afe37222a1fc7 Mon Sep 17 00:00:00 2001
> Message-Id: <0a8be27cbc2ac0c6fc2632865b5afe37222a1fc7.1533830053.git.daniel@iogearbox.net>
> From: Daniel Borkmann <daniel@iogearbox.net>
> Date: Thu, 9 Aug 2018 16:50:21 +0200
> Subject: [PATCH bpf-next] bpf, btf: enable for all maps
>
> # bpftool m dump id 19
> [{
> "key": {
> "": {
> "vip": 0,
> "vipv6": []
> },
> "port": 0,
> "family": 0,
> "proto": 0
> },
> "value": {
> "flags": 0,
> "vip_num": 0
> }
> }
> ]
>
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> ---
> include/linux/bpf.h | 4 +---
> kernel/bpf/arraymap.c | 27 ---------------------------
> kernel/bpf/inode.c | 3 ++-
> kernel/bpf/syscall.c | 24 ++++++++++++++++++++----
> 4 files changed, 23 insertions(+), 35 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index cd8790d..91aa4be 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -48,8 +48,6 @@ struct bpf_map_ops {
> u32 (*map_fd_sys_lookup_elem)(void *ptr);
> void (*map_seq_show_elem)(struct bpf_map *map, void *key,
> struct seq_file *m);
> - int (*map_check_btf)(const struct bpf_map *map, const struct btf *btf,
> - u32 key_type_id, u32 value_type_id);
> };
>
> struct bpf_map {
> @@ -118,7 +116,7 @@ static inline bool bpf_map_offload_neutral(const struct bpf_map *map)
>
> static inline bool bpf_map_support_seq_show(const struct bpf_map *map)
> {
> - return map->ops->map_seq_show_elem && map->ops->map_check_btf;
> + return map->ops->map_seq_show_elem;
> }
>
> extern const struct bpf_map_ops bpf_map_offload_ops;
> diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
> index 2aa55d030..67f0bdf 100644
> --- a/kernel/bpf/arraymap.c
> +++ b/kernel/bpf/arraymap.c
> @@ -358,32 +358,6 @@ static void array_map_seq_show_elem(struct bpf_map *map, void *key,
> rcu_read_unlock();
> }
>
> -static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
> - u32 btf_key_id, u32 btf_value_id)
> -{
> - const struct btf_type *key_type, *value_type;
> - u32 key_size, value_size;
> - u32 int_data;
> -
> - key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
> - if (!key_type || BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
> - return -EINVAL;
> -
> - int_data = *(u32 *)(key_type + 1);
> - /* bpf array can only take a u32 key. This check makes
> - * sure that the btf matches the attr used during map_create.
> - */
> - if (BTF_INT_BITS(int_data) != 32 || key_size != 4 ||
> - BTF_INT_OFFSET(int_data))
> - return -EINVAL;
> -
> - value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
> - if (!value_type || value_size != map->value_size)
> - return -EINVAL;
> -
> - return 0;
> -}
> -
> const struct bpf_map_ops array_map_ops = {
> .map_alloc_check = array_map_alloc_check,
> .map_alloc = array_map_alloc,
> @@ -394,7 +368,6 @@ const struct bpf_map_ops array_map_ops = {
> .map_delete_elem = array_map_delete_elem,
> .map_gen_lookup = array_map_gen_lookup,
> .map_seq_show_elem = array_map_seq_show_elem,
> - .map_check_btf = array_map_check_btf,
> };
>
> const struct bpf_map_ops percpu_array_map_ops = {
> diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
> index 76efe9a..400f27d 100644
> --- a/kernel/bpf/inode.c
> +++ b/kernel/bpf/inode.c
> @@ -332,7 +332,8 @@ static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
> struct bpf_map *map = arg;
>
> return bpf_mkobj_ops(dentry, mode, arg, &bpf_map_iops,
> - map->btf ? &bpffs_map_fops : &bpffs_obj_fops);
> + bpf_map_support_seq_show(map) ?
> + &bpffs_map_fops : &bpffs_obj_fops);
There are an issue here, the condition bpf_map_support_seq_show(map) may
not be enough since the map specific implementation assumes availability
of btf and proper map key/value btf_type_id's.
We can either use
map->btf && bpf_map_support_seq_show(map)
condition here, or check map->btf in each individual implementation
of map_support_seq_show().
> }
>
> static struct dentry *
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 5af4e9e..0b6f6e8 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -455,6 +455,23 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
> return 0;
> }
>
> +static int map_check_btf(const struct bpf_map *map, const struct btf *btf,
> + u32 btf_key_id, u32 btf_value_id)
> +{
> + const struct btf_type *key_type, *value_type;
> + u32 key_size, value_size;
> +
> + key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
> + if (!key_type || key_size != map->key_size)
> + return -EINVAL;
> +
> + value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
> + if (!value_type || value_size != map->value_size)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> #define BPF_MAP_CREATE_LAST_FIELD btf_value_type_id
> /* called via syscall */
> static int map_create(union bpf_attr *attr)
> @@ -489,8 +506,7 @@ static int map_create(union bpf_attr *attr)
> atomic_set(&map->refcnt, 1);
> atomic_set(&map->usercnt, 1);
>
> - if (bpf_map_support_seq_show(map) &&
> - (attr->btf_key_type_id || attr->btf_value_type_id)) {
> + if (attr->btf_key_type_id || attr->btf_value_type_id) {
> struct btf *btf;
>
> if (!attr->btf_key_type_id || !attr->btf_value_type_id) {
> @@ -504,8 +520,8 @@ static int map_create(union bpf_attr *attr)
> goto free_map_nouncharge;
> }
>
> - err = map->ops->map_check_btf(map, btf, attr->btf_key_type_id,
> - attr->btf_value_type_id);
> + err = map_check_btf(map, btf, attr->btf_key_type_id,
> + attr->btf_value_type_id);
> if (err) {
> btf_put(btf);
> goto free_map_nouncharge;
>
^ permalink raw reply
* Re: [PATCH iproute2/net-next] tc_util: Add support for showing TCA_STATS_BASIC_HW statistics
From: Eelco Chaudron @ 2018-08-09 16:56 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, davem
In-Reply-To: <20180809090723.3caf4b3f@xeon-e3>
Thanks for the quick reply, see inline responses.
On 9 Aug 2018, at 18:07, Stephen Hemminger wrote:
> On Thu, 9 Aug 2018 11:16:02 -0400
> Eelco Chaudron <echaudro@redhat.com> wrote:
>
>>
>> +static void print_tcstats_basic_hw(struct rtattr **tbs, char
>> *prefix)
>> +{
>> + struct gnet_stats_basic bs = {0};
>
> If not present don't print it rather than printing zero.
>
This is used to print separate SW counters below, which is not displayed
if 0, i.e. not present.
However I will move it under the “if (tbs[TCA_STATS_BASIC])”
statement, so it’s more explicit.
>> + struct gnet_stats_basic bs_hw = {0};
>
> This initialization is unnecessary since you always overwrite it.
>
Thanks will remove it in the v2
>> +
>> + if (!tbs[TCA_STATS_BASIC_HW])
>> + return;
>> +
>> + memcpy(&bs_hw, RTA_DATA(tbs[TCA_STATS_BASIC_HW]),
>> + MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC_HW]), sizeof(bs_hw)));
>> +
>> + if (bs_hw.bytes == 0 && bs_hw.packets == 0)
>> + return;
>> +
>> + if (tbs[TCA_STATS_BASIC]) {
>> + memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]),
>> + MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]),
>> + sizeof(bs)));
>> + }
>> +
>> + if (bs.bytes >= bs_hw.bytes && bs.packets >= bs_hw.packets) {
>> + print_string(PRINT_FP, NULL, "\n%s", prefix);
>
> Please use the magic string _SL_ to allow supporting single line
> output mode.
>
Will do in the V2.
>> + print_lluint(PRINT_ANY, "sw_bytes",
>> + "Sent software %llu bytes",
>> + bs.bytes - bs_hw.bytes);
>> + print_uint(PRINT_ANY, "sw_packets", " %u pkt",
>> + bs.packets - bs_hw.packets);
>> + }
>> +
>> + print_string(PRINT_FP, NULL, "\n%s", prefix);
>> + print_lluint(PRINT_ANY, "hw_bytes", "Sent hardware %llu bytes",
>> + bs_hw.bytes);
>> + print_uint(PRINT_ANY, "hw_packets", " %u pkt", bs_hw.packets);
>> +}
^ permalink raw reply
* Re: [PATCH bpf] bpf: fix bpffs non-array map seq_show issue
From: Daniel Borkmann @ 2018-08-09 17:02 UTC (permalink / raw)
To: Yonghong Song, Alexei Starovoitov
Cc: ast, netdev, kernel-team, jakub.kicinski
In-Reply-To: <99a17600-57c8-06fc-c555-83dc8793f174@fb.com>
On 08/09/2018 06:55 PM, Yonghong Song wrote:
> On 8/9/18 8:59 AM, Daniel Borkmann wrote:
>> On 08/09/2018 05:15 PM, Yonghong Song wrote:
>>> On 8/9/18 7:24 AM, Daniel Borkmann wrote:
>>>> On 08/09/2018 05:55 AM, Yonghong Song wrote:
>>>>> On 8/8/18 7:25 PM, Alexei Starovoitov wrote:
>>>>>> On Wed, Aug 08, 2018 at 06:25:19PM -0700, Yonghong Song wrote:
>>>>>>> In function map_seq_next() of kernel/bpf/inode.c,
>>>>>>> the first key will be the "0" regardless of the map type.
>>>>>>> This works for array. But for hash type, if it happens
>>>>>>> key "0" is in the map, the bpffs map show will miss
>>>>>>> some items if the key "0" is not the first element of
>>>>>>> the first bucket.
>>>>>>>
>>>>>>> This patch fixed the issue by guaranteeing to get
>>>>>>> the first element, if the seq_show is just started,
>>>>>>> by passing NULL pointer key to map_get_next_key() callback.
>>>>>>> This way, no missing elements will occur for
>>>>>>> bpffs hash table show even if key "0" is in the map.
>>>>>
>>>>> Currently, map_seq_show_elem callback is only implemented
>>>>> for arraymap. So the problem actually is not exposed.
>>>>>
>>>>> The issue is discovered when I tried to implement
>>>>> map_seq_show_elem for hash maps, and I will have followup
>>>>> patches for it.
>>
>> Btw, on that note, I would also prefer if we could decouple
>> BTF from the map_seq_show_elem() as there is really no reason
>> to have it on a per-map. I had a patch below which would enable
>> it for all map types generically, and bpftool works out of the
>> box for it. Also, array doesn't really have to be 'int' type
>> enforced as long as it's some data structure with 4 bytes, it's
>> all fine, so this can be made fully generic (we only eventually
>> care about the match in size).
>
> I agree with a generic map_check_btf as mostly we only care about size
> and this change should enable btftool btf based pretty print for hash/lru_hash tables.
Yep, agree, the below output from bpftool is from test_xdp_noinline.o
where both work with it.
>> From 0a8be27cbc2ac0c6fc2632865b5afe37222a1fc7 Mon Sep 17 00:00:00 2001
>> Message-Id: <0a8be27cbc2ac0c6fc2632865b5afe37222a1fc7.1533830053.git.daniel@iogearbox.net>
>> From: Daniel Borkmann <daniel@iogearbox.net>
>> Date: Thu, 9 Aug 2018 16:50:21 +0200
>> Subject: [PATCH bpf-next] bpf, btf: enable for all maps
>>
>> # bpftool m dump id 19
>> [{
>> "key": {
>> "": {
>> "vip": 0,
>> "vipv6": []
>> },
>> "port": 0,
>> "family": 0,
>> "proto": 0
>> },
>> "value": {
>> "flags": 0,
>> "vip_num": 0
>> }
>> }
>> ]
>>
>> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
>> ---
>> include/linux/bpf.h | 4 +---
>> kernel/bpf/arraymap.c | 27 ---------------------------
>> kernel/bpf/inode.c | 3 ++-
>> kernel/bpf/syscall.c | 24 ++++++++++++++++++++----
>> 4 files changed, 23 insertions(+), 35 deletions(-)
>>
>> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
>> index cd8790d..91aa4be 100644
>> --- a/include/linux/bpf.h
>> +++ b/include/linux/bpf.h
>> @@ -48,8 +48,6 @@ struct bpf_map_ops {
>> u32 (*map_fd_sys_lookup_elem)(void *ptr);
>> void (*map_seq_show_elem)(struct bpf_map *map, void *key,
>> struct seq_file *m);
>> - int (*map_check_btf)(const struct bpf_map *map, const struct btf *btf,
>> - u32 key_type_id, u32 value_type_id);
>> };
>>
>> struct bpf_map {
>> @@ -118,7 +116,7 @@ static inline bool bpf_map_offload_neutral(const struct bpf_map *map)
>>
>> static inline bool bpf_map_support_seq_show(const struct bpf_map *map)
>> {
>> - return map->ops->map_seq_show_elem && map->ops->map_check_btf;
>> + return map->ops->map_seq_show_elem;
>> }
>>
>> extern const struct bpf_map_ops bpf_map_offload_ops;
>> diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
>> index 2aa55d030..67f0bdf 100644
>> --- a/kernel/bpf/arraymap.c
>> +++ b/kernel/bpf/arraymap.c
>> @@ -358,32 +358,6 @@ static void array_map_seq_show_elem(struct bpf_map *map, void *key,
>> rcu_read_unlock();
>> }
>>
>> -static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
>> - u32 btf_key_id, u32 btf_value_id)
>> -{
>> - const struct btf_type *key_type, *value_type;
>> - u32 key_size, value_size;
>> - u32 int_data;
>> -
>> - key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
>> - if (!key_type || BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
>> - return -EINVAL;
>> -
>> - int_data = *(u32 *)(key_type + 1);
>> - /* bpf array can only take a u32 key. This check makes
>> - * sure that the btf matches the attr used during map_create.
>> - */
>> - if (BTF_INT_BITS(int_data) != 32 || key_size != 4 ||
>> - BTF_INT_OFFSET(int_data))
>> - return -EINVAL;
>> -
>> - value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
>> - if (!value_type || value_size != map->value_size)
>> - return -EINVAL;
>> -
>> - return 0;
>> -}
>> -
>> const struct bpf_map_ops array_map_ops = {
>> .map_alloc_check = array_map_alloc_check,
>> .map_alloc = array_map_alloc,
>> @@ -394,7 +368,6 @@ const struct bpf_map_ops array_map_ops = {
>> .map_delete_elem = array_map_delete_elem,
>> .map_gen_lookup = array_map_gen_lookup,
>> .map_seq_show_elem = array_map_seq_show_elem,
>> - .map_check_btf = array_map_check_btf,
>> };
>>
>> const struct bpf_map_ops percpu_array_map_ops = {
>> diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
>> index 76efe9a..400f27d 100644
>> --- a/kernel/bpf/inode.c
>> +++ b/kernel/bpf/inode.c
>> @@ -332,7 +332,8 @@ static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
>> struct bpf_map *map = arg;
>>
>> return bpf_mkobj_ops(dentry, mode, arg, &bpf_map_iops,
>> - map->btf ? &bpffs_map_fops : &bpffs_obj_fops);
>> + bpf_map_support_seq_show(map) ?
>> + &bpffs_map_fops : &bpffs_obj_fops);
>
> There are an issue here, the condition bpf_map_support_seq_show(map) may not be enough since the map specific implementation assumes availability of btf and proper map key/value btf_type_id's.
> We can either use
> map->btf && bpf_map_support_seq_show(map)
> condition here, or check map->btf in each individual implementation
> of map_support_seq_show().
Good, point, agree. Will fix and cook proper patch later today.
Thanks Yonghong!
>> }
>>
>> static struct dentry *
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index 5af4e9e..0b6f6e8 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -455,6 +455,23 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
>> return 0;
>> }
>>
>> +static int map_check_btf(const struct bpf_map *map, const struct btf *btf,
>> + u32 btf_key_id, u32 btf_value_id)
>> +{
>> + const struct btf_type *key_type, *value_type;
>> + u32 key_size, value_size;
>> +
>> + key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
>> + if (!key_type || key_size != map->key_size)
>> + return -EINVAL;
>> +
>> + value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
>> + if (!value_type || value_size != map->value_size)
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +
>> #define BPF_MAP_CREATE_LAST_FIELD btf_value_type_id
>> /* called via syscall */
>> static int map_create(union bpf_attr *attr)
>> @@ -489,8 +506,7 @@ static int map_create(union bpf_attr *attr)
>> atomic_set(&map->refcnt, 1);
>> atomic_set(&map->usercnt, 1);
>>
>> - if (bpf_map_support_seq_show(map) &&
>> - (attr->btf_key_type_id || attr->btf_value_type_id)) {
>> + if (attr->btf_key_type_id || attr->btf_value_type_id) {
>> struct btf *btf;
>>
>> if (!attr->btf_key_type_id || !attr->btf_value_type_id) {
>> @@ -504,8 +520,8 @@ static int map_create(union bpf_attr *attr)
>> goto free_map_nouncharge;
>> }
>>
>> - err = map->ops->map_check_btf(map, btf, attr->btf_key_type_id,
>> - attr->btf_value_type_id);
>> + err = map_check_btf(map, btf, attr->btf_key_type_id,
>> + attr->btf_value_type_id);
>> if (err) {
>> btf_put(btf);
>> goto free_map_nouncharge;
>>
^ permalink raw reply
* Re: [Query]: DSA Understanding
From: Andrew Lunn @ 2018-08-09 17:23 UTC (permalink / raw)
To: Lad, Prabhakar; +Cc: netdev
In-Reply-To: <CA+V-a8uvA2rZ8gGFwXH835-vEs3G+cAygNLAi3uC1Sf+LpW_jQ@mail.gmail.com>
> Its coming from the switch lan4 I have attached the png, where
> C4:F3:12:08:FE:7F is
> the mac of lan4, which is broadcast to ff:ff:ff:ff:ff:ff, which is
> causing rx counter on
> PC to go up.
So, big packets are making it from the switch to the PC. But the small
ARP packets are not.
This is what Florian was suggesting.
ARP packets are smaller than 64 bytes, which is the minimum packet
size for Ethernet. Any packets smaller than 64 bytes are called runt
packets. They have to be padded upto 64 bytes in order to make them
valid. Otherwise the destination, or any switch along the path, might
throw them away.
What could be happening is that the CSPW driver or hardware is padding
the packet to 64 bytes. But that packet has a DSA header in it. The
switch removes the header, recalculate the checksum and sends the
packet. It is now either 4 or 8 bytes smaller, depending on what DSA
header was used. It then becomes a runt packet.
Florian had to fix this problem recently.
http://patchwork.ozlabs.org/patch/836534/
You probably need something similar for the cpsw.
Andrew
^ permalink raw reply
* Re: kernel BUG at net/ipv4/ip_output.c:LINE!
From: syzbot @ 2018-08-09 20:02 UTC (permalink / raw)
To: davem, kuznet, linux-kernel, netdev, syzkaller-bugs, yoshfuji
In-Reply-To: <000000000000f68d660570dcddd8@google.com>
syzbot has found a reproducer for the following crash on:
HEAD commit: 112cbae26d18 Merge branch 'linus' of git://git.kernel.org/..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1192ae72400000
kernel config: https://syzkaller.appspot.com/x/.config?x=152cb8ccd35b1f70
dashboard link: https://syzkaller.appspot.com/bug?extid=90d5ec0c05e708f3b66d
compiler: gcc (GCC) 8.0.1 20180413 (experimental)
syzkaller repro:https://syzkaller.appspot.com/x/repro.syz?x=153ed6e2400000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1539038c400000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+90d5ec0c05e708f3b66d@syzkaller.appspotmail.com
IPv6: ADDRCONF(NETDEV_UP): veth0: link is not ready
IPv6: ADDRCONF(NETDEV_CHANGE): veth0: link becomes ready
IPv6: ADDRCONF(NETDEV_CHANGE): bond0: link becomes ready
8021q: adding VLAN 0 to HW filter on device team0
------------[ cut here ]------------
kernel BUG at net/ipv4/ip_output.c:775!
invalid opcode: 0000 [#1] SMP KASAN
CPU: 1 PID: 4713 Comm: syz-executor450 Not tainted 4.18.0-rc8+ #182
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:ip_do_fragment+0x2436/0x2aa0 net/ipv4/ip_output.c:775
Code: 8b 8d 70 fe ff ff e9 99 e8 ff ff 4c 89 ef e8 a1 65 40 fc e9 7b e9 ff
ff 4c 89 f7 e8 94 65 40 fc e9 f3 e5 ff ff e8 7a 89 02 fc <0f> 0b 4c 89 e7
e8 80 65 40 fc e9 b7 e8 ff ff 4c 89 f7 89 8d 70 fe
RSP: 0018:ffff8801cfe3e880 EFLAGS: 00010293
RAX: ffff8801af542080 RBX: ffff8801c88eaa00 RCX: ffffffff85797886
RDX: 0000000000000000 RSI: ffffffff85798ed6 RDI: 0000000000000005
RBP: ffff8801cfe3ea58 R08: ffff8801af542080 R09: ffffed0039110032
R10: ffffed0039110034 R11: ffff8801c88801a3 R12: ffff8801c88eaac4
R13: 00000000fffffff2 R14: ffff8801c88eaad0 R15: dffffc0000000000
FS: 0000000001479880(0000) GS:ffff8801db100000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffff600400 CR3: 00000001cf669000 CR4: 00000000001406e0
Call Trace:
ip_fragment.constprop.49+0x179/0x240 net/ipv4/ip_output.c:548
ip_finish_output+0x6e4/0xfa0 net/ipv4/ip_output.c:315
NF_HOOK_COND include/linux/netfilter.h:276 [inline]
ip_output+0x223/0x880 net/ipv4/ip_output.c:405
dst_output include/net/dst.h:444 [inline]
ip_local_out+0xc5/0x1b0 net/ipv4/ip_output.c:124
iptunnel_xmit+0x53b/0x800 net/ipv4/ip_tunnel_core.c:91
ip_tunnel_xmit+0x1598/0x3af1 net/ipv4/ip_tunnel.c:778
__gre_xmit+0x5b7/0x950 net/ipv4/ip_gre.c:449
ipgre_xmit+0x3e8/0xb50 net/ipv4/ip_gre.c:701
__netdev_start_xmit include/linux/netdevice.h:4148 [inline]
netdev_start_xmit include/linux/netdevice.h:4157 [inline]
xmit_one net/core/dev.c:3034 [inline]
dev_hard_start_xmit+0x26c/0xc30 net/core/dev.c:3050
__dev_queue_xmit+0x29c2/0x38e0 net/core/dev.c:3569
dev_queue_xmit+0x17/0x20 net/core/dev.c:3602
__bpf_tx_skb net/core/filter.c:1995 [inline]
__bpf_redirect_common net/core/filter.c:2033 [inline]
__bpf_redirect+0x563/0xa80 net/core/filter.c:2040
____bpf_clone_redirect net/core/filter.c:2073 [inline]
bpf_clone_redirect+0x2f6/0x490 net/core/filter.c:2045
bpf_prog_bebbfe2050753572+0xef4/0x1000
Modules linked in:
Dumping ftrace buffer:
(ftrace buffer empty)
---[ end trace b3cbe48b5e178b8d ]---
RIP: 0010:ip_do_fragment+0x2436/0x2aa0 net/ipv4/ip_output.c:775
Code: 8b 8d 70 fe ff ff e9 99 e8 ff ff 4c 89 ef e8 a1 65 40 fc e9 7b e9 ff
ff 4c 89 f7 e8 94 65 40 fc e9 f3 e5 ff ff e8 7a 89 02 fc <0f> 0b 4c 89 e7
e8 80 65 40 fc e9 b7 e8 ff ff 4c 89 f7 89 8d 70 fe
RSP: 0018:ffff8801cfe3e880 EFLAGS: 00010293
RAX: ffff8801af542080 RBX: ffff8801c88eaa00 RCX: ffffffff85797886
RDX: 0000000000000000 RSI: ffffffff85798ed6 RDI: 0000000000000005
RBP: ffff8801cfe3ea58 R08: ffff8801af542080 R09: ffffed0039110032
R10: ffffed0039110034 R11: ffff8801c88801a3 R12: ffff8801c88eaac4
R13: 00000000fffffff2 R14: ffff8801c88eaad0 R15: dffffc0000000000
FS: 0000000001479880(0000) GS:ffff8801db100000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffff600400 CR3: 00000001cf669000 CR4: 00000000001406e0
^ permalink raw reply
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