* [PATCH iproute2-next] tc: jsonify output of q_fifo
From: Jakub Kicinski @ 2018-10-05 0:08 UTC (permalink / raw)
To: dsahern; +Cc: netdev, oss-drivers, Jakub Kicinski
Print limits correctly in JSON context.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
tc/q_fifo.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/tc/q_fifo.c b/tc/q_fifo.c
index cb86a404d4de..61493fbbc5bc 100644
--- a/tc/q_fifo.c
+++ b/tc/q_fifo.c
@@ -69,9 +69,12 @@ static int fifo_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
qopt = RTA_DATA(opt);
if (strcmp(qu->id, "bfifo") == 0) {
SPRINT_BUF(b1);
- fprintf(f, "limit %s", sprint_size(qopt->limit, b1));
- } else
- fprintf(f, "limit %up", qopt->limit);
+ print_uint(PRINT_JSON, "limit", NULL, qopt->limit);
+ print_string(PRINT_FP, NULL, "limit %s",
+ sprint_size(qopt->limit, b1));
+ } else {
+ print_uint(PRINT_ANY, "limit", "limit %up", qopt->limit);
+ }
return 0;
}
--
2.17.1
^ permalink raw reply related
* [PATCH net v2] net: mvpp2: Extract the correct ethtype from the skb for tx csum offload
From: Maxime Chevallier @ 2018-10-05 7:04 UTC (permalink / raw)
To: davem
Cc: Maxime Chevallier, netdev, linux-kernel, Antoine Tenart,
thomas.petazzoni, gregory.clement, miquel.raynal, nadavh, stefanc,
ymarkman, mw
When offloading the L3 and L4 csum computation on TX, we need to extract
the l3_proto from the ethtype, independently of the presence of a vlan
tag.
The actual driver uses skb->protocol as-is, resulting in packets with
the wrong L4 checksum being sent when there's a vlan tag in the packet
header and checksum offloading is enabled.
This commit makes use of vlan_protocol_get() to get the correct ethtype
regardless the presence of a vlan tag.
Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit")
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
V2: Use htons on values that can be swapped at compile-time, following
Yan's comment. Fix the "Fixes" tag and a typo, following Sergei's comment.
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 38cc01beea79..a74002b43b51 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1725,7 +1725,7 @@ static void mvpp2_txq_desc_put(struct mvpp2_tx_queue *txq)
}
/* Set Tx descriptors fields relevant for CSUM calculation */
-static u32 mvpp2_txq_desc_csum(int l3_offs, int l3_proto,
+static u32 mvpp2_txq_desc_csum(int l3_offs, __be16 l3_proto,
int ip_hdr_len, int l4_proto)
{
u32 command;
@@ -2600,14 +2600,15 @@ static u32 mvpp2_skb_tx_csum(struct mvpp2_port *port, struct sk_buff *skb)
if (skb->ip_summed == CHECKSUM_PARTIAL) {
int ip_hdr_len = 0;
u8 l4_proto;
+ __be16 l3_proto = vlan_get_protocol(skb);
- if (skb->protocol == htons(ETH_P_IP)) {
+ if (l3_proto == htons(ETH_P_IP)) {
struct iphdr *ip4h = ip_hdr(skb);
/* Calculate IPv4 checksum and L4 checksum */
ip_hdr_len = ip4h->ihl;
l4_proto = ip4h->protocol;
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ } else if (l3_proto == htons(ETH_P_IPV6)) {
struct ipv6hdr *ip6h = ipv6_hdr(skb);
/* Read l4_protocol from one of IPv6 extra headers */
@@ -2619,7 +2620,7 @@ static u32 mvpp2_skb_tx_csum(struct mvpp2_port *port, struct sk_buff *skb)
}
return mvpp2_txq_desc_csum(skb_network_offset(skb),
- skb->protocol, ip_hdr_len, l4_proto);
+ l3_proto, ip_hdr_len, l4_proto);
}
return MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_IP_CSUM_DISABLE;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next] net: sched: remove unused helpers
From: Jakub Kicinski @ 2018-10-05 0:07 UTC (permalink / raw)
To: davem; +Cc: jiri, netdev, oss-drivers, Jakub Kicinski
tcf_block_dev() doesn't seem to be used anywhere in the tree.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
include/net/pkt_cls.h | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 313fe840742d..338ef054bf16 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -65,11 +65,6 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
return block->q;
}
-static inline struct net_device *tcf_block_dev(struct tcf_block *block)
-{
- return tcf_block_q(block)->dev_queue->dev;
-}
-
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);
@@ -122,11 +117,6 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
return NULL;
}
-static inline struct net_device *tcf_block_dev(struct tcf_block *block)
-{
- return NULL;
-}
-
static inline
int tc_setup_cb_block_register(struct tcf_block *block, tc_setup_cb_t *cb,
void *cb_priv)
--
2.17.1
^ permalink raw reply related
* Re: [RFC PATCH bpf-next v4 7/7] selftests/bpf: add test cases for queue and stack maps
From: Alexei Starovoitov @ 2018-10-04 23:59 UTC (permalink / raw)
To: Mauricio Vasquez B; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev
In-Reply-To: <153867318092.10087.8115445755907117246.stgit@kernel>
On Thu, Oct 04, 2018 at 07:13:00PM +0200, Mauricio Vasquez B wrote:
> Two types of tests are done:
> - test_maps: only userspace api.
> - test_progs: userspace api and ebpf helpers.
>
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
overall looks very close. thank for you working on it.
please fix the nits and resubmit without rfc tag.
Thx!
^ permalink raw reply
* Re: [RFC PATCH bpf-next v4 5/7] bpf: restrict use of peek/push/pop
From: Alexei Starovoitov @ 2018-10-04 23:57 UTC (permalink / raw)
To: Mauricio Vasquez B; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev
In-Reply-To: <153867316984.10087.3212168623519526172.stgit@kernel>
On Thu, Oct 04, 2018 at 07:12:49PM +0200, Mauricio Vasquez B wrote:
> Restrict the use of peek, push and pop helpers only to queue and stack
> maps.
>
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
> ---
> kernel/bpf/verifier.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 489667f93061..8b1f1b348782 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -2328,6 +2328,13 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
> if (func_id != BPF_FUNC_sk_select_reuseport)
> goto error;
> break;
> + case BPF_MAP_TYPE_QUEUE:
> + case BPF_MAP_TYPE_STACK:
> + if (func_id != BPF_FUNC_map_peek_elem &&
> + func_id != BPF_FUNC_map_pop_elem &&
> + func_id != BPF_FUNC_map_push_elem)
> + goto error;
why this is separate patch?
I think it should be part of previous patch.
> + break;
> default:
> break;
> }
> @@ -2384,6 +2391,13 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
> if (map->map_type != BPF_MAP_TYPE_REUSEPORT_SOCKARRAY)
> goto error;
> break;
> + case BPF_FUNC_map_peek_elem:
> + case BPF_FUNC_map_pop_elem:
> + case BPF_FUNC_map_push_elem:
> + if (map->map_type != BPF_MAP_TYPE_QUEUE &&
> + map->map_type != BPF_MAP_TYPE_STACK)
> + goto error;
> + break;
> default:
> break;
> }
>
^ permalink raw reply
* Re: [RFC PATCH bpf-next v4 4/7] bpf: add bpf queue and stack maps
From: Alexei Starovoitov @ 2018-10-04 23:57 UTC (permalink / raw)
To: Mauricio Vasquez B; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev
In-Reply-To: <153867316459.10087.2913745359364075968.stgit@kernel>
On Thu, Oct 04, 2018 at 07:12:44PM +0200, Mauricio Vasquez B wrote:
> Implement two new kind of maps that support the peek, push and pop
> operations.
>
> A use case for this is to keep track of a pool of elements, like
> network ports in a SNAT.
>
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
> ---
> include/linux/bpf.h | 7 +
> include/linux/bpf_types.h | 2
> include/uapi/linux/bpf.h | 35 ++++-
> kernel/bpf/Makefile | 2
> kernel/bpf/core.c | 3
> kernel/bpf/helpers.c | 43 ++++++
> kernel/bpf/queue_stack_maps.c | 300 +++++++++++++++++++++++++++++++++++++++++
> kernel/bpf/syscall.c | 31 +++-
> kernel/bpf/verifier.c | 14 +-
> net/core/filter.c | 6 +
> 10 files changed, 424 insertions(+), 19 deletions(-)
> create mode 100644 kernel/bpf/queue_stack_maps.c
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 98c7eeb6d138..cad3bc5cffd1 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -40,6 +40,9 @@ struct bpf_map_ops {
> int (*map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags);
> int (*map_delete_elem)(struct bpf_map *map, void *key);
> void *(*map_lookup_and_delete_elem)(struct bpf_map *map, void *key);
> + int (*map_push_elem)(struct bpf_map *map, void *value, u64 flags);
> + int (*map_pop_elem)(struct bpf_map *map, void *value);
> + int (*map_peek_elem)(struct bpf_map *map, void *value);
>
> /* funcs called by prog_array and perf_event_array map */
> void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file,
> @@ -139,6 +142,7 @@ enum bpf_arg_type {
> ARG_CONST_MAP_PTR, /* const argument used as pointer to bpf_map */
> ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */
> ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */
> + ARG_PTR_TO_UNINIT_MAP_VALUE, /* pointer to valid memory used to store a map value */
>
> /* the following constraints used to prototype bpf_memcmp() and other
> * functions that access data on eBPF program stack
> @@ -825,6 +829,9 @@ static inline int bpf_fd_reuseport_array_update_elem(struct bpf_map *map,
> extern const struct bpf_func_proto bpf_map_lookup_elem_proto;
> extern const struct bpf_func_proto bpf_map_update_elem_proto;
> extern const struct bpf_func_proto bpf_map_delete_elem_proto;
> +extern const struct bpf_func_proto bpf_map_push_elem_proto;
> +extern const struct bpf_func_proto bpf_map_pop_elem_proto;
> +extern const struct bpf_func_proto bpf_map_peek_elem_proto;
>
> extern const struct bpf_func_proto bpf_get_prandom_u32_proto;
> extern const struct bpf_func_proto bpf_get_smp_processor_id_proto;
> diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
> index 658509daacd4..a2ec73aa1ec7 100644
> --- a/include/linux/bpf_types.h
> +++ b/include/linux/bpf_types.h
> @@ -69,3 +69,5 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_XSKMAP, xsk_map_ops)
> BPF_MAP_TYPE(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, reuseport_array_ops)
> #endif
> #endif
> +BPF_MAP_TYPE(BPF_MAP_TYPE_QUEUE, queue_map_ops)
> +BPF_MAP_TYPE(BPF_MAP_TYPE_STACK, stack_map_ops)
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 3bb94aa2d408..bfa042273fad 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -129,6 +129,8 @@ enum bpf_map_type {
> BPF_MAP_TYPE_CGROUP_STORAGE,
> BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
> BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
> + BPF_MAP_TYPE_QUEUE,
> + BPF_MAP_TYPE_STACK,
> };
>
> enum bpf_prog_type {
> @@ -463,6 +465,28 @@ union bpf_attr {
> * Return
> * 0 on success, or a negative error in case of failure.
> *
> + * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags)
> + * Description
> + * Push an element *value* in *map*. *flags* is one of:
> + *
> + * **BPF_EXIST**
> + * If the queue/stack is full, the oldest element is removed to
> + * make room for this.
> + * Return
> + * 0 on success, or a negative error in case of failure.
> + *
> + * int bpf_map_pop_elem(struct bpf_map *map, void *value)
> + * Description
> + * Pop an element from *map*.
> + * Return
> + * 0 on success, or a negative error in case of failure.
> + *
> + * int bpf_map_peek_elem(struct bpf_map *map, void *value)
> + * Description
> + * Get an element from *map* without removing it.
> + * Return
> + * 0 on success, or a negative error in case of failure.
> + *
> * int bpf_probe_read(void *dst, u32 size, const void *src)
> * Description
> * For tracing programs, safely attempt to read *size* bytes from
> @@ -790,14 +814,14 @@ union bpf_attr {
> *
> * int ret;
> * struct bpf_tunnel_key key = {};
> - *
> + *
> * ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
> * if (ret < 0)
> * return TC_ACT_SHOT; // drop packet
> - *
> + *
> * if (key.remote_ipv4 != 0x0a000001)
> * return TC_ACT_SHOT; // drop packet
> - *
> + *
> * return TC_ACT_OK; // accept packet
> *
> * This interface can also be used with all encapsulation devices
> @@ -2304,7 +2328,10 @@ union bpf_attr {
> FN(skb_ancestor_cgroup_id), \
> FN(sk_lookup_tcp), \
> FN(sk_lookup_udp), \
> - FN(sk_release),
> + FN(sk_release), \
> + FN(map_push_elem), \
> + FN(map_pop_elem), \
> + FN(map_peek_elem),
>
> /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> * function eBPF program intends to call
> diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
> index 0488b8258321..17afae9e65f3 100644
> --- a/kernel/bpf/Makefile
> +++ b/kernel/bpf/Makefile
> @@ -3,7 +3,7 @@ obj-y := core.o
>
> obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o
> obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o
> -obj-$(CONFIG_BPF_SYSCALL) += local_storage.o
> +obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o
> obj-$(CONFIG_BPF_SYSCALL) += disasm.o
> obj-$(CONFIG_BPF_SYSCALL) += btf.o
> ifeq ($(CONFIG_NET),y)
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index 3f5bf1af0826..8d2db076d123 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -1783,6 +1783,9 @@ BPF_CALL_0(bpf_user_rnd_u32)
> const struct bpf_func_proto bpf_map_lookup_elem_proto __weak;
> const struct bpf_func_proto bpf_map_update_elem_proto __weak;
> const struct bpf_func_proto bpf_map_delete_elem_proto __weak;
> +const struct bpf_func_proto bpf_map_push_elem_proto __weak;
> +const struct bpf_func_proto bpf_map_pop_elem_proto __weak;
> +const struct bpf_func_proto bpf_map_peek_elem_proto __weak;
>
> const struct bpf_func_proto bpf_get_prandom_u32_proto __weak;
> const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak;
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 6502115e8f55..ab0d5e3f9892 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -76,6 +76,49 @@ const struct bpf_func_proto bpf_map_delete_elem_proto = {
> .arg2_type = ARG_PTR_TO_MAP_KEY,
> };
>
> +BPF_CALL_3(bpf_map_push_elem, struct bpf_map *, map, void *, value, u64, flags)
> +{
> + return map->ops->map_push_elem(map, value, flags);
> +}
> +
> +const struct bpf_func_proto bpf_map_push_elem_proto = {
> + .func = bpf_map_push_elem,
> + .gpl_only = false,
> + .pkt_access = true,
> + .ret_type = RET_INTEGER,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_MAP_VALUE,
> + .arg3_type = ARG_ANYTHING,
> +};
> +
> +BPF_CALL_2(bpf_map_pop_elem, struct bpf_map *, map, void *, value)
> +{
> + return map->ops->map_pop_elem(map, value);
> +}
> +
> +const struct bpf_func_proto bpf_map_pop_elem_proto = {
> + .func = bpf_map_pop_elem,
> + .gpl_only = false,
> + .pkt_access = true,
> + .ret_type = RET_INTEGER,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_UNINIT_MAP_VALUE,
> +};
> +
> +BPF_CALL_2(bpf_map_peek_elem, struct bpf_map *, map, void *, value)
> +{
> + return map->ops->map_peek_elem(map, value);
> +}
> +
> +const struct bpf_func_proto bpf_map_peek_elem_proto = {
> + .func = bpf_map_pop_elem,
> + .gpl_only = false,
> + .pkt_access = true,
> + .ret_type = RET_INTEGER,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_UNINIT_MAP_VALUE,
> +};
> +
> const struct bpf_func_proto bpf_get_prandom_u32_proto = {
> .func = bpf_user_rnd_u32,
> .gpl_only = false,
> diff --git a/kernel/bpf/queue_stack_maps.c b/kernel/bpf/queue_stack_maps.c
> new file mode 100644
> index 000000000000..a597c5ba68f6
> --- /dev/null
> +++ b/kernel/bpf/queue_stack_maps.c
> @@ -0,0 +1,300 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * queue_stack_maps.c: BPF queue and stack maps
> + *
> + * Copyright (c) 2018 Politecnico di Torino
> + */
> +#include <linux/bpf.h>
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +#include "percpu_freelist.h"
> +
> +#define QUEUE_STACK_CREATE_FLAG_MASK \
> + (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
> +
> +
> +struct bpf_queue_stack {
> + struct bpf_map map;
> + raw_spinlock_t lock;
> + u32 head, tail;
> + u32 index_mask;
> + u32 count;
> +
> + char elements[0] __aligned(8);
> +};
> +
> +static struct bpf_queue_stack *bpf_queue_stack(struct bpf_map *map)
> +{
> + return container_of(map, struct bpf_queue_stack, map);
> +}
> +
> +static bool queue_stack_map_is_empty(struct bpf_queue_stack *qs)
> +{
> + return qs->count == 0;
> +}
> +
> +static bool queue_stack_map_is_full(struct bpf_queue_stack *qs)
> +{
> + return qs->count == qs->map.max_entries;
> +}
> +
> +/* Called from syscall */
> +static int queue_stack_map_alloc_check(union bpf_attr *attr)
> +{
> + /* check sanity of attributes */
> + if (attr->max_entries == 0 || attr->key_size != 0 ||
> + attr->map_flags & ~QUEUE_STACK_CREATE_FLAG_MASK)
> + return -EINVAL;
> +
> + if (attr->value_size > KMALLOC_MAX_SIZE)
> + /* if value_size is bigger, the user space won't be able to
> + * access the elements.
> + */
> + return -E2BIG;
> +
> + return 0;
> +}
> +
> +static struct bpf_map *queue_stack_map_alloc(union bpf_attr *attr)
> +{
> + int ret, numa_node = bpf_map_attr_numa_node(attr);
> + u32 max_entries, value_size, index_mask;
> + u64 queue_size, cost, mask64;
> + struct bpf_queue_stack *qs;
> +
> + max_entries = attr->max_entries;
> + value_size = attr->value_size;
> +
> + /* From arraymap.c:
> + * On 32 bit archs roundup_pow_of_two() with max_entries that has
> + * upper most bit set in u32 space is undefined behavior due to
> + * resulting 1U << 32, so do it manually here in u64 space.
> + */
> + mask64 = fls_long(max_entries - 1);
> + mask64 = 1ULL << mask64;
> + mask64 -= 1;
> +
> + index_mask = mask64;
> +
> + /* Round up queue size to nearest power of 2 */
> + max_entries = index_mask + 1;
what's the point of roundup ?
The memory waste becomes quite large when max_entries are high.
If queue/stack is sized to exact max_entries,
then 'count' can be removed too, right?
> + /* Check for overflows. */
> + if (max_entries < attr->max_entries)
> + return ERR_PTR(-E2BIG);
> +
> + queue_size = sizeof(*qs) + (u64) value_size * max_entries;
> +
> + cost = queue_size;
> + if (cost >= U32_MAX - PAGE_SIZE)
> + return ERR_PTR(-E2BIG);
> +
> + cost = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
> +
> + ret = bpf_map_precharge_memlock(cost);
> + if (ret < 0)
> + return ERR_PTR(ret);
> +
> + qs = bpf_map_area_alloc(queue_size, numa_node);
> + if (!qs)
> + return ERR_PTR(-ENOMEM);
> +
> + memset(qs, 0, sizeof(*qs));
> +
> + bpf_map_init_from_attr(&qs->map, attr);
> +
> + qs->map.pages = cost;
> + qs->index_mask = index_mask;
> +
> + raw_spin_lock_init(&qs->lock);
> +
> + return &qs->map;
> +}
> +
> +/* Called when map->refcnt goes to zero, either from workqueue or from syscall */
> +static void queue_stack_map_free(struct bpf_map *map)
> +{
> + struct bpf_queue_stack *qs = bpf_queue_stack(map);
> +
> + /* at this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
> + * so the programs (can be more than one that used this map) were
> + * disconnected from events. Wait for outstanding critical sections in
> + * these programs to complete
> + */
> + synchronize_rcu();
> +
> + bpf_map_area_free(qs);
> +}
> +
> +static int __queue_map_get(struct bpf_map *map, void *value, bool delete)
> +{
> + struct bpf_queue_stack *qs = bpf_queue_stack(map);
> + unsigned long flags;
> + int err = 0;
> + void *ptr;
> +
> + raw_spin_lock_irqsave(&qs->lock, flags);
> +
> + if (queue_stack_map_is_empty(qs)) {
> + err = -ENOENT;
> + goto out;
> + }
> +
> + ptr = &qs->elements[qs->tail * qs->map.value_size];
> + memcpy(value, ptr, qs->map.value_size);
> +
> + if (delete) {
> + qs->tail = (qs->tail + 1) & qs->index_mask;
> + qs->count--;
> + }
> +
> +out:
> + raw_spin_unlock_irqrestore(&qs->lock, flags);
> + return err;
> +}
> +
> +
> +static int __stack_map_get(struct bpf_map *map, void *value, bool delete)
> +{
> + struct bpf_queue_stack *qs = bpf_queue_stack(map);
> + unsigned long flags;
> + int err = 0;
> + void *ptr;
> + u32 index;
> +
> + raw_spin_lock_irqsave(&qs->lock, flags);
> +
> + if (queue_stack_map_is_empty(qs)) {
> + err = -ENOENT;
> + goto out;
> + }
> +
> + index = (qs->head - 1) & qs->index_mask;
> + ptr = &qs->elements[index * qs->map.value_size];
> + memcpy(value, ptr, qs->map.value_size);
> +
> + if (delete) {
> + qs->head = (qs->head - 1) & qs->index_mask;
> + qs->count--;
> + }
> +
> +out:
> + raw_spin_unlock_irqrestore(&qs->lock, flags);
> + return err;
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int queue_map_peek_elem(struct bpf_map *map, void *value)
> +{
> + return __queue_map_get(map, value, false);
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int stack_map_peek_elem(struct bpf_map *map, void *value)
> +{
> + return __stack_map_get(map, value, false);
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int queue_map_pop_elem(struct bpf_map *map, void *value)
> +{
> + return __queue_map_get(map, value, true);
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int stack_map_pop_elem(struct bpf_map *map, void *value)
> +{
> + return __stack_map_get(map, value, true);
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int queue_stack_map_push_elem(struct bpf_map *map, void *value,
> + u64 flags)
> +{
> + struct bpf_queue_stack *qs = bpf_queue_stack(map);
> + unsigned long irq_flags;
> + int err = 0;
> + void *dst;
> +
> + /* BPF_EXIST is used to force making room for a new element in case the
> + * map is full
> + */
> + bool replace = (flags & BPF_EXIST);
> +
> + /* Check supported flags for queue and stack maps */
> + if (flags & BPF_NOEXIST || flags > BPF_EXIST)
> + return -EINVAL;
> +
> + raw_spin_lock_irqsave(&qs->lock, irq_flags);
> +
> + if (queue_stack_map_is_full(qs)) {
> + if (!replace) {
> + err = -E2BIG;
ENOSPC is probably more accurate ?
> + goto out;
> + }
> + /* advance tail pointer to overwrite oldest element */
'oldest' is ambiguous here.
For queue it's true, but for stack it's the last element.
Since stack is poping from the head, push w/exist flag will keep
overwriting the last element.
Pls explain it more clearly in helper description in bpf.h
> + qs->tail = (qs->tail + 1) & qs->index_mask;
> + qs->count--;
> + }
> +
> + dst = &qs->elements[qs->head * qs->map.value_size];
> + memcpy(dst, value, qs->map.value_size);
> +
> + qs->head = (qs->head + 1) & qs->index_mask;
> + qs->count++;
> +
> +out:
> + raw_spin_unlock_irqrestore(&qs->lock, irq_flags);
> + return err;
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static void *queue_stack_map_lookup_elem(struct bpf_map *map, void *key)
> +{
> + return NULL;
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int queue_stack_map_update_elem(struct bpf_map *map, void *key,
> + void *value, u64 flags)
> +{
> + return -EINVAL;
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int queue_stack_map_delete_elem(struct bpf_map *map, void *key)
> +{
> + return -EINVAL;
> +}
> +
> +/* Called from syscall */
> +static int queue_stack_map_get_next_key(struct bpf_map *map, void *key,
> + void *next_key)
> +{
> + return -EINVAL;
> +}
> +
> +const struct bpf_map_ops queue_map_ops = {
> + .map_alloc_check = queue_stack_map_alloc_check,
> + .map_alloc = queue_stack_map_alloc,
> + .map_free = queue_stack_map_free,
> + .map_lookup_elem = queue_stack_map_lookup_elem,
> + .map_update_elem = queue_stack_map_update_elem,
> + .map_delete_elem = queue_stack_map_delete_elem,
> + .map_push_elem = queue_stack_map_push_elem,
> + .map_pop_elem = queue_map_pop_elem,
> + .map_peek_elem = queue_map_peek_elem,
> + .map_get_next_key = queue_stack_map_get_next_key,
> +};
> +
> +const struct bpf_map_ops stack_map_ops = {
> + .map_alloc_check = queue_stack_map_alloc_check,
> + .map_alloc = queue_stack_map_alloc,
> + .map_free = queue_stack_map_free,
> + .map_lookup_elem = queue_stack_map_lookup_elem,
> + .map_update_elem = queue_stack_map_update_elem,
> + .map_delete_elem = queue_stack_map_delete_elem,
> + .map_push_elem = queue_stack_map_push_elem,
> + .map_pop_elem = stack_map_pop_elem,
> + .map_peek_elem = stack_map_peek_elem,
> + .map_get_next_key = queue_stack_map_get_next_key,
> +};
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 50957e243bfb..c46bf2d38be3 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -727,6 +727,9 @@ static int map_lookup_elem(union bpf_attr *attr)
> err = bpf_fd_htab_map_lookup_elem(map, key, value);
> } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
> err = bpf_fd_reuseport_array_lookup_elem(map, key, value);
> + } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
> + map->map_type == BPF_MAP_TYPE_STACK) {
> + err = map->ops->map_peek_elem(map, value);
> } else {
> rcu_read_lock();
> ptr = map->ops->map_lookup_elem(map, key);
> @@ -841,6 +844,9 @@ static int map_update_elem(union bpf_attr *attr)
> /* rcu_read_lock() is not needed */
> err = bpf_fd_reuseport_array_update_elem(map, key, value,
> attr->flags);
> + } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
> + map->map_type == BPF_MAP_TYPE_STACK) {
> + err = map->ops->map_push_elem(map, value, attr->flags);
> } else {
> rcu_read_lock();
> err = map->ops->map_update_elem(map, key, value, attr->flags);
> @@ -1001,11 +1007,6 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
> goto err_put;
> }
>
> - if (!map->ops->map_lookup_and_delete_elem) {
> - err = -ENOTSUPP;
> - goto err_put;
> - }
> -
> key = __bpf_copy_key(ukey, map->key_size);
> if (IS_ERR(key)) {
> err = PTR_ERR(key);
> @@ -1028,12 +1029,22 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
> */
> preempt_disable();
> __this_cpu_inc(bpf_prog_active);
> - rcu_read_lock();
> - ptr = map->ops->map_lookup_and_delete_elem(map, key);
> - if (ptr)
> - memcpy(value, ptr, value_size);
> - rcu_read_unlock();
> + if (map->map_type == BPF_MAP_TYPE_QUEUE ||
> + map->map_type == BPF_MAP_TYPE_STACK) {
> + err = map->ops->map_pop_elem(map, value);
please clean up the paches, so that patch 4 doesn't immediately
deletes the lines that were introduced in patch 3.
Otherwise what was the point of them in patch 3?
> + } else {
> + if (!map->ops->map_lookup_and_delete_elem) {
> + err = -ENOTSUPP;
> + goto free_value;
> + }
> + rcu_read_lock();
> + ptr = map->ops->map_lookup_and_delete_elem(map, key);
> + if (ptr)
> + memcpy(value, ptr, value_size);
> + rcu_read_unlock();
> err = ptr ? 0 : -ENOENT;
> + }
> +
> __this_cpu_dec(bpf_prog_active);
> preempt_enable();
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 73c81bef6ae8..489667f93061 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -2121,7 +2121,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
> }
>
> if (arg_type == ARG_PTR_TO_MAP_KEY ||
> - arg_type == ARG_PTR_TO_MAP_VALUE) {
> + arg_type == ARG_PTR_TO_MAP_VALUE ||
> + arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE) {
> expected_type = PTR_TO_STACK;
> if (!type_is_pkt_pointer(type) && type != PTR_TO_MAP_VALUE &&
> type != expected_type)
> @@ -2191,7 +2192,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
> err = check_helper_mem_access(env, regno,
> meta->map_ptr->key_size, false,
> NULL);
> - } else if (arg_type == ARG_PTR_TO_MAP_VALUE) {
> + } else if (arg_type == ARG_PTR_TO_MAP_VALUE ||
> + arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE) {
> /* bpf_map_xxx(..., map_ptr, ..., value) call:
> * check [value, value + map->value_size) validity
> */
> @@ -2200,9 +2202,10 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
> verbose(env, "invalid map_ptr to access map->value\n");
> return -EACCES;
> }
> + meta->raw_mode = (arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE);
> err = check_helper_mem_access(env, regno,
> meta->map_ptr->value_size, false,
> - NULL);
> + meta);
> } else if (arg_type_is_mem_size(arg_type)) {
> bool zero_size_allowed = (arg_type == ARG_CONST_SIZE_OR_ZERO);
>
> @@ -2676,7 +2679,10 @@ record_func_map(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
> if (func_id != BPF_FUNC_tail_call &&
> func_id != BPF_FUNC_map_lookup_elem &&
> func_id != BPF_FUNC_map_update_elem &&
> - func_id != BPF_FUNC_map_delete_elem)
> + func_id != BPF_FUNC_map_delete_elem &&
> + func_id != BPF_FUNC_map_push_elem &&
> + func_id != BPF_FUNC_map_pop_elem &&
> + func_id != BPF_FUNC_map_peek_elem)
> return 0;
>
> if (meta->map_ptr == NULL) {
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 591c698bc517..40736e0d9cff 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -4993,6 +4993,12 @@ bpf_base_func_proto(enum bpf_func_id func_id)
> return &bpf_map_update_elem_proto;
> case BPF_FUNC_map_delete_elem:
> return &bpf_map_delete_elem_proto;
> + case BPF_FUNC_map_push_elem:
> + return &bpf_map_push_elem_proto;
> + case BPF_FUNC_map_pop_elem:
> + return &bpf_map_pop_elem_proto;
> + case BPF_FUNC_map_peek_elem:
> + return &bpf_map_peek_elem_proto;
> case BPF_FUNC_get_prandom_u32:
> return &bpf_get_prandom_u32_proto;
> case BPF_FUNC_get_smp_processor_id:
>
^ permalink raw reply
* Re: [PATCH net-next] udp: Add tracepoints to monitor skbs going in and out of a UDP socket
From: David Howells @ 2018-10-05 6:46 UTC (permalink / raw)
To: Alexei Starovoitov; +Cc: dhowells, David Ahern, netdev, linux-afs, linux-kernel
In-Reply-To: <20181005020316.7cqlcfkedhamwhtt@ast-mbp.dhcp.thefacebook.com>
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> - kprobes at the top of the function don't use traps and they've been
> optimized over the years to have very low overhead
To quote kprobes.txt:
How Does a Kprobe Work?
-----------------------
When a kprobe is registered, Kprobes makes a copy of the probed
instruction and replaces the first byte(s) of the probed instruction
with a breakpoint instruction (e.g., int3 on i386 and x86_64).
Perhaps the docs need updating.
However, for my purposes, tracepoints are easier.
Anyway, as I said, I don't feel that strongly about the patch. It was useful
for me, and I thought it might be useful for other people.
David
^ permalink raw reply
* Re: [PATCH] team: set IFF_SLAVE on team ports
From: Jiri Pirko @ 2018-10-05 6:46 UTC (permalink / raw)
To: Chas Williams; +Cc: Stephen Hemminger, Jan Blunck, LKML, netdev
In-Reply-To: <526bd655-5816-69dd-ac75-bdd4f85f1ce9@gmail.com>
Wed, Oct 03, 2018 at 07:30:06PM CEST, 3chas3@gmail.com wrote:
>
>
>On 10/03/18 06:44, Jiri Pirko wrote:
>> Tue, Oct 02, 2018 at 11:20:25PM CEST, 3chas3@gmail.com wrote:
>> >
>> >
>> > On 10/02/18 07:12, Jiri Pirko wrote:
>> > > Mon, Oct 01, 2018 at 04:06:16PM CEST, 3chas3@gmail.com wrote:
>> > > >
>> > > >
>> > > > On 09/30/18 05:34, Jiri Pirko wrote:
>> > > > > Sun, Sep 30, 2018 at 11:38:05AM CEST, stephen@networkplumber.org wrote:
>> > > > > > On Sun, 30 Sep 2018 09:14:14 +0200
>> > > > > > Jiri Pirko <jiri@resnulli.us> wrote:
>> > > > > >
>> > > > > > > Thu, Sep 27, 2018 at 04:04:26PM CEST, 3chas3@gmail.com wrote:
>> > > > > > > >
>> > > > > > > >
>> > > > > > > > On 07/10/15 02:41, Jiri Pirko wrote:
>> > > > > > > > > Thu, Jul 09, 2015 at 05:36:55PM CEST, jblunck@infradead.org wrote:
>> > > > > > > > > > On Thu, Jul 9, 2015 at 12:07 PM, Jiri Pirko <jiri@resnulli.us> wrote:
>> > > > > > > > > > > Thu, Jul 09, 2015 at 11:58:34AM CEST, jblunck@infradead.org wrote:
>> > > > > > > > > > > > The code in net/ipv6/addrconf.c:addrconf_notify() tests for IFF_SLAVE to
>> > > > > > > > > > > > decide if it should start the address configuration. Since team ports
>> > > > > > > > > > > > shouldn't get link-local addresses assigned lets set IFF_SLAVE when linking
>> > > > > > > > > > > > a port to the team master.
>> > > > > > > > > > >
>> > > > > > > > > > > I don't want to use IFF_SLAVE in team. Other master-slave devices are
>> > > > > > > > > > > not using that as well, for example bridge, ovs, etc.
>> > > > > > > > > >
>> > > > > > > > > > Maybe they need to get fixed too. I've used that flag because it is
>> > > > > > > > > > documented as
>> > > > > > > > > > a "slave of a load balancer" which describes what a team port is.
>> > > > > > > > > >
>> > > > > > > > > > > I think that this should be fixed in addrconf_notify. It should lookup
>> > > > > > > > > > > if there is a master on top and bail out in that case.
>> > > > > > > > > >
>> > > > > > > > > > There are other virtual interfaces that have a master assigned and want to
>> > > > > > > > > > participate in IPv6 address configuration.
>> > > > > > > > >
>> > > > > > > > > Can you give me an example?
>> > > > > > > >
>> > > > > > > > I would like to revisit this patch (yes, I know it has been a while). I
>> > > > > > > > believe the VRF implementation uses master to group the interfaces under
>> > > > > > > > a single interface.
>> > > > > > > >
>> > > > > > > > I don't see a reason not to use IFF_SLAVE since team and bonding are fairly
>> > > > > > > > similar.
>> > > > > > >
>> > > > > > > Again, why do you need team port to have IFF_SLAVE flag? What do you
>> > > > > > > want to achieve
>> > > > > >
>> > > > > > Without setting this flag IPv6 will try and make a link specific address.
>> > >
>> > > You are talking about addrconf_notify() right? Easy to fix to check
>> > > something more convenient. Like netif_is_lag_port() if you want to avoid
>> > > it for bond/team. netif_is_ovs_port(), netif_is_bridge_port() etc. Lot's
>> > > of helpers to cover this.
>> >
>> > OK, IPv6 should probably be using this.
>> >
>> > >
>> > >
>> > >
>> > > > >
>> > > > > Why is it not an issue with bridge, ovs, and other master-slave devices?
>> > > > >
>> > > >
>> > > > It very well might be an issue for bridge and ovs. Other master-slave
>> > > > devices include the existing VRF implementation in the kernel and those slave
>> > > > interfaces will certainly want to use IPv6.
>> > > >
>> > > > However, IFF_SLAVE has a specific meaning:
>> > > >
>> > > > ./include/uapi/linux/if.h: * @IFF_SLAVE: slave of a load balancer. Volatile.
>> > >
>> > > I know that some userspace apps are using this flag to determine a
>> > > "bonding slave". I don't think that they care much about eql...
>> > >
>> > >
>> > > >
>> > > > The bonding driver is not the only user:
>> > > >
>> > > > ./drivers/net/eql.c:#define eql_is_slave(dev) ((dev->flags & IFF_SLAVE) ==
>> > > > IFF_SLAVE)
>> > > > ./drivers/net/eql.c: slave->dev->flags &= ~IFF_SLAVE;
>> > > > ./drivers/net/eql.c: slave->dev->flags |= IFF_SLAVE;
>> > > >
>> > > > The team driver would like to use this same flag since it is a load balancer
>> > > > as well. The side effect of not assigning IPv6 is a bonus. The fact that
>> > >
>> > > No, please leave IFF_SLAVE as it is. Both kernel and userspace have
>> > > their clear indications right now about the master/slave relationships.
>> >
>> > The team driver does create a master/slave relationship. The team slaves are
>> > literally slaves of the master device. It's not clear to me
>> > why you we can't mark the slaves of the team master as actually being
>> > slave interfaces?
>>
>> So? IFF_SLAVE flag serves a different purpose. That's it. Team does not
>> need it, bridge does not need it, macvlan does not need it, etc.
>
>I agree. But team *is* a load balancer. Why can't team mark its slave
>interfaces as IFF_SLAVE? They are literally slaves of a load balancer which
>is the exact meaning of the IFF_SLAVE flag.
I described that multiple times, don't want to repeat myself. Please
read the thread again.
>
>>
>>
>> >
>> > >
>> > >
>> > > > bridges and ovs are also likely broken is a different issue. Should there be
>> > > > a another flag that says "layer 2 only"? Very possibly, but that is
>> > > > something all these interfaces should be using to include bonding, team, eql,
>> > > > obs, bridge etc. That's not a reasonable objection to labeling the team
>> > > > slave as slaves since they are literally slaves of a load balancer.
>> > > >
>> > > >
>> > > >
^ permalink raw reply
* Re: [RFC PATCH bpf-next v4 3/7] bpf: add MAP_LOOKUP_AND_DELETE_ELEM syscall
From: Alexei Starovoitov @ 2018-10-04 23:37 UTC (permalink / raw)
To: Mauricio Vasquez B; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev
In-Reply-To: <153867315936.10087.889230344298708557.stgit@kernel>
On Thu, Oct 04, 2018 at 07:12:39PM +0200, Mauricio Vasquez B wrote:
> The following patch implements a bpf queue/stack maps that
> provides the peek/pop/push functions. There is not a direct
> relationship between those functions and the current maps
> syscalls, hence a new MAP_LOOKUP_AND_DELETE_ELEM syscall is added,
> this is mapped to the pop operation in the queue/stack maps
> and it is still to implement in other kind of maps.
>
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
> ---
> include/linux/bpf.h | 1 +
> include/uapi/linux/bpf.h | 1 +
> kernel/bpf/syscall.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 84 insertions(+)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 027697b6a22f..98c7eeb6d138 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -39,6 +39,7 @@ struct bpf_map_ops {
> void *(*map_lookup_elem)(struct bpf_map *map, void *key);
> int (*map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags);
> int (*map_delete_elem)(struct bpf_map *map, void *key);
> + void *(*map_lookup_and_delete_elem)(struct bpf_map *map, void *key);
>
> /* funcs called by prog_array and perf_event_array map */
> void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file,
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index f9187b41dff6..3bb94aa2d408 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -103,6 +103,7 @@ enum bpf_cmd {
> BPF_BTF_LOAD,
> BPF_BTF_GET_FD_BY_ID,
> BPF_TASK_FD_QUERY,
> + BPF_MAP_LOOKUP_AND_DELETE_ELEM,
> };
>
> enum bpf_map_type {
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index eb75e8af73ff..50957e243bfb 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -975,6 +975,85 @@ static int map_get_next_key(union bpf_attr *attr)
> return err;
> }
>
> +#define BPF_MAP_LOOKUP_AND_DELETE_ELEM_LAST_FIELD value
> +
> +static int map_lookup_and_delete_elem(union bpf_attr *attr)
> +{
> + void __user *ukey = u64_to_user_ptr(attr->key);
> + void __user *uvalue = u64_to_user_ptr(attr->value);
> + int ufd = attr->map_fd;
> + struct bpf_map *map;
> + void *key, *value, *ptr;
> + u32 value_size;
> + struct fd f;
> + int err;
> +
> + if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
copy-paste error
> + return -EINVAL;
> +
> + f = fdget(ufd);
> + map = __bpf_map_get(f);
> + if (IS_ERR(map))
> + return PTR_ERR(map);
> +
> + if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
> + err = -EPERM;
> + goto err_put;
> + }
> +
> + if (!map->ops->map_lookup_and_delete_elem) {
> + err = -ENOTSUPP;
> + goto err_put;
> + }
> +
> + key = __bpf_copy_key(ukey, map->key_size);
> + if (IS_ERR(key)) {
> + err = PTR_ERR(key);
> + goto err_put;
> + }
> +
> + value_size = map->value_size;
> +
> + err = -ENOMEM;
> + value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
> + if (!value)
> + goto free_key;
> +
> + err = -EFAULT;
> + if (copy_from_user(value, uvalue, value_size) != 0)
> + goto free_value;
> +
> + /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
> + * inside bpf map update or delete otherwise deadlocks are possible
> + */
> + preempt_disable();
> + __this_cpu_inc(bpf_prog_active);
> + rcu_read_lock();
> + ptr = map->ops->map_lookup_and_delete_elem(map, key);
> + if (ptr)
> + memcpy(value, ptr, value_size);
> + rcu_read_unlock();
> + err = ptr ? 0 : -ENOENT;
> + __this_cpu_dec(bpf_prog_active);
> + preempt_enable();
messed up formatting
> +
> + if (err)
> + goto free_value;
> +
> + if (copy_to_user(uvalue, value, value_size) != 0)
> + goto free_value;
> +
> + err = 0;
> +
> +free_value:
> + kfree(value);
> +free_key:
> + kfree(key);
> +err_put:
> + fdput(f);
> + return err;
> +}
> +
> static const struct bpf_prog_ops * const bpf_prog_types[] = {
> #define BPF_PROG_TYPE(_id, _name) \
> [_id] = & _name ## _prog_ops,
> @@ -2448,6 +2527,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
> case BPF_TASK_FD_QUERY:
> err = bpf_task_fd_query(&attr, uattr);
> break;
> + case BPF_MAP_LOOKUP_AND_DELETE_ELEM:
> + err = map_lookup_and_delete_elem(&attr);
> + break;
> default:
> err = -EINVAL;
> break;
>
^ permalink raw reply
* [PATCH] ixgbe: allow IPsec Tx offload in VEPA mode
From: Shannon Nelson @ 2018-10-04 23:28 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher; +Cc: netdev
When it's possible that the PF might end up trying to send a
packet to one of its own VFs, we have to forbid IPsec offload
because the device drops the packets into a black hole.
See commit 47b6f50077e6 ("ixgbe: disallow IPsec Tx offload
when in SR-IOV mode") for more info.
This really is only necessary when the device is in the default
VEB mode. If instead the device is running in VEPA mode,
the packets will go through the encryption engine and out the
MAC/PHY as normal, and get "hairpinned" as needed by the switch.
So let's not block IPsec offload when in VEPA mode. To get
there with the ixgbe device, use the handy 'bridge' command:
bridge link set dev eth1 hwmode vepa
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index fd1b054..4d77f42 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -4,6 +4,7 @@
#include "ixgbe.h"
#include <net/xfrm.h>
#include <crypto/aead.h>
+#include <linux/if_bridge.h>
#define IXGBE_IPSEC_KEY_BITS 160
static const char aes_gcm_name[] = "rfc4106(gcm(aes))";
@@ -693,7 +694,8 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
} else {
struct tx_sa tsa;
- if (adapter->num_vfs)
+ if (adapter->num_vfs &&
+ adapter->bridge_mode != BRIDGE_MODE_VEPA)
return -EOPNOTSUPP;
/* find the first unused index */
--
2.7.4
^ permalink raw reply related
* Re: [bpf-next PATCH 1/3] net: fix generic XDP to handle if eth header was mangled
From: Song Liu @ 2018-10-04 23:20 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Networking, Daniel Borkmann, yoel, Alexei Starovoitov
In-Reply-To: <20181003160413.755f9cd5@redhat.com>
Hi Jesper,
On Wed, Oct 3, 2018 at 7:04 AM Jesper Dangaard Brouer <brouer@redhat.com> wrote:
>
> On Tue, 25 Sep 2018 22:36:39 -0700
> Song Liu <liu.song.a23@gmail.com> wrote:
>
> > On Tue, Sep 25, 2018 at 7:26 AM Jesper Dangaard Brouer
> > <brouer@redhat.com> wrote:
> > >
> > > XDP can modify (and resize) the Ethernet header in the packet.
> > >
> > > There is a bug in generic-XDP, because skb->protocol and skb->pkt_type
> > > are setup before reaching (netif_receive_)generic_xdp.
> > >
> > > This bug was hit when XDP were popping VLAN headers (changing
> > > eth->h_proto), as skb->protocol still contains VLAN-indication
> > > (ETH_P_8021Q) causing invocation of skb_vlan_untag(skb), which corrupt
> > > the packet (basically popping the VLAN again).
> > >
> > > This patch catch if XDP changed eth header in such a way, that SKB
> > > fields needs to be updated.
> > >
> > > Fixes: d445516966dc ("net: xdp: support xdp generic on virtual devices")
> > > Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> > > ---
> > > net/core/dev.c | 14 ++++++++++++++
> > > 1 file changed, 14 insertions(+)
> > >
> > > diff --git a/net/core/dev.c b/net/core/dev.c
> > > index ca78dc5a79a3..db6d89f536cb 100644
> > > --- a/net/core/dev.c
> > > +++ b/net/core/dev.c
> > > @@ -4258,6 +4258,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
> > > struct netdev_rx_queue *rxqueue;
> > > void *orig_data, *orig_data_end;
> > > u32 metalen, act = XDP_DROP;
> > > + __be16 orig_eth_type;
> > > + struct ethhdr *eth;
> > > + bool orig_bcast;
> > > int hlen, off;
> > > u32 mac_len;
> > >
> > > @@ -4298,6 +4301,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
> > > xdp->data_hard_start = skb->data - skb_headroom(skb);
> > > orig_data_end = xdp->data_end;
> > > orig_data = xdp->data;
> > > + eth = (struct ethhdr *)xdp->data;
> > > + orig_bcast = is_multicast_ether_addr_64bits(eth->h_dest);
> > > + orig_eth_type = eth->h_proto;
> > >
> > > rxqueue = netif_get_rxqueue(skb);
> > > xdp->rxq = &rxqueue->xdp_rxq;
> > > @@ -4321,6 +4327,14 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
> > >
> > > }
> > >
> > > + /* check if XDP changed eth hdr such SKB needs update */
> > > + eth = (struct ethhdr *)xdp->data;
> > > + if ((orig_eth_type != eth->h_proto) ||
> > > + (orig_bcast != is_multicast_ether_addr_64bits(eth->h_dest))) {
> >
> > Is the actions below always correct for the condition above? Do we need
> > to confirm the SKB is updated properly?
>
> I cannot find the issue that you are hinting to?
>
> If the BPF prog used bpf_xdp_adjust_head(), which the included selftest
> program does, then skb->data have been appropriately adjusted just
> above (with __skb_pull(skb, off) or __skb_push(skb, -off)), which makes
> the call to skb_reset_mac_header(skb) inside eth_type_trans() correct.
>
> I've double checked the code, and I cannot find anything wrong...
> please let me know if I missed something!?
>
>
> > > + __skb_push(skb, mac_len);
> > > + skb->protocol = eth_type_trans(skb, skb->dev);
>
> We could change mac_len to be ETH_HLEN, because inside eth_type_trans()
> the constant ETH_HLEN is used, that way we are 100% sure the
> skb_push/skb_pull are "paired". Will that be better for you?
Thanks for the explanation. Now I understand it better.
I think using ETH_HLEN is better. Both napi_frags_finish() and
__dev_forward_skb()
use similar pattern.
Song
^ permalink raw reply
* [PATCH iproute2 net-next v2 5/6] tc: Add support for configuring the taprio scheduler
From: Vinicius Costa Gomes @ 2018-10-04 23:17 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri,
jesus.sanchez-palencia, ilias.apalodimas, simon.fok
In-Reply-To: <20181004231711.6058-1-vinicius.gomes@intel.com>
This traffic scheduler allows traffic classes states (transmission
allowed/not allowed, in the simplest case) to be scheduled, according
to a pre-generated time sequence. This is the basis of the IEEE
802.1Qbv specification.
Example configuration:
tc qdisc replace dev enp3s0 parent root handle 100 taprio \
num_tc 3 \
map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \
queues 1@0 1@1 2@2 \
base-time 1528743495910289987 \
sched-entry S 01 300000 \
sched-entry S 02 300000 \
sched-entry S 04 300000 \
clockid CLOCK_TAI
The configuration format is similar to mqprio. The main difference is
the presence of a schedule, built by multiple "sched-entry"
definitions, each entry has the following format:
sched-entry <CMD> <GATE MASK> <INTERVAL>
The only supported <CMD> is "S", which means "SetGateStates",
following the IEEE 802.1Qbv-2015 definition (Table 8-6). <GATE MASK>
is a bitmask where each bit is a associated with a traffic class, so
bit 0 (the least significant bit) being "on" means that traffic class
0 is "active" for that schedule entry. <INTERVAL> is a time duration
in nanoseconds that specifies for how long that state defined by <CMD>
and <GATE MASK> should be held before moving to the next entry.
This schedule is circular, that is, after the last entry is executed
it starts from the first one, indefinitely.
The other parameters can be defined as follows:
- base-time: specifies the instant when the schedule starts, if
'base-time' is a time in the past, the schedule will start at
base-time + (N * cycle-time)
where N is the smallest integer so the resulting time is greater
than "now", and "cycle-time" is the sum of all the intervals of the
entries in the schedule;
- clockid: specifies the reference clock to be used;
The parameters should be similar to what the IEEE 802.1Q family of
specification defines.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
---
tc/Makefile | 1 +
tc/q_taprio.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 401 insertions(+)
create mode 100644 tc/q_taprio.c
diff --git a/tc/Makefile b/tc/Makefile
index 5a1a7ff9..25a28284 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -74,6 +74,7 @@ TCMODULES += e_bpf.o
TCMODULES += f_matchall.o
TCMODULES += q_cbs.o
TCMODULES += q_etf.o
+TCMODULES += q_taprio.o
TCSO :=
ifeq ($(TC_CONFIG_ATM),y)
diff --git a/tc/q_taprio.c b/tc/q_taprio.c
new file mode 100644
index 00000000..562dacb8
--- /dev/null
+++ b/tc/q_taprio.c
@@ -0,0 +1,400 @@
+/*
+ * q_taprio.c Time Aware Priority Scheduler
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+ * Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "utils.h"
+#include "tc_util.h"
+#include "list.h"
+
+struct sched_entry {
+ struct list_head list;
+ uint32_t index;
+ uint32_t interval;
+ uint32_t gatemask;
+ uint8_t cmd;
+};
+
+#define CLOCKID_INVALID (-1)
+static const struct static_clockid {
+ const char *name;
+ clockid_t clockid;
+} clockids_sysv[] = {
+ { "REALTIME", CLOCK_REALTIME },
+ { "TAI", CLOCK_TAI },
+ { "BOOTTIME", CLOCK_BOOTTIME },
+ { "MONOTONIC", CLOCK_MONOTONIC },
+ { NULL }
+};
+
+static void explain(void)
+{
+ fprintf(stderr, "Usage: ... taprio clockid CLOCKID\n");
+ fprintf(stderr, " [num_tc NUMBER] [map P0 P1 ...] ");
+ fprintf(stderr, " [queues COUNT@OFFSET COUNT@OFFSET COUNT@OFFSET ...] ");
+ fprintf(stderr, " [ [sched-entry index cmd gate-mask interval] ... ] ");
+ fprintf(stderr, " [base-time time] ");
+ fprintf(stderr, "\nCLOCKID must be a valid SYS-V id (i.e. CLOCK_TAI)");
+ fprintf(stderr, "\n");
+}
+
+static void explain_clockid(const char *val)
+{
+ fprintf(stderr, "taprio: illegal value for \"clockid\": \"%s\".\n", val);
+ fprintf(stderr, "It must be a valid SYS-V id (i.e. CLOCK_TAI)\n");
+}
+
+static int get_clockid(__s32 *val, const char *arg)
+{
+ const struct static_clockid *c;
+
+ /* Drop the CLOCK_ prefix if that is being used. */
+ if (strcasestr(arg, "CLOCK_") != NULL)
+ arg += sizeof("CLOCK_") - 1;
+
+ for (c = clockids_sysv; c->name; c++) {
+ if (strcasecmp(c->name, arg) == 0) {
+ *val = c->clockid;
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static const char* get_clock_name(clockid_t clockid)
+{
+ const struct static_clockid *c;
+
+ for (c = clockids_sysv; c->name; c++) {
+ if (clockid == c->clockid)
+ return c->name;
+ }
+
+ return "invalid";
+}
+
+static const char *entry_cmd_to_str(__u8 cmd)
+{
+ switch (cmd) {
+ case TC_TAPRIO_CMD_SET_GATES:
+ return "S";
+ default:
+ return "Invalid";
+ }
+}
+
+static int str_to_entry_cmd(const char *str)
+{
+ if (strcmp(str, "S") == 0)
+ return TC_TAPRIO_CMD_SET_GATES;
+
+ return -1;
+}
+
+static int add_sched_list(struct list_head *sched_entries, struct nlmsghdr *n)
+{
+ struct sched_entry *e;
+
+ list_for_each_entry(e, sched_entries, list) {
+ struct rtattr *a;
+
+ a = addattr_nest(n, 1024, TCA_TAPRIO_SCHED_ENTRY);
+
+ addattr_l(n, 1024, TCA_TAPRIO_SCHED_ENTRY_CMD, &e->cmd, sizeof(e->cmd));
+ addattr_l(n, 1024, TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, &e->gatemask, sizeof(e->gatemask));
+ addattr_l(n, 1024, TCA_TAPRIO_SCHED_ENTRY_INTERVAL, &e->interval, sizeof(e->interval));
+
+ addattr_nest_end(n, a);
+ }
+
+ return 0;
+}
+
+static void explain_sched_entry(void)
+{
+ fprintf(stderr, "Usage: ... taprio ... sched-entry <cmd> <gate mask> <interval>\n");
+}
+
+static struct sched_entry *create_entry(uint32_t gatemask, uint32_t interval, uint8_t cmd)
+{
+ struct sched_entry *e;
+
+ e = calloc(1, sizeof(*e));
+ if (!e)
+ return NULL;
+
+ e->gatemask = gatemask;
+ e->interval = interval;
+ e->cmd = cmd;
+
+ return e;
+}
+
+static int taprio_parse_opt(struct qdisc_util *qu, int argc,
+ char **argv, struct nlmsghdr *n, const char *dev)
+{
+ __s32 clockid = CLOCKID_INVALID;
+ struct tc_mqprio_qopt opt = { };
+ struct list_head sched_entries;
+ struct rtattr *tail;
+ __s64 base_time = 0;
+ int err, idx;
+
+ INIT_LIST_HEAD(&sched_entries);
+
+ while (argc > 0) {
+ idx = 0;
+ if (strcmp(*argv, "num_tc") == 0) {
+ NEXT_ARG();
+ if (get_u8(&opt.num_tc, *argv, 10)) {
+ fprintf(stderr, "Illegal \"num_tc\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "map") == 0) {
+ while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) {
+ NEXT_ARG();
+ if (get_u8(&opt.prio_tc_map[idx], *argv, 10)) {
+ PREV_ARG();
+ break;
+ }
+ idx++;
+ }
+ for ( ; idx < TC_QOPT_MAX_QUEUE; idx++)
+ opt.prio_tc_map[idx] = 0;
+ } else if (strcmp(*argv, "queues") == 0) {
+ char *tmp, *tok;
+
+ while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) {
+ NEXT_ARG();
+
+ tmp = strdup(*argv);
+ if (!tmp)
+ break;
+
+ tok = strtok(tmp, "@");
+ if (get_u16(&opt.count[idx], tok, 10)) {
+ free(tmp);
+ PREV_ARG();
+ break;
+ }
+ tok = strtok(NULL, "@");
+ if (get_u16(&opt.offset[idx], tok, 10)) {
+ free(tmp);
+ PREV_ARG();
+ break;
+ }
+ free(tmp);
+ idx++;
+ }
+ } else if (strcmp(*argv, "sched-entry") == 0) {
+ uint32_t mask, interval;
+ struct sched_entry *e;
+ uint8_t cmd;
+
+ NEXT_ARG();
+ err = str_to_entry_cmd(*argv);
+ if (err < 0) {
+ explain_sched_entry();
+ return -1;
+ }
+ cmd = err;
+
+ NEXT_ARG();
+ if (get_u32(&mask, *argv, 16)) {
+ explain_sched_entry();
+ return -1;
+ }
+
+ NEXT_ARG();
+ if (get_u32(&interval, *argv, 0)) {
+ explain_sched_entry();
+ return -1;
+ }
+
+ e = create_entry(mask, interval, cmd);
+ if (!e) {
+ fprintf(stderr, "taprio: not enough memory for new schedule entry\n");
+ return -1;
+ }
+
+ list_add_tail(&e->list, &sched_entries);
+
+ } else if (strcmp(*argv, "base-time") == 0) {
+ NEXT_ARG();
+ if (get_s64(&base_time, *argv, 10)) {
+ PREV_ARG();
+ break;
+ }
+ } else if (strcmp(*argv, "clockid") == 0) {
+ NEXT_ARG();
+ if (clockid != CLOCKID_INVALID) {
+ fprintf(stderr, "taprio: duplicate \"clockid\" specification\n");
+ return -1;
+ }
+ if (get_clockid(&clockid, *argv)) {
+ explain_clockid(*argv);
+ return -1;
+ }
+ } else if (strcmp(*argv, "help") == 0) {
+ explain();
+ return -1;
+ } else {
+ fprintf(stderr, "Unknown argument\n");
+ return -1;
+ }
+ argc--; argv++;
+ }
+
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+
+ if (opt.num_tc > 0)
+ addattr_l(n, 1024, TCA_TAPRIO_ATTR_PRIOMAP, &opt, sizeof(opt));
+
+ if (base_time)
+ addattr_l(n, 1024, TCA_TAPRIO_ATTR_SCHED_BASE_TIME, &base_time, sizeof(base_time));
+
+ addattr_l(n, 1024, TCA_TAPRIO_ATTR_SCHED_CLOCKID, &clockid, sizeof(clockid));
+
+ if (!list_empty(&sched_entries)) {
+ struct rtattr *entry_list;
+ entry_list = addattr_nest(n, 1024, TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST | NLA_F_NESTED);
+
+ err = add_sched_list(&sched_entries, n);
+ if (err < 0) {
+ fprintf(stderr, "Could not add schedule to netlink message\n");
+ return -1;
+ }
+
+ addattr_nest_end(n, entry_list);
+ }
+
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+
+ return 0;
+}
+
+static int print_sched_list(FILE *f, struct rtattr *list)
+{
+ struct rtattr *item;
+ int rem;
+
+ if (list == NULL)
+ return 0;
+
+ rem = RTA_PAYLOAD(list);
+
+ open_json_array(PRINT_JSON, "schedule");
+
+ for (item = RTA_DATA(list); RTA_OK(item, rem); item = RTA_NEXT(item, rem)) {
+ struct rtattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1];
+ __u32 index = 0, gatemask = 0, interval = 0;
+ __u8 command = 0;
+
+ parse_rtattr_nested(tb, TCA_TAPRIO_SCHED_ENTRY_MAX, item);
+
+ if (tb[TCA_TAPRIO_SCHED_ENTRY_INDEX])
+ index = rta_getattr_u32(tb[TCA_TAPRIO_SCHED_ENTRY_INDEX]);
+
+ if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD])
+ command = rta_getattr_u8(tb[TCA_TAPRIO_SCHED_ENTRY_CMD]);
+
+ if (tb[TCA_TAPRIO_SCHED_ENTRY_GATE_MASK])
+ gatemask = rta_getattr_u32(tb[TCA_TAPRIO_SCHED_ENTRY_GATE_MASK]);
+
+ if (tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL])
+ interval = rta_getattr_u32(tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL]);
+
+ open_json_object(NULL);
+ print_uint(PRINT_ANY, "index", "\tindex %u", index);
+ print_string(PRINT_ANY, "cmd", " cmd %s", entry_cmd_to_str(command));
+ print_0xhex(PRINT_ANY, "gatemask", " gatemask %#x", gatemask);
+ print_uint(PRINT_ANY, "interval", " interval %u", interval);
+ close_json_object();
+
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+ }
+
+ close_json_array(PRINT_ANY, "");
+
+ return 0;
+}
+
+static int taprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
+{
+ struct rtattr *tb[TCA_TAPRIO_ATTR_MAX + 1];
+ struct tc_mqprio_qopt *qopt = 0;
+ __s32 clockid = CLOCKID_INVALID;
+ __s64 base_time = 0;
+ int i;
+
+ if (opt == NULL)
+ return 0;
+
+ parse_rtattr_nested(tb, TCA_TAPRIO_ATTR_MAX, opt);
+
+ if (tb[TCA_TAPRIO_ATTR_PRIOMAP] == NULL)
+ return -1;
+
+ qopt = RTA_DATA(tb[TCA_TAPRIO_ATTR_PRIOMAP]);
+
+ print_uint(PRINT_ANY, "tc", "tc %u ", qopt->num_tc);
+
+ open_json_array(PRINT_ANY, "map");
+ for (i = 0; i <= TC_PRIO_MAX; i++)
+ print_uint(PRINT_ANY, NULL, " %u", qopt->prio_tc_map[i]);
+ close_json_array(PRINT_ANY, "");
+
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+
+ open_json_array(PRINT_ANY, "queues");
+ for (i = 0; i < qopt->num_tc; i++) {
+ open_json_object(NULL);
+ print_uint(PRINT_ANY, "offset", " offset %u", qopt->offset[i]);
+ print_uint(PRINT_ANY, "count", " count %u", qopt->count[i]);
+ close_json_object();
+ }
+ close_json_array(PRINT_ANY, "");
+
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+
+ if (tb[TCA_TAPRIO_ATTR_SCHED_BASE_TIME])
+ base_time = rta_getattr_s64(tb[TCA_TAPRIO_ATTR_SCHED_BASE_TIME]);
+
+ if (tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID])
+ clockid = rta_getattr_s32(tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]);
+
+ print_string(PRINT_ANY, "clockid", "clockid %s", get_clock_name(clockid));
+
+ print_lluint(PRINT_ANY, "base_time", " base-time %lld", base_time);
+
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+
+ return print_sched_list(f, tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST]);
+}
+
+struct qdisc_util taprio_qdisc_util = {
+ .id = "taprio",
+ .parse_qopt = taprio_parse_opt,
+ .print_qopt = taprio_print_opt,
+};
--
2.19.0
^ permalink raw reply related
* [PATCH iproute2 net-next v2 3/6] libnetlink: Add helper for getting a __s32 from netlink msgs
From: Vinicius Costa Gomes @ 2018-10-04 23:17 UTC (permalink / raw)
To: netdev
Cc: Jesus Sanchez-Palencia, jhs, xiyou.wangcong, jiri,
ilias.apalodimas, simon.fok
In-Reply-To: <20181004231711.6058-1-vinicius.gomes@intel.com>
From: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
This function retrieves a signed 32-bit integer from a netlink message
and returns it.
Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
---
include/libnetlink.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 88164975..79ba793e 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -185,6 +185,10 @@ static inline __u64 rta_getattr_u64(const struct rtattr *rta)
memcpy(&tmp, RTA_DATA(rta), sizeof(__u64));
return tmp;
}
+static inline __s32 rta_getattr_s32(const struct rtattr *rta)
+{
+ return *(__s32 *)RTA_DATA(rta);
+}
static inline __s64 rta_getattr_s64(const struct rtattr *rta)
{
__s64 tmp;
--
2.19.0
^ permalink raw reply related
* [PATCH iproute2 net-next v2 2/6] include: Add helper to retrieve a __s64 from a netlink msg
From: Vinicius Costa Gomes @ 2018-10-04 23:17 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri,
jesus.sanchez-palencia, ilias.apalodimas, simon.fok
In-Reply-To: <20181004231711.6058-1-vinicius.gomes@intel.com>
This allows signed 64-bit integers to be retrieved from a netlink
message.
---
include/libnetlink.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 9d9249e6..88164975 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -185,6 +185,13 @@ static inline __u64 rta_getattr_u64(const struct rtattr *rta)
memcpy(&tmp, RTA_DATA(rta), sizeof(__u64));
return tmp;
}
+static inline __s64 rta_getattr_s64(const struct rtattr *rta)
+{
+ __s64 tmp;
+
+ memcpy(&tmp, RTA_DATA(rta), sizeof(__s64));
+ return tmp;
+}
static inline const char *rta_getattr_str(const struct rtattr *rta)
{
return (const char *)RTA_DATA(rta);
--
2.19.0
^ permalink raw reply related
* [PATCH iproute2 net-next v2 4/6] include: add definitions for taprio [DO NOT COMMIT]
From: Vinicius Costa Gomes @ 2018-10-04 23:17 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri,
jesus.sanchez-palencia, ilias.apalodimas, simon.fok
In-Reply-To: <20181004231711.6058-1-vinicius.gomes@intel.com>
DO NOT COMMIT
This patch exists only to ease the testing, until this header is
updated with the definitions from the kernel.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
include/uapi/linux/pkt_sched.h | 52 ++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 8975fd1a..89ee47c2 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -395,9 +395,9 @@ enum {
struct tc_htb_xstats {
__u32 lends;
__u32 borrows;
- __u32 giants; /* too big packets (rate will not be accurate) */
- __u32 tokens;
- __u32 ctokens;
+ __u32 giants; /* unused since 'Make HTB scheduler work with TSO.' */
+ __s32 tokens;
+ __s32 ctokens;
};
/* HFSC section */
@@ -1084,4 +1084,50 @@ enum {
CAKE_ATM_MAX
};
+
+/* TAPRIO */
+enum {
+ TC_TAPRIO_CMD_SET_GATES = 0x00,
+ TC_TAPRIO_CMD_SET_AND_HOLD = 0x01,
+ TC_TAPRIO_CMD_SET_AND_RELEASE = 0x02,
+};
+
+enum {
+ TCA_TAPRIO_SCHED_ENTRY_UNSPEC,
+ TCA_TAPRIO_SCHED_ENTRY_INDEX, /* u32 */
+ TCA_TAPRIO_SCHED_ENTRY_CMD, /* u8 */
+ TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, /* u32 */
+ TCA_TAPRIO_SCHED_ENTRY_INTERVAL, /* u32 */
+ __TCA_TAPRIO_SCHED_ENTRY_MAX,
+};
+#define TCA_TAPRIO_SCHED_ENTRY_MAX (__TCA_TAPRIO_SCHED_ENTRY_MAX - 1)
+
+/* The format for schedule entry list is:
+ * [TCA_TAPRIO_SCHED_ENTRY_LIST]
+ * [TCA_TAPRIO_SCHED_ENTRY]
+ * [TCA_TAPRIO_SCHED_ENTRY_CMD]
+ * [TCA_TAPRIO_SCHED_ENTRY_GATES]
+ * [TCA_TAPRIO_SCHED_ENTRY_INTERVAL]
+ */
+enum {
+ TCA_TAPRIO_SCHED_UNSPEC,
+ TCA_TAPRIO_SCHED_ENTRY,
+ __TCA_TAPRIO_SCHED_MAX,
+};
+
+#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1)
+
+enum {
+ TCA_TAPRIO_ATTR_UNSPEC,
+ TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
+ TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */
+ TCA_TAPRIO_ATTR_SCHED_BASE_TIME, /* s64 */
+ TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */
+ TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */
+ TCA_TAPRIO_PAD,
+ __TCA_TAPRIO_ATTR_MAX,
+};
+
+#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
+
#endif
--
2.19.0
^ permalink raw reply related
* [PATCH iproute2 net-next v2 1/6] utils: Implement get_s64()
From: Vinicius Costa Gomes @ 2018-10-04 23:17 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri,
jesus.sanchez-palencia, ilias.apalodimas, simon.fok
In-Reply-To: <20181004231711.6058-1-vinicius.gomes@intel.com>
Add this helper to read signed 64-bit integers from a string.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
include/utils.h | 1 +
lib/utils.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/include/utils.h b/include/utils.h
index 8cb4349e..58574a05 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -139,6 +139,7 @@ int get_time_rtt(unsigned *val, const char *arg, int *raw);
#define get_byte get_u8
#define get_ushort get_u16
#define get_short get_s16
+int get_s64(__s64 *val, const char *arg, int base);
int get_u64(__u64 *val, const char *arg, int base);
int get_u32(__u32 *val, const char *arg, int base);
int get_s32(__s32 *val, const char *arg, int base);
diff --git a/lib/utils.c b/lib/utils.c
index e87ecf31..1b84b801 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -383,6 +383,27 @@ int get_u8(__u8 *val, const char *arg, int base)
return 0;
}
+int get_s64(__s64 *val, const char *arg, int base)
+{
+ long res;
+ char *ptr;
+
+ errno = 0;
+
+ if (!arg || !*arg)
+ return -1;
+ res = strtoll(arg, &ptr, base);
+ if (!ptr || ptr == arg || *ptr)
+ return -1;
+ if ((res == LLONG_MIN || res == LLONG_MAX) && errno == ERANGE)
+ return -1;
+ if (res > INT64_MAX || res < INT64_MIN)
+ return -1;
+
+ *val = res;
+ return 0;
+}
+
int get_s32(__s32 *val, const char *arg, int base)
{
long res;
--
2.19.0
^ permalink raw reply related
* [PATCH iproute2 net-next v2 6/6] taprio: Add manpage for tc-taprio(8)
From: Vinicius Costa Gomes @ 2018-10-04 23:17 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri,
jesus.sanchez-palencia, ilias.apalodimas, simon.fok
In-Reply-To: <20181004231711.6058-1-vinicius.gomes@intel.com>
This documents the parameters and provides an example of usage.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
man/man8/tc-taprio.8 | 142 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 142 insertions(+)
create mode 100644 man/man8/tc-taprio.8
diff --git a/man/man8/tc-taprio.8 b/man/man8/tc-taprio.8
new file mode 100644
index 00000000..92055b43
--- /dev/null
+++ b/man/man8/tc-taprio.8
@@ -0,0 +1,142 @@
+.TH TAPRIO 8 "25 Sept 2018" "iproute2" "Linux"
+.SH NAME
+TAPRIO \- Time Aware Priority Shaper
+.SH SYNOPSIS
+.B tc qdisc ... dev
+dev
+.B parent
+classid
+.B [ handle
+major:
+.B ] taprio num_tc
+tcs
+.ti +8
+.B map
+P0 P1 P2 ...
+.B queues
+count1@offset1 count2@offset2 ...
+.ti +8
+.B base-time
+base-time
+.B clockid
+clockid
+.ti +8
+.B sched-entry
+<command 1> <gate mask 1> <interval 1>
+.ti +8
+.B sched-entry
+<command 2> <gate mask 2> <interval 2>
+.ti +8
+.B sched-entry
+<command 3> <gate mask 3> <interval 3>
+.ti +8
+.B sched-entry
+<command N> <gate mask N> <interval N>
+
+.SH DESCRIPTION
+The TAPRIO qdisc implements a simplified version of the scheduling
+state machine defined by IEEE 802.1Q-2018 Section 8.6.9, which allows
+configuration of a sequence of gate states, where each gate state
+allows outgoing traffic for a subset (potentially empty) of traffic
+classes.
+
+How traffic is mapped to different hardware queues is similar to
+.BR mqprio(8)
+and so the
+.B map
+and
+.Q queues
+parameters have the same meaning.
+
+The other parameters specify the schedule, and at what point in time
+it should start (it can behave as the schedule started in the past).
+
+.SH PARAMETERS
+.TP
+num_tc
+.BR
+Number of traffic classes to use. Up to 16 classes supported.
+
+.TP
+map
+.br
+The priority to traffic class map. Maps priorities 0..15 to a specified
+traffic class. See
+.BR mqprio(8)
+for more details.
+
+.TP
+queues
+.br
+Provide count and offset of queue range for each traffic class. In the
+format,
+.B count@offset.
+Queue ranges for each traffic classes cannot overlap and must be a
+contiguous range of queues.
+
+.TP
+base-time
+.br
+Specifies the instant in nanoseconds, using the reference of
+.B clockid,
+defining the time when the schedule starts. If 'base-time' is a time
+in the past, the schedule will start at
+
+base-time + (N * cycle-time)
+
+where N is the smallest integer so the resulting time is greater than
+"now", and "cycle-time" is the sum of all the intervals of the entries
+in the schedule;
+
+.TP
+clockid
+.br
+Specifies the clock to be used by qdisc's internal timer for measuring
+time and scheduling events.
+
+.TP
+sched-entry
+.br
+There may multiple
+.B sched-entry
+parameters in a single schedule. Each one has the
+
+sched-entry <command> <gatemask> <interval>
+
+format. The only supported <command> is "S", which
+means "SetGateStates", following the IEEE 802.1Q-2018 definition
+(Table 8-7). <gate mask> is a bitmask where each bit is a associated
+with a traffic class, so bit 0 (the least significant bit) being "on"
+means that traffic class 0 is "active" for that schedule entry.
+<interval> is a time duration, in nanoseconds, that specifies for how
+long that state defined by <command> and <gate mask> should be held
+before moving to the next entry.
+
+.SH EXAMPLES
+
+The following example shows how an traffic schedule with three traffic
+classes ("num_tc 3"), which are separated different traffic classes,
+we are going to call these TC 0, TC 1 and TC 2. We could read the
+"map" parameter below as: traffic with priority 3 is classified as TC
+0, priority 2 is classified as TC 1 and the rest is classified as TC
+2.
+
+The schedule will start at instant 1528743495910289987 using the
+reference CLOCK_TAI. The schedule is composed of three entries each of
+300us duration.
+
+.EX
+# tc qdisc replace dev eth0 parent root handle 100 taprio \\
+ num_tc 3 \\
+ map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \\
+ queues 1@0 1@1 2@2 \\
+ base-time 1528743495910289987 \\
+ sched-entry S 01 300000 \\
+ sched-entry S 02 300000 \\
+ sched-entry S 04 300000 \\
+ clockid CLOCK_TAI
+.EE
+
+
+.SH AUTHORS
+Vinicius Costa Gomes <vinicius.gomes@intel.com>
--
2.19.0
^ permalink raw reply related
* [PATCH iproute2 net-next v2 0/6] Introduce the taprio scheduler
From: Vinicius Costa Gomes @ 2018-10-04 23:17 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri,
jesus.sanchez-palencia, ilias.apalodimas, simon.fok
Hi,
Changes from v1:
- Remove references to the "H" (Set-Gates-And-Hold-MAC) and "R"
(Set-Gates-And-Release-MAC) commands, as these commands will only
be used when Frame Preemption support is added (David Ahern);
- Moved the functions that print and read commands to be closer (David
Ahern);
Changes from RFC:
- Removed support for the sched-file parameter, in favor of
supporting the batch mode feature;
This is the iproute2 side of the taprio v1 series.
Please see the kernel side cover letter for more information about how
to test this.
Cheers,
^ permalink raw reply
* Re: [PATCH 2/2] can: tcan4x5x: Add tcan4x5x driver to the kernel
From: Wolfgang Grandegger @ 2018-10-05 5:56 UTC (permalink / raw)
To: Dan Murphy, mkl, davem; +Cc: linux-can, netdev, linux-kernel, Mario.Huettel
In-Reply-To: <7a75a096-d07f-693e-74b6-74a76c00acf5@ti.com>
Hello Dan,
Am 04.10.2018 um 22:26 schrieb Dan Murphy:
> Wolfgang
>
> On 09/26/2018 12:54 PM, Wolfgang Grandegger wrote:
>> Hello,
>>
>> I wonder why you do not extend the existing MCAN driver by implementing
>> an interface to access the hardware. Would that be feasible?
>>
>
> I have created a m_can_core code base that can be used by other hardware that
> have special needs.
>
> So I have created the m_can_core, m_can and the tcan4x5x drivers.
Great, I still think it's a good idea to have just one "m_can" driver.
> I can RFC the code to see if this is what is expected.
> It is not 100% working but it is close enough for a directional call.
That would be nice! Most of the SPI accesses are pure register accesses.
A few read/write more bytes at a time (for data, etc.) but that could be
handled by appropriate interface functions. One general problem is that
SPI accesses are not possible from interrupt context requiring threads
or work queues. Also NAPI is usually not used.
Other opinions?
Wolfgang.
PS: I have added Mario to the CC. Maybe he could test a common driver on
his M_CAN hardware.
^ permalink raw reply
* Re: [PATCH v2] typo fix in Documentation/networking/af_xdp.rst
From: Daniel Borkmann @ 2018-10-04 22:14 UTC (permalink / raw)
To: Björn Töpel, kdjimeli; +Cc: Netdev
In-Reply-To: <CAJ+HfNiSn5ehkArKMgO3P-xwnDedVJvOTQqHw0-st9y8PuoH_w@mail.gmail.com>
On 10/04/2018 07:38 PM, Björn Töpel wrote:
> Den tors 4 okt. 2018 kl 19:03 skrev Konrad Djimeli <kdjimeli@igalia.com>:
>>
>> Fix a simple typo: Completetion -> Completion
>>
>> Signed-off-by: Konrad Djimeli <kdjimeli@igalia.com>
>> ---
>> Changes in v2:
>> - Update line below to be same length as text above
>>
>> Documentation/networking/af_xdp.rst | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/networking/af_xdp.rst b/Documentation/networking/af_xdp.rst
>> index ff929cfab4f4..4ae4f9d8f8fe 100644
>> --- a/Documentation/networking/af_xdp.rst
>> +++ b/Documentation/networking/af_xdp.rst
>> @@ -159,8 +159,8 @@ log2(2048) LSB of the addr will be masked off, meaning that 2048, 2050
>> and 3000 refers to the same chunk.
>>
>>
>> -UMEM Completetion Ring
>> -~~~~~~~~~~~~~~~~~~~~~~
>> +UMEM Completion Ring
>> +~~~~~~~~~~~~~~~~~~~~
>>
>> The Completion Ring is used transfer ownership of UMEM frames from
>> kernel-space to user-space. Just like the Fill ring, UMEM indicies are
>> --
>> 2.17.1
>>
>
> Thanks Konrad! For future patches, you should tag your patch with
> 'bpf' or 'bpf-next' as pointed out in
> Documentation/bpf/bpf_devel_QA.rst. I guess this should go to 'bpf'.
>
> Acked-by: Björn Töpel <bjorn.topel@intel.com>
I think it's so minor that bpf-next is totally fine, therefore applied
there, thanks Konrad!
^ permalink raw reply
* Re: [PATCH bpf-next] bpf: emit audit messages upon successful prog load and unload
From: Alexei Starovoitov @ 2018-10-04 22:10 UTC (permalink / raw)
To: Jesper Dangaard Brouer; +Cc: Daniel Borkmann, ast, netdev, Jiri Olsa, acme
In-Reply-To: <20181004222231.2edd5add@redhat.com>
On Thu, Oct 04, 2018 at 10:22:31PM +0200, Jesper Dangaard Brouer wrote:
> On Thu, 4 Oct 2018 21:41:17 +0200 Daniel Borkmann <daniel@iogearbox.net> wrote:
>
> > On 10/04/2018 08:39 PM, Jesper Dangaard Brouer wrote:
> > > On Thu, 4 Oct 2018 10:11:43 -0700 Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > >> On Thu, Oct 04, 2018 at 03:50:38PM +0200, Daniel Borkmann wrote:
> [...]
> > >>
> > >> If the purpose of the patch is to give user space visibility into
> > >> bpf prog load/unload as a notification, then I completely agree that
> > >> some notification mechanism is necessary.
> >
> > Yeah, I did only regard it as only that, nothing more. Some means
> > of timeline and notification that can be kept in a record in user
> > space and later retrieved e.g. for introspection on what has been
> > loaded.
> >
> > >> I've started working on such mechanism via perf ring buffer which is
> > >> the fastest mechanism we have in the kernel so far.
> > >> See long discussion here: https://patchwork.ozlabs.org/patch/971970/
> >
> > That one is definitely needed in any case to resolve the kallsyms
> > limitations, and it does have overlap in that in either case we
> > want to look at past BPF programs that have been unloaded in the
> > meantime, so I don't have a strong preference either way, and the
> > former is needed in any case. Though thought was that audit might
> > be an option for those not running profiling daemons 24/7, but
> > presumably bpftool could be extended to record these events as
> > well if we don't want to reuse audit infra.
>
> Yes, exactly, I don't want to run a profiling daemon 24/7 to record
> these events. I do acknowledge that this perf event is relevant,
> especially for catching the kernel symbols (I need that myself), but it
> does not cover my use-case.
>
> My use-case is to 24/7 collect and keep records in userspace, and have a
> timeline of these notifications, for later retrieval. The idea is that
> our support engineers can look at these records when troubleshooting
> the system. And the plan is also to collect these records as part of
> our sosreport tool, which is part of the support case.
I don't think you're implying that prog load/unload should be spamming dmesg
and auditd not even running...
Also auditd has to be changed to support retrieving prog related info (like license)
via sys_bpf system call when it sees prog_id.
Since it has to change it can just as easily use perf ring buffer
to receive notifications.
So we solve notification problem once and all user space tools can use it.
^ permalink raw reply
* Re: [PATCH RFC,net-next 0/3] ip_tunnel: specify tunnel type via template
From: Pablo Neira Ayuso @ 2018-10-04 21:58 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: netdev, netfilter-devel, roopa, amir, pshelar, u9012063
In-Reply-To: <20181004121357.3efa7275@cakuba.netronome.com>
Hi Jakub,
On Thu, Oct 04, 2018 at 12:13:57PM -0700, Jakub Kicinski wrote:
> On Thu, 4 Oct 2018 02:03:42 +0200, Pablo Neira Ayuso wrote:
> > Hi,
> >
> > The following patchset adds a new field to the tunnel metadata template
> > to restrict the configuration to a given tunnel driver. Currently, a
> > misconfiguration may result in packets going to the wrong tunnel driver.
> >
> > Although we have the tunnel option flags, they are not mandatory for
> > some tunnel drivers, eg. vxlan, which may use it or not; and gre which
> > does not use them.
>
> Option flags are necessary because interpretation of option blob is
> entirely protocol-specific.
>
> > This patch updates tc's tunnel action and netfilter's tunnel extension
> > to use this new field. OVS netlink interface has been left unset, although they
> > could be updated to use this.
> >
> > By extending the existing tc action to support the IP_TUNNEL_INFO_BRIDGE
> > mode, I think it should be possible to expose IP_TUNNEL_TYPE_VLAN too,
> > although this patchset doesn't address this scenario.
> >
> > The field is initialized to zero, which maps to IP_TUNNEL_TYPE_UNSPEC to
> > retain the existing behaviour, so the existing flexibility is still in
> > place while this new feature is added.
> >
> > Cc'ing people that git annotate show as dealing with these bits more
> > recently.
>
> What practical scenario are you trying to address here?
Incorrect configuration. The tunnel template defines an ID field, this
ID means vni in vxlan, but it also means session in erspan. If a
packet that should go to vxlan tunnel device (to be encapsulated using
vni 5) ends up in a gre/erspan device, you will get an erspan packet
with session 5. With this new tunnel type field, you can restrict
the tunnel template to work _only_ for a given tunnel device driver.
Hence, if the packet ends up in the wrong tunnel device driver due to
incorrect configuration, packet gets dropped.
> Have you seen
> https://www.mail-archive.com/netdev@vger.kernel.org/msg250705.html
> ?
Hm, I remember to have seen some hw offload driver code that is making
assumptions on the destination ports to pick the tunnel protocol,
based on what the act_key_tunnel is passing.
This patchset may probably help there too since act_key_tunnel will
convey the tunnel type, given this can now be made explicit. The tc
action parsing from the driver can annotate the tunnel type that has
been set in this rule via act_tunnel_key, then validate that follow up
mirred action points to a tunnel device of the same type.
Thanks.
^ permalink raw reply
* Re: [PATCH net] net: dsa: b53: Keep CPU port as tagged in all VLANs
From: David Miller @ 2018-10-05 4:53 UTC (permalink / raw)
To: f.fainelli; +Cc: netdev, lists, andrew, vivien.didelot, linux-kernel
In-Reply-To: <20181005032413.8866-1-f.fainelli@gmail.com>
From: Florian Fainelli <f.fainelli@gmail.com>
Date: Thu, 4 Oct 2018 20:24:13 -0700
> Commit c499696e7901 ("net: dsa: b53: Stop using dev->cpu_port
> incorrectly") was a bit too trigger happy in removing the CPU port from
> the VLAN membership because we rely on DSA to program the CPU port VLAN,
> which it does, except it does not bother itself with tagged/untagged and
> just usese untagged.
>
> Having the CPU port "follow" the user ports tagged/untagged is not great
> and does not allow for properly differentiating, so keep the CPU port
> tagged in all VLANs.
>
> Reported-by: Gerhard Wiesinger <lists@wiesinger.com>
> Fixes: c499696e7901 ("net: dsa: b53: Stop using dev->cpu_port incorrectly")
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH bpf-next 1/6] bpf: introduce BPF_PROG_TYPE_FILE_FILTER
From: Al Viro @ 2018-10-05 4:46 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David S . Miller, daniel, luto, netdev, linux-kernel, kernel-team
In-Reply-To: <20181004025750.498303-2-ast@kernel.org>
On Wed, Oct 03, 2018 at 07:57:45PM -0700, Alexei Starovoitov wrote:
> @@ -15,6 +15,7 @@
> #include <linux/bpf.h>
> #include <linux/bpf-cgroup.h>
> #include <net/sock.h>
> +#include <../fs/mount.h>
No.
> + struct file *file = NULL;
> + struct inode *inode;
> + struct super_block *sb;
> + struct mount *mnt;
Fuck, no.
> + case offsetof(struct bpf_file_info, mnt_id):
> + /* dst = real_mount(file->f_path.mnt)->mnt_id */
> + mnt = real_mount(LD_1(file->f_path.mnt));
> + LD_n(mnt->mnt_id);
NAK. Anything in struct mount is private to just a couple of
files in fs/*.c. Don't do that. And keep in mind that internal
details can and will be changed at zero notice, so be careful
with adding such stuff.
Another problem is your direct poking in ->i_ino. It's not
something directly exposed to userland at the moment and it should
not become such. Filesystem has every right to have ->getattr()
set ->ino (== ->st_ino value) in whichever way it likes; the same
goes for ->dev.
^ permalink raw reply
* Your images 22
From: Joanna @ 2018-10-04 14:53 UTC (permalink / raw)
To: netdev
Have photos for cutting out or retouching?
We are one image team and we do editing for your the e-commerce photos,
industry photos or portrait photo.
If you need test editing then let me know.
Waiting for your reply and the photo work.
Thanks,
Joanna
^ 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