Netdev List
 help / color / mirror / Atom feed
* 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

* Re: [PATCH net-next 0/7] mlxsw: Various updates
From: David Miller @ 2018-08-09 17:37 UTC (permalink / raw)
  To: idosch; +Cc: netdev, jiri, mlxsw
In-Reply-To: <20180809085913.20671-1-idosch@mellanox.com>

From: Ido Schimmel <idosch@mellanox.com>
Date: Thu,  9 Aug 2018 11:59:06 +0300

> Patches 1-3 update the driver to use a new firmware version. Due to a
> recently discovered issue, the version (and future ones) does not
> support matching on VLAN ID at egress. This is enforced in the driver
> and reported back to the user via extack.
> 
> Patch 4 adds a new selftest for the recently introduced algorithmic
> TCAM.
> 
> Patch 5 converts the driver to use SPDX identifiers.
> 
> Patches 6-7 fix a bug in ethtool stats reporting and expose counters for
> all 16 TCs, following recent MC-aware changes that utilize TCs 8-15.

Series applied, thanks!

^ permalink raw reply

* Re: [PATCH 1/3] net:svc_rdma_transport: remove unneeded variable 'ret' in rdma_listen_handler
From: J. Bruce Fields @ 2018-08-09 20:06 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: zhong jiang, davem, netdev, linux-kernel
In-Reply-To: <2c343d78-e668-1b97-a4e6-228296da0d70@Netapp.com>

On Tue, Aug 07, 2018 at 10:49:11AM -0400, Anna Schumaker wrote:
> (Adding Bruce since he takes nfs / sunrpc server patches)

Applied, thanks.--b.

> 
> On 08/07/2018 07:20 AM, zhong jiang wrote:
> > The ret is not modified after initalization, So just remove the variable
> > and return 0.
> > 
> > Signed-off-by: zhong jiang <zhongjiang@huawei.com>
> > ---
> >  net/sunrpc/xprtrdma/svc_rdma_transport.c | 3 +--
> >  1 file changed, 1 insertion(+), 2 deletions(-)
> > 
> > diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
> > index 547b2cd..2848caf 100644
> > --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
> > +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
> > @@ -296,7 +296,6 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
> >  			       struct rdma_cm_event *event)
> >  {
> >  	struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.src_addr;
> > -	int ret = 0;
> >  
> >  	trace_svcrdma_cm_event(event, sap);
> >  
> > @@ -315,7 +314,7 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
> >  		break;
> >  	}
> >  
> > -	return ret;
> > +	return 0;
> >  }
> >  
> >  static int rdma_cma_handler(struct rdma_cm_id *cma_id,
> > 

^ permalink raw reply

* Re: [PATCH bpf] bpf: fix bpffs non-array map seq_show issue
From: Yonghong Song @ 2018-08-09 17:54 UTC (permalink / raw)
  To: Daniel Borkmann, Alexei Starovoitov
  Cc: ast, netdev, kernel-team, jakub.kicinski
In-Reply-To: <2adc84c4-2e92-db75-ba27-7e23eb9c95ad@iogearbox.net>



On 8/9/18 10:02 AM, Daniel Borkmann wrote:
> 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.

Sounds good. i will wait until this gets merged and then resubmit.

> 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

* [PATCH ethtool v2 0/3] ethtool: Wake-on-LAN using filters
From: Florian Fainelli @ 2018-08-09 18:03 UTC (permalink / raw)
  To: netdev, linville; +Cc: davem, andrew, Florian Fainelli

Hi John,

This patch series syncs up ethtool-copy.h to get the new definitions
required for supporting wake-on-LAN using filters: WAKE_FILTER and
RX_CLS_FLOW_WAKE and then updates the rxclass.c code to allow us to
specify action -2 (RX_CLS_FLOW_WAKE).

Let me know if you would like this to be done differently.

Thanks!

Changes in v2:

- properly put the man page hunk describing action -2 into patch #3

Florian Fainelli (3):
  ethtool-copy.h: sync with net-next
  ethtool: Add support for WAKE_FILTER (WoL using filters)
  ethtool: Add support for action value -2 (wake-up filter)

 ethtool-copy.h | 15 +++++++++++----
 ethtool.8.in   |  4 +++-
 ethtool.c      |  5 +++++
 rxclass.c      |  8 +++++---
 4 files changed, 24 insertions(+), 8 deletions(-)

-- 
2.17.1

^ permalink raw reply

* [PATCH ethtool v2 1/3] ethtool-copy.h: sync with net-next
From: Florian Fainelli @ 2018-08-09 18:04 UTC (permalink / raw)
  To: netdev, linville; +Cc: davem, andrew, Florian Fainelli
In-Reply-To: <20180809180402.19430-1-f.fainelli@gmail.com>

This covers kernel changes up to commit 6cfef793b558:
   ethtool: Add WAKE_FILTER and RX_CLS_FLOW_WAKE

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 ethtool-copy.h | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index 8cc61e9ab40b..6bfbb85f9402 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -215,12 +215,16 @@ struct ethtool_value {
 	__u32	data;
 };
 
+#define PFC_STORM_PREVENTION_AUTO	0xffff
+#define PFC_STORM_PREVENTION_DISABLE	0
+
 enum tunable_id {
 	ETHTOOL_ID_UNSPEC,
 	ETHTOOL_RX_COPYBREAK,
 	ETHTOOL_TX_COPYBREAK,
+	ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */
 	/*
-	 * Add your fresh new tubale attribute above and remember to update
+	 * Add your fresh new tunable attribute above and remember to update
 	 * tunable_strings[] in net/core/ethtool.c
 	 */
 	__ETHTOOL_TUNABLE_COUNT,
@@ -864,7 +868,8 @@ struct ethtool_flow_ext {
  *	includes the %FLOW_EXT or %FLOW_MAC_EXT flag
  *	(see &struct ethtool_flow_ext description).
  * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
- *	if packets should be discarded
+ *	if packets should be discarded, or %RX_CLS_FLOW_WAKE if the
+ *	packets should be used for Wake-on-LAN with %WAKE_FILTER
  * @location: Location of rule in the table.  Locations must be
  *	numbered such that a flow matching multiple rules will be
  *	classified according to the first (lowest numbered) rule.
@@ -896,13 +901,13 @@ struct ethtool_rx_flow_spec {
 static __inline__ __u64 ethtool_get_flow_spec_ring(__u64 ring_cookie)
 {
 	return ETHTOOL_RX_FLOW_SPEC_RING & ring_cookie;
-};
+}
 
 static __inline__ __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie)
 {
 	return (ETHTOOL_RX_FLOW_SPEC_RING_VF & ring_cookie) >>
 				ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
-};
+}
 
 /**
  * struct ethtool_rxnfc - command to get or set RX flow classification rules
@@ -1628,6 +1633,7 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex)
 #define WAKE_ARP		(1 << 4)
 #define WAKE_MAGIC		(1 << 5)
 #define WAKE_MAGICSECURE	(1 << 6) /* only meaningful if WAKE_MAGIC */
+#define WAKE_FILTER		(1 << 7)
 
 /* L2-L4 network traffic flow types */
 #define	TCP_V4_FLOW	0x01	/* hash or spec (tcp_ip4_spec) */
@@ -1665,6 +1671,7 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex)
 #define	RXH_DISCARD	(1 << 31)
 
 #define	RX_CLS_FLOW_DISC	0xffffffffffffffffULL
+#define RX_CLS_FLOW_WAKE	0xfffffffffffffffeULL
 
 /* Special RX classification rule insert location values */
 #define RX_CLS_LOC_SPECIAL	0x80000000	/* flag */
-- 
2.17.1

^ permalink raw reply related

* [PATCH ethtool v2 2/3] ethtool: Add support for WAKE_FILTER (WoL using filters)
From: Florian Fainelli @ 2018-08-09 18:04 UTC (permalink / raw)
  To: netdev, linville; +Cc: davem, andrew, Florian Fainelli
In-Reply-To: <20180809180402.19430-1-f.fainelli@gmail.com>

Add a new character 'f' which can be used to configure an Ethernet
controller to support Wake-on-LAN using filters programmed with the
ethtool::rxnfc and the special action -2 (wake-up filter). This is
useful in particular in the context of devices that must support wake-up
on more complex patterns such as multicast DNS packets.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 ethtool.8.in | 3 ++-
 ethtool.c    | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/ethtool.8.in b/ethtool.8.in
index 0a366aa536ae..3eb9005ada48 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -58,7 +58,7 @@
 .\"
 .\"	\(*WO - wol flags
 .\"
-.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBd\fP...
+.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBf|\fBd\fP...
 .\"
 .\"	\(*FL - flow type values
 .\"
@@ -679,6 +679,7 @@ b	Wake on broadcast messages
 a	Wake on ARP
 g	Wake on MagicPacket\[tm]
 s	Enable SecureOn\[tm] password for MagicPacket\[tm]
+f	Wake on filter(s)
 d	T{
 Disable (wake on nothing).  This option clears all previous options.
 T}
diff --git a/ethtool.c b/ethtool.c
index fb93ae898312..aa2bbe9e4c65 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -931,6 +931,9 @@ static int parse_wolopts(char *optstr, u32 *data)
 		case 's':
 			*data |= WAKE_MAGICSECURE;
 			break;
+		case 'f':
+			*data |= WAKE_FILTER;
+			break;
 		case 'd':
 			*data = 0;
 			break;
@@ -964,6 +967,8 @@ static char *unparse_wolopts(int wolopts)
 			*p++ = 'g';
 		if (wolopts & WAKE_MAGICSECURE)
 			*p++ = 's';
+		if (wolopts & WAKE_FILTER)
+			*p++ = 'f';
 	} else {
 		*p = 'd';
 	}
-- 
2.17.1

^ permalink raw reply related

* [PATCH ethtool v2 3/3] ethtool: Add support for action value -2 (wake-up filter)
From: Florian Fainelli @ 2018-08-09 18:04 UTC (permalink / raw)
  To: netdev, linville; +Cc: davem, andrew, Florian Fainelli
In-Reply-To: <20180809180402.19430-1-f.fainelli@gmail.com>

Add the ability to program special filters using ethtool::rxnfc which
are meant to be used for wake-up purposes (in conjuction with
WAKE_FILTER) using the special action value: -2 (RX_CLS_FLOW_WAKE).

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 ethtool.8.in | 1 +
 rxclass.c    | 8 +++++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/ethtool.8.in b/ethtool.8.in
index 3eb9005ada48..97c7330fd373 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -871,6 +871,7 @@ Specifies the Rx queue to send packets to, or some other action.
 nokeep;
 lB	l.
 -1	Drop the matched flow
+-2	Use the matched flow as a Wake-on-LAN filter
 0 or higher	Rx queue to route the flow
 .TE
 .TP
diff --git a/rxclass.c b/rxclass.c
index 42d122d1ed86..79972651e706 100644
--- a/rxclass.c
+++ b/rxclass.c
@@ -251,7 +251,11 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp,
 	if (fsp->flow_type & FLOW_RSS)
 		fprintf(stdout, "\tRSS Context ID: %u\n", rss_context);
 
-	if (fsp->ring_cookie != RX_CLS_FLOW_DISC) {
+	if (fsp->ring_cookie == RX_CLS_FLOW_DISC) {
+		fprintf(stdout, "\tAction: Drop\n");
+	} else if (fsp->ring_cookie == RX_CLS_FLOW_WAKE) {
+		fprintf(stdout, "\tAction: Wake-on-LAN\n");
+	} else {
 		u64 vf = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
 		u64 queue = ethtool_get_flow_spec_ring(fsp->ring_cookie);
 
@@ -266,8 +270,6 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp,
 		else
 			fprintf(stdout, "\tAction: Direct to queue %llu\n",
 				queue);
-	} else {
-		fprintf(stdout, "\tAction: Drop\n");
 	}
 
 	fprintf(stdout, "\n");
-- 
2.17.1

^ permalink raw reply related

* Re: [PATCH net-next 00/13] More complete PHYLINK support for mv88e6xxx
From: David Miller @ 2018-08-09 18:08 UTC (permalink / raw)
  To: andrew; +Cc: netdev, rmk+kernel, f.fainelli, nikita.yoush, cphealy,
	marek.behun
In-Reply-To: <1533821929-20071-1-git-send-email-andrew@lunn.ch>

From: Andrew Lunn <andrew@lunn.ch>
Date: Thu,  9 Aug 2018 15:38:36 +0200

> Previous patches added sufficient PHYLINK support to the mv88e6xxx
> that it did not break existing use cases, basically fixed-link phys.
> 
> This patchset builds out the support so that SFP modules, up to
> 2.5Gbps can be supported, on mv88e6390X, on ports 9 and 10. It also
> provides a framework which can be extended to support SFPs on ports
> 2-8 of mv88e6390X, 10Gbps PHYs, and SFP support on the 6352 family.
> 
> Russell King did much of the initial work, implementing the validate
> and mac_link_state calls. However, there is an important TODO in the
> commit message:
> 
> needs to call phylink_mac_change() when the port link comes up/goes down.
> 
> The remaining patches implement this, by adding more support for the
> SERDES interfaces, in particular, interrupt support so we get notified
> when the SERDES gains/looses sync.
> 
> This has been tested on the ZII devel C, using a Clearfog as peer
> device.

Looks good to me, series applied, thanks!

^ permalink raw reply

* [PATCH net-next 0/3] qed*: Enhancements
From: Manish Chopra @ 2018-08-09 18:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, ariel.elior, michal.kalderon

Hi David,

This patch series adds following support in drivers -

1. Egress mqprio offload.
2. Add destination IP based flow profile.
3. Ingress flower offload (for drop action).

Please consider applying this series to "net-next".

Thanks,
Manish

Manish Chopra (3):
  qed/qede: Multi CoS support.
  qede: Add destination ip based flow profile.
  qede: Ingress tc flower offload (drop action) support.

 drivers/net/ethernet/qlogic/qed/qed_l2.c        |   9 +-
 drivers/net/ethernet/qlogic/qed/qed_main.c      |   5 +-
 drivers/net/ethernet/qlogic/qede/qede.h         |  20 +-
 drivers/net/ethernet/qlogic/qede/qede_ethtool.c |  50 ++-
 drivers/net/ethernet/qlogic/qede/qede_filter.c  | 422 ++++++++++++++++++++----
 drivers/net/ethernet/qlogic/qede/qede_fp.c      |  29 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c    | 195 +++++++++--
 include/linux/qed/qed_eth_if.h                  |   6 +
 8 files changed, 628 insertions(+), 108 deletions(-)

-- 
1.8.3.1

^ permalink raw reply

* [PATCH net-next 1/3] qed/qede: Multi CoS support.
From: Manish Chopra @ 2018-08-09 18:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, ariel.elior, michal.kalderon
In-Reply-To: <20180809181351.32394-1-manish.chopra@cavium.com>

This patch adds support for tc mqprio offload,
using this different traffic classes on the adapter
can be utilized based on configured priority to tc map.

For example -

tc qdisc add dev eth0 root mqprio num_tc 4 map 0 1 2 3

This will cause SKBs with priority 0,1,2,3 to transmit
over tc 0,1,2,3 hardware queues respectively.

Signed-off-by: Manish Chopra <manish.chopra@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed_l2.c        |   9 +-
 drivers/net/ethernet/qlogic/qed/qed_main.c      |   5 +-
 drivers/net/ethernet/qlogic/qede/qede.h         |  13 +++
 drivers/net/ethernet/qlogic/qede/qede_ethtool.c |  48 ++++++--
 drivers/net/ethernet/qlogic/qede/qede_fp.c      |  29 +++--
 drivers/net/ethernet/qlogic/qede/qede_main.c    | 139 +++++++++++++++++++-----
 include/linux/qed/qed_eth_if.h                  |   6 +
 7 files changed, 200 insertions(+), 49 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 5ede640..82a1bd1 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -2188,16 +2188,17 @@ int qed_get_queue_coalesce(struct qed_hwfn *p_hwfn, u16 *p_coal, void *handle)
 static int qed_fill_eth_dev_info(struct qed_dev *cdev,
 				 struct qed_dev_eth_info *info)
 {
+	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
 	int i;
 
 	memset(info, 0, sizeof(*info));
 
-	info->num_tc = 1;
-
 	if (IS_PF(cdev)) {
 		int max_vf_vlan_filters = 0;
 		int max_vf_mac_filters = 0;
 
+		info->num_tc = p_hwfn->hw_info.num_hw_tc;
+
 		if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
 			u16 num_queues = 0;
 
@@ -2248,6 +2249,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
 	} else {
 		u16 total_cids = 0;
 
+		info->num_tc = 1;
+
 		/* Determine queues &  XDP support */
 		for_each_hwfn(cdev, i) {
 			struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
@@ -2554,7 +2557,7 @@ static int qed_start_txq(struct qed_dev *cdev,
 
 	rc = qed_eth_tx_queue_start(p_hwfn,
 				    p_hwfn->hw_info.opaque_fid,
-				    p_params, 0,
+				    p_params, p_params->tc,
 				    pbl_addr, pbl_size, ret_params);
 
 	if (rc) {
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index dbe8131..2094d86 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -948,13 +948,14 @@ static void qed_update_pf_params(struct qed_dev *cdev,
 		params->eth_pf_params.num_arfs_filters = 0;
 
 	/* In case we might support RDMA, don't allow qede to be greedy
-	 * with the L2 contexts. Allow for 64 queues [rx, tx, xdp] per hwfn.
+	 * with the L2 contexts. Allow for 64 queues [rx, tx cos, xdp]
+	 * per hwfn.
 	 */
 	if (QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) {
 		u16 *num_cons;
 
 		num_cons = &params->eth_pf_params.num_cons;
-		*num_cons = min_t(u16, *num_cons, 192);
+		*num_cons = min_t(u16, *num_cons, QED_MAX_L2_CONS);
 	}
 
 	for (i = 0; i < cdev->num_hwfns; i++) {
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index d7ed0d3..e90c60a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -386,6 +386,15 @@ struct qede_tx_queue {
 #define QEDE_TXQ_XDP_TO_IDX(edev, txq)	((txq)->index - \
 					 QEDE_MAX_TSS_CNT(edev))
 #define QEDE_TXQ_IDX_TO_XDP(edev, idx)	((idx) + QEDE_MAX_TSS_CNT(edev))
+#define QEDE_NDEV_TXQ_ID_TO_FP_ID(edev, idx)	((edev)->fp_num_rx + \
+						 ((idx) % QEDE_TSS_COUNT(edev)))
+#define QEDE_NDEV_TXQ_ID_TO_TXQ_COS(edev, idx)	((idx) / QEDE_TSS_COUNT(edev))
+#define QEDE_TXQ_TO_NDEV_TXQ_ID(edev, txq)	((QEDE_TSS_COUNT(edev) * \
+						 (txq)->cos) + (txq)->index)
+#define QEDE_NDEV_TXQ_ID_TO_TXQ(edev, idx)	\
+	(&((edev)->fp_array[QEDE_NDEV_TXQ_ID_TO_FP_ID(edev, idx)].txq \
+	[QEDE_NDEV_TXQ_ID_TO_TXQ_COS(edev, idx)]))
+#define QEDE_FP_TC0_TXQ(fp)	(&((fp)->txq[0]))
 
 	/* Regular Tx requires skb + metadata for release purpose,
 	 * while XDP requires the pages and the mapped address.
@@ -399,6 +408,8 @@ struct qede_tx_queue {
 
 	/* Slowpath; Should be kept in end [unless missing padding] */
 	void *handle;
+	u16 cos;
+	u16 ndev_txq_id;
 };
 
 #define BD_UNMAP_ADDR(bd)		HILO_U64(le32_to_cpu((bd)->addr.hi), \
@@ -541,5 +552,7 @@ void qede_reload(struct qede_dev *edev,
 #define QEDE_RX_HDR_SIZE		256
 #define QEDE_MAX_JUMBO_PACKET_SIZE	9600
 #define	for_each_queue(i) for (i = 0; i < edev->num_queues; i++)
+#define for_each_cos_in_txq(edev, var) \
+	for ((var) = 0; (var) < (edev)->dev_info.num_tc; (var)++)
 
 #endif /* _QEDE_H_ */
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index b37857f..2bd84d6 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -222,7 +222,7 @@ static void qede_get_strings_stats_txq(struct qede_dev *edev,
 				QEDE_TXQ_XDP_TO_IDX(edev, txq),
 				qede_tqstats_arr[i].string);
 		else
-			sprintf(*buf, "%d: %s", txq->index,
+			sprintf(*buf, "%d_%d: %s", txq->index, txq->cos,
 				qede_tqstats_arr[i].string);
 		*buf += ETH_GSTRING_LEN;
 	}
@@ -262,8 +262,13 @@ static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
 		if (fp->type & QEDE_FASTPATH_XDP)
 			qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf);
 
-		if (fp->type & QEDE_FASTPATH_TX)
-			qede_get_strings_stats_txq(edev, fp->txq, &buf);
+		if (fp->type & QEDE_FASTPATH_TX) {
+			int cos;
+
+			for_each_cos_in_txq(edev, cos)
+				qede_get_strings_stats_txq(edev,
+							   &fp->txq[cos], &buf);
+		}
 	}
 
 	/* Account for non-queue statistics */
@@ -338,8 +343,12 @@ static void qede_get_ethtool_stats(struct net_device *dev,
 		if (fp->type & QEDE_FASTPATH_XDP)
 			qede_get_ethtool_stats_txq(fp->xdp_tx, &buf);
 
-		if (fp->type & QEDE_FASTPATH_TX)
-			qede_get_ethtool_stats_txq(fp->txq, &buf);
+		if (fp->type & QEDE_FASTPATH_TX) {
+			int cos;
+
+			for_each_cos_in_txq(edev, cos)
+				qede_get_ethtool_stats_txq(&fp->txq[cos], &buf);
+		}
 	}
 
 	for (i = 0; i < QEDE_NUM_STATS; i++) {
@@ -366,7 +375,8 @@ static int qede_get_sset_count(struct net_device *dev, int stringset)
 				num_stats--;
 
 		/* Account for the Regular Tx statistics */
-		num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS;
+		num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS *
+				edev->dev_info.num_tc;
 
 		/* Account for the Regular Rx statistics */
 		num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS;
@@ -741,9 +751,17 @@ static int qede_get_coalesce(struct net_device *dev,
 		}
 
 		for_each_queue(i) {
+			struct qede_tx_queue *txq;
+
 			fp = &edev->fp_array[i];
+
+			/* All TX queues of given fastpath uses same
+			 * coalescing value, so no need to iterate over
+			 * all TCs, TC0 txq should suffice.
+			 */
 			if (fp->type & QEDE_FASTPATH_TX) {
-				tx_handle = fp->txq->handle;
+				txq = QEDE_FP_TC0_TXQ(fp);
+				tx_handle = txq->handle;
 				break;
 			}
 		}
@@ -801,9 +819,17 @@ static int qede_set_coalesce(struct net_device *dev,
 		}
 
 		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
+			struct qede_tx_queue *txq;
+
+			/* All TX queues of given fastpath uses same
+			 * coalescing value, so no need to iterate over
+			 * all TCs, TC0 txq should suffice.
+			 */
+			txq = QEDE_FP_TC0_TXQ(fp);
+
 			rc = edev->ops->common->set_coalesce(edev->cdev,
 							     0, txc,
-							     fp->txq->handle);
+							     txq->handle);
 			if (rc) {
 				DP_INFO(edev,
 					"Set TX coalesce error, rc = %d\n", rc);
@@ -1385,8 +1411,10 @@ static int qede_selftest_transmit_traffic(struct qede_dev *edev,
 	u16 val;
 
 	for_each_queue(i) {
-		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
-			txq = edev->fp_array[i].txq;
+		struct qede_fastpath *fp = &edev->fp_array[i];
+
+		if (fp->type & QEDE_FASTPATH_TX) {
+			txq = QEDE_FP_TC0_TXQ(fp);
 			break;
 		}
 	}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index 8c9e95b..1a78027 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -408,12 +408,12 @@ static void qede_xdp_tx_int(struct qede_dev *edev, struct qede_tx_queue *txq)
 
 static int qede_tx_int(struct qede_dev *edev, struct qede_tx_queue *txq)
 {
+	unsigned int pkts_compl = 0, bytes_compl = 0;
 	struct netdev_queue *netdev_txq;
 	u16 hw_bd_cons;
-	unsigned int pkts_compl = 0, bytes_compl = 0;
 	int rc;
 
-	netdev_txq = netdev_get_tx_queue(edev->ndev, txq->index);
+	netdev_txq = netdev_get_tx_queue(edev->ndev, txq->ndev_txq_id);
 
 	hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr);
 	barrier();
@@ -1365,9 +1365,14 @@ static bool qede_poll_is_more_work(struct qede_fastpath *fp)
 		if (qede_txq_has_work(fp->xdp_tx))
 			return true;
 
-	if (likely(fp->type & QEDE_FASTPATH_TX))
-		if (qede_txq_has_work(fp->txq))
-			return true;
+	if (likely(fp->type & QEDE_FASTPATH_TX)) {
+		int cos;
+
+		for_each_cos_in_txq(fp->edev, cos) {
+			if (qede_txq_has_work(&fp->txq[cos]))
+				return true;
+		}
+	}
 
 	return false;
 }
@@ -1382,8 +1387,14 @@ int qede_poll(struct napi_struct *napi, int budget)
 	struct qede_dev *edev = fp->edev;
 	int rx_work_done = 0;
 
-	if (likely(fp->type & QEDE_FASTPATH_TX) && qede_txq_has_work(fp->txq))
-		qede_tx_int(edev, fp->txq);
+	if (likely(fp->type & QEDE_FASTPATH_TX)) {
+		int cos;
+
+		for_each_cos_in_txq(fp->edev, cos) {
+			if (qede_txq_has_work(&fp->txq[cos]))
+				qede_tx_int(edev, &fp->txq[cos]);
+		}
+	}
 
 	if ((fp->type & QEDE_FASTPATH_XDP) && qede_txq_has_work(fp->xdp_tx))
 		qede_xdp_tx_int(edev, fp->xdp_tx);
@@ -1444,8 +1455,8 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 	/* Get tx-queue context and netdev index */
 	txq_index = skb_get_queue_mapping(skb);
-	WARN_ON(txq_index >= QEDE_TSS_COUNT(edev));
-	txq = edev->fp_array[edev->fp_num_rx + txq_index].txq;
+	WARN_ON(txq_index >= QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc);
+	txq = QEDE_NDEV_TXQ_ID_TO_TXQ(edev, txq_index);
 	netdev_txq = netdev_get_tx_queue(ndev, txq_index);
 
 	WARN_ON(qed_chain_get_elem_left(&txq->tx_pbl) < (MAX_SKB_FRAGS + 1));
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 6a79604..d7299af 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -536,6 +536,43 @@ static int qede_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return 0;
 }
 
+int qede_setup_tc(struct net_device *ndev, u8 num_tc)
+{
+	struct qede_dev *edev = netdev_priv(ndev);
+	int cos, count, offset;
+
+	if (num_tc > edev->dev_info.num_tc)
+		return -EINVAL;
+
+	netdev_reset_tc(ndev);
+	netdev_set_num_tc(ndev, num_tc);
+
+	for_each_cos_in_txq(edev, cos) {
+		count = QEDE_TSS_COUNT(edev);
+		offset = cos * QEDE_TSS_COUNT(edev);
+		netdev_set_tc_queue(ndev, cos, count, offset);
+	}
+
+	return 0;
+}
+
+static int
+qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
+		      void *type_data)
+{
+	struct tc_mqprio_qopt *mqprio;
+
+	switch (type) {
+	case TC_SETUP_QDISC_MQPRIO:
+		mqprio = type_data;
+
+		mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
+		return qede_setup_tc(dev, mqprio->num_tc);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const struct net_device_ops qede_netdev_ops = {
 	.ndo_open = qede_open,
 	.ndo_stop = qede_close,
@@ -568,6 +605,7 @@ static int qede_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 #ifdef CONFIG_RFS_ACCEL
 	.ndo_rx_flow_steer = qede_rx_flow_steer,
 #endif
+	.ndo_setup_tc = qede_setup_tc_offload,
 };
 
 static const struct net_device_ops qede_netdev_vf_ops = {
@@ -621,7 +659,8 @@ static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev,
 	struct qede_dev *edev;
 
 	ndev = alloc_etherdev_mqs(sizeof(*edev),
-				  info->num_queues, info->num_queues);
+				  info->num_queues * info->num_tc,
+				  info->num_queues);
 	if (!ndev) {
 		pr_err("etherdev allocation failed\n");
 		return NULL;
@@ -830,7 +869,8 @@ static int qede_alloc_fp_array(struct qede_dev *edev)
 		}
 
 		if (fp->type & QEDE_FASTPATH_TX) {
-			fp->txq = kzalloc(sizeof(*fp->txq), GFP_KERNEL);
+			fp->txq = kcalloc(edev->dev_info.num_tc,
+					  sizeof(*fp->txq), GFP_KERNEL);
 			if (!fp->txq)
 				goto err;
 		}
@@ -879,10 +919,15 @@ static void qede_sp_task(struct work_struct *work)
 static void qede_update_pf_params(struct qed_dev *cdev)
 {
 	struct qed_pf_params pf_params;
+	u16 num_cons;
 
 	/* 64 rx + 64 tx + 64 XDP */
 	memset(&pf_params, 0, sizeof(struct qed_pf_params));
-	pf_params.eth_pf_params.num_cons = (MAX_SB_PER_PF_MIMD - 1) * 3;
+
+	/* 1 rx + 1 xdp + max tx cos */
+	num_cons = QED_MIN_L2_CONS;
+
+	pf_params.eth_pf_params.num_cons = (MAX_SB_PER_PF_MIMD - 1) * num_cons;
 
 	/* Same for VFs - make sure they'll have sufficient connections
 	 * to support XDP Tx queues.
@@ -1363,8 +1408,12 @@ static void qede_free_mem_fp(struct qede_dev *edev, struct qede_fastpath *fp)
 	if (fp->type & QEDE_FASTPATH_XDP)
 		qede_free_mem_txq(edev, fp->xdp_tx);
 
-	if (fp->type & QEDE_FASTPATH_TX)
-		qede_free_mem_txq(edev, fp->txq);
+	if (fp->type & QEDE_FASTPATH_TX) {
+		int cos;
+
+		for_each_cos_in_txq(edev, cos)
+			qede_free_mem_txq(edev, &fp->txq[cos]);
+	}
 }
 
 /* This function allocates all memory needed for a single fp (i.e. an entity
@@ -1391,9 +1440,13 @@ static int qede_alloc_mem_fp(struct qede_dev *edev, struct qede_fastpath *fp)
 	}
 
 	if (fp->type & QEDE_FASTPATH_TX) {
-		rc = qede_alloc_mem_txq(edev, fp->txq);
-		if (rc)
-			goto out;
+		int cos;
+
+		for_each_cos_in_txq(edev, cos) {
+			rc = qede_alloc_mem_txq(edev, &fp->txq[cos]);
+			if (rc)
+				goto out;
+		}
 	}
 
 out:
@@ -1466,10 +1519,23 @@ static void qede_init_fp(struct qede_dev *edev)
 		}
 
 		if (fp->type & QEDE_FASTPATH_TX) {
-			fp->txq->index = txq_index++;
-			if (edev->dev_info.is_legacy)
-				fp->txq->is_legacy = 1;
-			fp->txq->dev = &edev->pdev->dev;
+			int cos;
+
+			for_each_cos_in_txq(edev, cos) {
+				struct qede_tx_queue *txq = &fp->txq[cos];
+				u16 ndev_tx_id;
+
+				txq->cos = cos;
+				txq->index = txq_index;
+				ndev_tx_id = QEDE_TXQ_TO_NDEV_TXQ_ID(edev, txq);
+				txq->ndev_txq_id = ndev_tx_id;
+
+				if (edev->dev_info.is_legacy)
+					txq->is_legacy = 1;
+				txq->dev = &edev->pdev->dev;
+			}
+
+			txq_index++;
 		}
 
 		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
@@ -1483,7 +1549,9 @@ static int qede_set_real_num_queues(struct qede_dev *edev)
 {
 	int rc = 0;
 
-	rc = netif_set_real_num_tx_queues(edev->ndev, QEDE_TSS_COUNT(edev));
+	rc = netif_set_real_num_tx_queues(edev->ndev,
+					  QEDE_TSS_COUNT(edev) *
+					  edev->dev_info.num_tc);
 	if (rc) {
 		DP_NOTICE(edev, "Failed to set real number of Tx queues\n");
 		return rc;
@@ -1685,9 +1753,13 @@ static int qede_stop_queues(struct qede_dev *edev)
 		fp = &edev->fp_array[i];
 
 		if (fp->type & QEDE_FASTPATH_TX) {
-			rc = qede_drain_txq(edev, fp->txq, true);
-			if (rc)
-				return rc;
+			int cos;
+
+			for_each_cos_in_txq(edev, cos) {
+				rc = qede_drain_txq(edev, &fp->txq[cos], true);
+				if (rc)
+					return rc;
+			}
 		}
 
 		if (fp->type & QEDE_FASTPATH_XDP) {
@@ -1703,9 +1775,13 @@ static int qede_stop_queues(struct qede_dev *edev)
 
 		/* Stop the Tx Queue(s) */
 		if (fp->type & QEDE_FASTPATH_TX) {
-			rc = qede_stop_txq(edev, fp->txq, i);
-			if (rc)
-				return rc;
+			int cos;
+
+			for_each_cos_in_txq(edev, cos) {
+				rc = qede_stop_txq(edev, &fp->txq[cos], i);
+				if (rc)
+					return rc;
+			}
 		}
 
 		/* Stop the Rx Queue */
@@ -1758,6 +1834,7 @@ static int qede_start_txq(struct qede_dev *edev,
 
 	params.p_sb = fp->sb_info;
 	params.sb_idx = sb_idx;
+	params.tc = txq->cos;
 
 	rc = edev->ops->q_tx_start(edev->cdev, rss_id, &params, phys_table,
 				   page_cnt, &ret_params);
@@ -1877,9 +1954,14 @@ static int qede_start_queues(struct qede_dev *edev, bool clear_stats)
 		}
 
 		if (fp->type & QEDE_FASTPATH_TX) {
-			rc = qede_start_txq(edev, fp, fp->txq, i, TX_PI(0));
-			if (rc)
-				goto out;
+			int cos;
+
+			for_each_cos_in_txq(edev, cos) {
+				rc = qede_start_txq(edev, fp, &fp->txq[cos], i,
+						    TX_PI(cos));
+				if (rc)
+					goto out;
+			}
 		}
 	}
 
@@ -1973,6 +2055,7 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
 		     bool is_locked)
 {
 	struct qed_link_params link_params;
+	u8 num_tc;
 	int rc;
 
 	DP_INFO(edev, "Starting qede load\n");
@@ -2019,6 +2102,10 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
 		goto err4;
 	DP_INFO(edev, "Start VPORT, RXQ and TXQ succeeded\n");
 
+	num_tc = netdev_get_num_tc(edev->ndev);
+	num_tc = num_tc ? num_tc : edev->dev_info.num_tc;
+	qede_setup_tc(edev->ndev, num_tc);
+
 	/* Program un-configured VLANs */
 	qede_configure_vlan_filters(edev);
 
@@ -2143,7 +2230,7 @@ static bool qede_is_txq_full(struct qede_dev *edev, struct qede_tx_queue *txq)
 {
 	struct netdev_queue *netdev_txq;
 
-	netdev_txq = netdev_get_tx_queue(edev->ndev, txq->index);
+	netdev_txq = netdev_get_tx_queue(edev->ndev, txq->ndev_txq_id);
 	if (netif_xmit_stopped(netdev_txq))
 		return true;
 
@@ -2208,9 +2295,11 @@ static void qede_get_eth_tlv_data(void *dev, void *data)
 	for_each_queue(i) {
 		fp = &edev->fp_array[i];
 		if (fp->type & QEDE_FASTPATH_TX) {
-			if (fp->txq->sw_tx_cons != fp->txq->sw_tx_prod)
+			struct qede_tx_queue *txq = QEDE_FP_TC0_TXQ(fp);
+
+			if (txq->sw_tx_cons != txq->sw_tx_prod)
 				etlv->txqs_empty = false;
-			if (qede_is_txq_full(edev, fp->txq))
+			if (qede_is_txq_full(edev, txq))
 				etlv->num_txqs_full++;
 		}
 		if (fp->type & QEDE_FASTPATH_RX) {
diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h
index 2978fa4..a131048 100644
--- a/include/linux/qed/qed_eth_if.h
+++ b/include/linux/qed/qed_eth_if.h
@@ -39,6 +39,10 @@
 #include <linux/qed/qed_if.h>
 #include <linux/qed/qed_iov_if.h>
 
+/* 64 max queues * (1 rx + 4 tx-cos + 1 xdp) */
+#define QED_MIN_L2_CONS (2 + NUM_PHYS_TCS_4PORT_K2)
+#define QED_MAX_L2_CONS (64 * (QED_MIN_L2_CONS))
+
 struct qed_queue_start_common_params {
 	/* Should always be relative to entity sending this. */
 	u8 vport_id;
@@ -49,6 +53,8 @@ struct qed_queue_start_common_params {
 
 	struct qed_sb_info *p_sb;
 	u8 sb_idx;
+
+	u8 tc;
 };
 
 struct qed_rxq_start_ret_params {
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 2/3] qede: Add destination ip based flow profile.
From: Manish Chopra @ 2018-08-09 18:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, ariel.elior, michal.kalderon
In-Reply-To: <20180809181351.32394-1-manish.chopra@cavium.com>

This patch adds support for dropping and redirecting
the flows based on destination IP in the packet.

This also moves the profile mode settings in their own
functions which can be used through tc flows in successive
patch.

For example -

ethtool -N p5p1 flow-type tcp4 dst-ip 192.168.40.100 action -1
ethtool -N p5p1 flow-type udp4 dst-ip 192.168.50.100 action 1
ethtool -N p5p1 flow-type tcp4 dst-ip 192.168.60.100 action 0x100000000

Signed-off-by: Manish Chopra <manish.chopra@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
 drivers/net/ethernet/qlogic/qede/qede_filter.c | 114 ++++++++++++++-----------
 1 file changed, 66 insertions(+), 48 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index f9a327c..d090257 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -1599,6 +1599,69 @@ static int qede_flow_spec_validate_unused(struct qede_dev *edev,
 	return 0;
 }
 
+static int qede_set_v4_tuple_to_profile(struct qede_dev *edev,
+					struct qede_arfs_tuple *t)
+{
+	/* We must have Only 4-tuples/l4 port/src ip/dst ip
+	 * as an input.
+	 */
+	if (t->src_port && t->dst_port && t->src_ipv4 && t->dst_ipv4) {
+		t->mode = QED_FILTER_CONFIG_MODE_5_TUPLE;
+	} else if (!t->src_port && t->dst_port &&
+		   !t->src_ipv4 && !t->dst_ipv4) {
+		t->mode = QED_FILTER_CONFIG_MODE_L4_PORT;
+	} else if (!t->src_port && !t->dst_port &&
+		   !t->dst_ipv4 && t->src_ipv4) {
+		t->mode = QED_FILTER_CONFIG_MODE_IP_SRC;
+	} else if (!t->src_port && !t->dst_port &&
+		   t->dst_ipv4 && !t->src_ipv4) {
+		t->mode = QED_FILTER_CONFIG_MODE_IP_DEST;
+	} else {
+		DP_INFO(edev, "Invalid N-tuple\n");
+		return -EOPNOTSUPP;
+	}
+
+	t->ip_comp = qede_flow_spec_ipv4_cmp;
+	t->build_hdr = qede_flow_build_ipv4_hdr;
+	t->stringify = qede_flow_stringify_ipv4_hdr;
+
+	return 0;
+}
+
+static int qede_set_v6_tuple_to_profile(struct qede_dev *edev,
+					struct qede_arfs_tuple *t,
+					struct in6_addr *zaddr)
+{
+	/* We must have Only 4-tuples/l4 port/src ip/dst ip
+	 * as an input.
+	 */
+	if (t->src_port && t->dst_port &&
+	    memcmp(&t->src_ipv6, zaddr, sizeof(struct in6_addr)) &&
+	    memcmp(&t->dst_ipv6, zaddr, sizeof(struct in6_addr))) {
+		t->mode = QED_FILTER_CONFIG_MODE_5_TUPLE;
+	} else if (!t->src_port && t->dst_port &&
+		   !memcmp(&t->src_ipv6, zaddr, sizeof(struct in6_addr)) &&
+		   !memcmp(&t->dst_ipv6, zaddr, sizeof(struct in6_addr))) {
+		t->mode = QED_FILTER_CONFIG_MODE_L4_PORT;
+	} else if (!t->src_port && !t->dst_port &&
+		   !memcmp(&t->dst_ipv6, zaddr, sizeof(struct in6_addr)) &&
+		   memcmp(&t->src_ipv6, zaddr, sizeof(struct in6_addr))) {
+		t->mode = QED_FILTER_CONFIG_MODE_IP_SRC;
+	} else if (!t->src_port && !t->dst_port &&
+		   memcmp(&t->dst_ipv6, zaddr, sizeof(struct in6_addr)) &&
+		   !memcmp(&t->src_ipv6, zaddr, sizeof(struct in6_addr))) {
+		t->mode = QED_FILTER_CONFIG_MODE_IP_DEST;
+	} else {
+		DP_INFO(edev, "Invalid N-tuple\n");
+		return -EOPNOTSUPP;
+	}
+
+	t->ip_comp = qede_flow_spec_ipv6_cmp;
+	t->build_hdr = qede_flow_build_ipv6_hdr;
+
+	return 0;
+}
+
 static int qede_flow_spec_to_tuple_ipv4_common(struct qede_dev *edev,
 					       struct qede_arfs_tuple *t,
 					       struct ethtool_rx_flow_spec *fs)
@@ -1638,27 +1701,7 @@ static int qede_flow_spec_to_tuple_ipv4_common(struct qede_dev *edev,
 	t->src_port = fs->h_u.tcp_ip4_spec.psrc;
 	t->dst_port = fs->h_u.tcp_ip4_spec.pdst;
 
-	/* We must either have a valid 4-tuple or only dst port
-	 * or only src ip as an input
-	 */
-	if (t->src_port && t->dst_port && t->src_ipv4 && t->dst_ipv4) {
-		t->mode = QED_FILTER_CONFIG_MODE_5_TUPLE;
-	} else if (!t->src_port && t->dst_port &&
-		   !t->src_ipv4 && !t->dst_ipv4) {
-		t->mode = QED_FILTER_CONFIG_MODE_L4_PORT;
-	}  else if (!t->src_port && !t->dst_port &&
-		    !t->dst_ipv4 && t->src_ipv4) {
-		t->mode = QED_FILTER_CONFIG_MODE_IP_SRC;
-	} else {
-		DP_INFO(edev, "Invalid N-tuple\n");
-		return -EOPNOTSUPP;
-	}
-
-	t->ip_comp = qede_flow_spec_ipv4_cmp;
-	t->build_hdr = qede_flow_build_ipv4_hdr;
-	t->stringify = qede_flow_stringify_ipv4_hdr;
-
-	return 0;
+	return qede_set_v4_tuple_to_profile(edev, t);
 }
 
 static int qede_flow_spec_to_tuple_tcpv4(struct qede_dev *edev,
@@ -1690,10 +1733,8 @@ static int qede_flow_spec_to_tuple_ipv6_common(struct qede_dev *edev,
 					       struct ethtool_rx_flow_spec *fs)
 {
 	struct in6_addr zero_addr;
-	void *p;
 
-	p = &zero_addr;
-	memset(p, 0, sizeof(zero_addr));
+	memset(&zero_addr, 0, sizeof(zero_addr));
 
 	if ((fs->h_u.tcp_ip6_spec.psrc &
 	     fs->m_u.tcp_ip6_spec.psrc) != fs->h_u.tcp_ip6_spec.psrc) {
@@ -1720,30 +1761,7 @@ static int qede_flow_spec_to_tuple_ipv6_common(struct qede_dev *edev,
 	t->src_port = fs->h_u.tcp_ip6_spec.psrc;
 	t->dst_port = fs->h_u.tcp_ip6_spec.pdst;
 
-	/* We must make sure we have a valid 4-tuple or only dest port
-	 * or only src ip as an input
-	 */
-	if (t->src_port && t->dst_port &&
-	    memcmp(&t->src_ipv6, p, sizeof(struct in6_addr)) &&
-	    memcmp(&t->dst_ipv6, p, sizeof(struct in6_addr))) {
-		t->mode = QED_FILTER_CONFIG_MODE_5_TUPLE;
-	} else if (!t->src_port && t->dst_port &&
-		   !memcmp(&t->src_ipv6, p, sizeof(struct in6_addr)) &&
-		   !memcmp(&t->dst_ipv6, p, sizeof(struct in6_addr))) {
-		t->mode = QED_FILTER_CONFIG_MODE_L4_PORT;
-	} else if (!t->src_port && !t->dst_port &&
-		   !memcmp(&t->dst_ipv6, p, sizeof(struct in6_addr)) &&
-		   memcmp(&t->src_ipv6, p, sizeof(struct in6_addr))) {
-		t->mode = QED_FILTER_CONFIG_MODE_IP_SRC;
-	} else {
-		DP_INFO(edev, "Invalid N-tuple\n");
-		return -EOPNOTSUPP;
-	}
-
-	t->ip_comp = qede_flow_spec_ipv6_cmp;
-	t->build_hdr = qede_flow_build_ipv6_hdr;
-
-	return 0;
+	return qede_set_v6_tuple_to_profile(edev, t, &zero_addr);
 }
 
 static int qede_flow_spec_to_tuple_tcpv6(struct qede_dev *edev,
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 3/3] qede: Ingress tc flower offload (drop action) support.
From: Manish Chopra @ 2018-08-09 18:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, ariel.elior, michal.kalderon
In-Reply-To: <20180809181351.32394-1-manish.chopra@cavium.com>

The main motive of this patch is to lay down driver's
tc offload infrastructure in place.

With these changes tc can offload various supported flow
profiles (4 tuples, src-ip, dst-ip, l4 port) for the drop
action. Dropped flows statistic is a global counter for
all the offloaded flows for drop action and is populated
in ethtool statistics as common "gft_filter_drop".

Examples -

tc qdisc add dev p4p1 ingress
tc filter add dev p4p1 protocol ipv4 parent ffff: flower \
	skip_sw ip_proto tcp dst_ip 192.168.40.200 action drop
tc filter add dev p4p1 protocol ipv4 parent ffff: flower \
	skip_sw ip_proto udp src_ip 192.168.40.100 action drop
tc filter add dev p4p1 protocol ipv4 parent ffff: flower \
	skip_sw ip_proto tcp src_ip 192.168.40.100 dst_ip 192.168.40.200 \
	src_port 453 dst_port 876 action drop
tc filter add dev p4p1 protocol ipv4 parent ffff: flower \
	skip_sw ip_proto tcp dst_port 98 action drop

Signed-off-by: Manish Chopra <manish.chopra@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
 drivers/net/ethernet/qlogic/qede/qede.h         |   7 +-
 drivers/net/ethernet/qlogic/qede/qede_ethtool.c |   2 +-
 drivers/net/ethernet/qlogic/qede/qede_filter.c  | 308 +++++++++++++++++++++++-
 drivers/net/ethernet/qlogic/qede/qede_main.c    |  56 ++++-
 4 files changed, 362 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index e90c60a..6a4d266 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -52,6 +52,9 @@
 #include <linux/qed/qed_chain.h>
 #include <linux/qed/qed_eth_if.h>
 
+#include <net/pkt_cls.h>
+#include <net/tc_act/tc_gact.h>
+
 #define QEDE_MAJOR_VERSION		8
 #define QEDE_MINOR_VERSION		33
 #define QEDE_REVISION_VERSION		0
@@ -469,7 +472,7 @@ int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
 void qede_free_arfs(struct qede_dev *edev);
 int qede_alloc_arfs(struct qede_dev *edev);
 int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info);
-int qede_del_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info);
+int qede_delete_flow_filter(struct qede_dev *edev, u64 cookie);
 int qede_get_cls_rule_entry(struct qede_dev *edev, struct ethtool_rxnfc *cmd);
 int qede_get_cls_rule_all(struct qede_dev *edev, struct ethtool_rxnfc *info,
 			  u32 *rule_locs);
@@ -535,6 +538,8 @@ void qede_reload(struct qede_dev *edev,
 int qede_txq_has_work(struct qede_tx_queue *txq);
 void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq, u8 count);
 void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq);
+int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
+			    struct tc_cls_flower_offload *f);
 
 #define RX_RING_SIZE_POW	13
 #define RX_RING_SIZE		((u16)BIT(RX_RING_SIZE_POW))
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 2bd84d6..19652cd 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -1285,7 +1285,7 @@ static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
 		rc = qede_add_cls_rule(edev, info);
 		break;
 	case ETHTOOL_SRXCLSRLDEL:
-		rc = qede_del_cls_rule(edev, info);
+		rc = qede_delete_flow_filter(edev, info->fs.location);
 		break;
 	default:
 		DP_INFO(edev, "Command parameters not supported\n");
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index d090257..9673d19 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -83,7 +83,7 @@ struct qede_arfs_fltr_node {
 	struct qede_arfs_tuple tuple;
 
 	u32 flow_id;
-	u16 sw_id;
+	u64 sw_id;
 	u16 rxq_id;
 	u16 next_rxq_id;
 	u8 vfid;
@@ -138,7 +138,7 @@ static void qede_configure_arfs_fltr(struct qede_dev *edev,
 
 		n->tuple.stringify(&n->tuple, tuple_buffer);
 		DP_VERBOSE(edev, NETIF_MSG_RX_STATUS,
-			   "%s sw_id[0x%x]: %s [vf %u queue %d]\n",
+			   "%s sw_id[0x%llx]: %s [vf %u queue %d]\n",
 			   add_fltr ? "Adding" : "Deleting",
 			   n->sw_id, tuple_buffer, n->vfid, rxq_id);
 	}
@@ -152,7 +152,10 @@ static void qede_configure_arfs_fltr(struct qede_dev *edev,
 qede_free_arfs_filter(struct qede_dev *edev,  struct qede_arfs_fltr_node *fltr)
 {
 	kfree(fltr->data);
-	clear_bit(fltr->sw_id, edev->arfs->arfs_fltr_bmap);
+
+	if (fltr->sw_id < QEDE_RFS_MAX_FLTR)
+		clear_bit(fltr->sw_id, edev->arfs->arfs_fltr_bmap);
+
 	kfree(fltr);
 }
 
@@ -214,7 +217,7 @@ void qede_arfs_filter_op(void *dev, void *filter, u8 fw_rc)
 
 	if (fw_rc) {
 		DP_NOTICE(edev,
-			  "Failed arfs filter configuration fw_rc=%d, flow_id=%d, sw_id=%d, src_port=%d, dst_port=%d, rxq=%d\n",
+			  "Failed arfs filter configuration fw_rc=%d, flow_id=%d, sw_id=0x%llx, src_port=%d, dst_port=%d, rxq=%d\n",
 			  fw_rc, fltr->flow_id, fltr->sw_id,
 			  ntohs(fltr->tuple.src_port),
 			  ntohs(fltr->tuple.dst_port), fltr->rxq_id);
@@ -1348,7 +1351,7 @@ void qede_config_rx_mode(struct net_device *ndev)
 }
 
 static struct qede_arfs_fltr_node *
-qede_get_arfs_fltr_by_loc(struct hlist_head *head, u32 location)
+qede_get_arfs_fltr_by_loc(struct hlist_head *head, u64 location)
 {
 	struct qede_arfs_fltr_node *fltr;
 
@@ -1959,9 +1962,8 @@ int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info)
 	return rc;
 }
 
-int qede_del_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info)
+int qede_delete_flow_filter(struct qede_dev *edev, u64 cookie)
 {
-	struct ethtool_rx_flow_spec *fsp = &info->fs;
 	struct qede_arfs_fltr_node *fltr = NULL;
 	int rc = -EPERM;
 
@@ -1970,7 +1972,7 @@ int qede_del_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info)
 		goto unlock;
 
 	fltr = qede_get_arfs_fltr_by_loc(QEDE_ARFS_BUCKET_HEAD(edev, 0),
-					 fsp->location);
+					 cookie);
 	if (!fltr)
 		goto unlock;
 
@@ -2000,3 +2002,293 @@ int qede_get_arfs_filter_count(struct qede_dev *edev)
 	__qede_unlock(edev);
 	return count;
 }
+
+static int qede_parse_actions(struct qede_dev *edev,
+			      struct tcf_exts *exts)
+{
+	int rc = -EINVAL, num_act = 0;
+	const struct tc_action *a;
+	bool is_drop = false;
+	LIST_HEAD(actions);
+
+	if (!tcf_exts_has_actions(exts)) {
+		DP_NOTICE(edev, "No tc actions received\n");
+		return rc;
+	}
+
+	tcf_exts_to_list(exts, &actions);
+	list_for_each_entry(a, &actions, list) {
+		num_act++;
+
+		if (is_tcf_gact_shot(a))
+			is_drop = true;
+	}
+
+	if (num_act == 1 && is_drop)
+		return 0;
+
+	return rc;
+}
+
+static int
+qede_tc_parse_ports(struct qede_dev *edev,
+		    struct tc_cls_flower_offload *f,
+		    struct qede_arfs_tuple *t)
+{
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
+		struct flow_dissector_key_ports *key, *mask;
+
+		key = skb_flow_dissector_target(f->dissector,
+						FLOW_DISSECTOR_KEY_PORTS,
+						f->key);
+		mask = skb_flow_dissector_target(f->dissector,
+						 FLOW_DISSECTOR_KEY_PORTS,
+						 f->mask);
+
+		if ((key->src && mask->src != U16_MAX) ||
+		    (key->dst && mask->dst != U16_MAX)) {
+			DP_NOTICE(edev, "Do not support ports masks\n");
+			return -EINVAL;
+		}
+
+		t->src_port = key->src;
+		t->dst_port = key->dst;
+	}
+
+	return 0;
+}
+
+static int
+qede_tc_parse_v6_common(struct qede_dev *edev,
+			struct tc_cls_flower_offload *f,
+			struct qede_arfs_tuple *t)
+{
+	struct in6_addr zero_addr, addr;
+
+	memset(&zero_addr, 0, sizeof(addr));
+	memset(&addr, 0xff, sizeof(addr));
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
+		struct flow_dissector_key_ipv6_addrs *key, *mask;
+
+		key = skb_flow_dissector_target(f->dissector,
+						FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+						f->key);
+		mask = skb_flow_dissector_target(f->dissector,
+						 FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+						 f->mask);
+
+		if ((memcmp(&key->src, &zero_addr, sizeof(addr)) &&
+		     memcmp(&mask->src, &addr, sizeof(addr))) ||
+		    (memcmp(&key->dst, &zero_addr, sizeof(addr)) &&
+		     memcmp(&mask->dst, &addr, sizeof(addr)))) {
+			DP_NOTICE(edev,
+				  "Do not support IPv6 address prefix/mask\n");
+			return -EINVAL;
+		}
+
+		memcpy(&t->src_ipv6, &key->src, sizeof(addr));
+		memcpy(&t->dst_ipv6, &key->dst, sizeof(addr));
+	}
+
+	if (qede_tc_parse_ports(edev, f, t))
+		return -EINVAL;
+
+	return qede_set_v6_tuple_to_profile(edev, t, &zero_addr);
+}
+
+static int
+qede_tc_parse_v4_common(struct qede_dev *edev,
+			struct tc_cls_flower_offload *f,
+			struct qede_arfs_tuple *t)
+{
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
+		struct flow_dissector_key_ipv4_addrs *key, *mask;
+
+		key = skb_flow_dissector_target(f->dissector,
+						FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+						f->key);
+		mask = skb_flow_dissector_target(f->dissector,
+						 FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+						 f->mask);
+
+		if ((key->src && mask->src != U32_MAX) ||
+		    (key->dst && mask->dst != U32_MAX)) {
+			DP_NOTICE(edev, "Do not support ipv4 prefix/masks\n");
+			return -EINVAL;
+		}
+
+		t->src_ipv4 = key->src;
+		t->dst_ipv4 = key->dst;
+	}
+
+	if (qede_tc_parse_ports(edev, f, t))
+		return -EINVAL;
+
+	return qede_set_v4_tuple_to_profile(edev, t);
+}
+
+static int
+qede_tc_parse_tcp_v6(struct qede_dev *edev,
+		     struct tc_cls_flower_offload *f,
+		     struct qede_arfs_tuple *tuple)
+{
+	tuple->ip_proto = IPPROTO_TCP;
+	tuple->eth_proto = htons(ETH_P_IPV6);
+
+	return qede_tc_parse_v6_common(edev, f, tuple);
+}
+
+static int
+qede_tc_parse_tcp_v4(struct qede_dev *edev,
+		     struct tc_cls_flower_offload *f,
+		     struct qede_arfs_tuple *tuple)
+{
+	tuple->ip_proto = IPPROTO_TCP;
+	tuple->eth_proto = htons(ETH_P_IP);
+
+	return qede_tc_parse_v4_common(edev, f, tuple);
+}
+
+static int
+qede_tc_parse_udp_v6(struct qede_dev *edev,
+		     struct tc_cls_flower_offload *f,
+		     struct qede_arfs_tuple *tuple)
+{
+	tuple->ip_proto = IPPROTO_UDP;
+	tuple->eth_proto = htons(ETH_P_IPV6);
+
+	return qede_tc_parse_v6_common(edev, f, tuple);
+}
+
+static int
+qede_tc_parse_udp_v4(struct qede_dev *edev,
+		     struct tc_cls_flower_offload *f,
+		     struct qede_arfs_tuple *tuple)
+{
+	tuple->ip_proto = IPPROTO_UDP;
+	tuple->eth_proto = htons(ETH_P_IP);
+
+	return qede_tc_parse_v4_common(edev, f, tuple);
+}
+
+static int
+qede_parse_flower_attr(struct qede_dev *edev, __be16 proto,
+		       struct tc_cls_flower_offload *f,
+		       struct qede_arfs_tuple *tuple)
+{
+	int rc = -EINVAL;
+	u8 ip_proto = 0;
+
+	memset(tuple, 0, sizeof(*tuple));
+
+	if (f->dissector->used_keys &
+	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
+	      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_PORTS))) {
+		DP_NOTICE(edev, "Unsupported key set:0x%x\n",
+			  f->dissector->used_keys);
+		return -EOPNOTSUPP;
+	}
+
+	if (proto != htons(ETH_P_IP) &&
+	    proto != htons(ETH_P_IPV6)) {
+		DP_NOTICE(edev, "Unsupported proto=0x%x\n", proto);
+		return -EPROTONOSUPPORT;
+	}
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+		struct flow_dissector_key_basic *key;
+
+		key = skb_flow_dissector_target(f->dissector,
+						FLOW_DISSECTOR_KEY_BASIC,
+						f->key);
+		ip_proto = key->ip_proto;
+	}
+
+	if (ip_proto == IPPROTO_TCP && proto == htons(ETH_P_IP))
+		rc = qede_tc_parse_tcp_v4(edev, f, tuple);
+	else if (ip_proto == IPPROTO_TCP && proto == htons(ETH_P_IPV6))
+		rc = qede_tc_parse_tcp_v6(edev, f, tuple);
+	else if (ip_proto == IPPROTO_UDP && proto == htons(ETH_P_IP))
+		rc = qede_tc_parse_udp_v4(edev, f, tuple);
+	else if (ip_proto == IPPROTO_UDP && proto == htons(ETH_P_IPV6))
+		rc = qede_tc_parse_udp_v6(edev, f, tuple);
+	else
+		DP_NOTICE(edev, "Invalid tc protocol request\n");
+
+	return rc;
+}
+
+int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
+			    struct tc_cls_flower_offload *f)
+{
+	struct qede_arfs_fltr_node *n;
+	int min_hlen, rc = -EINVAL;
+	struct qede_arfs_tuple t;
+
+	__qede_lock(edev);
+
+	if (!edev->arfs) {
+		rc = -EPERM;
+		goto unlock;
+	}
+
+	/* parse flower attribute and prepare filter */
+	if (qede_parse_flower_attr(edev, proto, f, &t))
+		goto unlock;
+
+	/* Validate profile mode and number of filters */
+	if ((edev->arfs->filter_count && edev->arfs->mode != t.mode) ||
+	    edev->arfs->filter_count == QEDE_RFS_MAX_FLTR) {
+		DP_NOTICE(edev,
+			  "Filter configuration invalidated, filter mode=0x%x, configured mode=0x%x, filter count=0x%x\n",
+			  t.mode, edev->arfs->mode, edev->arfs->filter_count);
+		goto unlock;
+	}
+
+	/* parse tc actions and get the vf_id */
+	if (qede_parse_actions(edev, f->exts))
+		goto unlock;
+
+	if (qede_flow_find_fltr(edev, &t)) {
+		rc = -EEXIST;
+		goto unlock;
+	}
+
+	n = kzalloc(sizeof(*n), GFP_KERNEL);
+	if (!n) {
+		rc = -ENOMEM;
+		goto unlock;
+	}
+
+	min_hlen = qede_flow_get_min_header_size(&t);
+
+	n->data = kzalloc(min_hlen, GFP_KERNEL);
+	if (!n->data) {
+		kfree(n);
+		rc = -ENOMEM;
+		goto unlock;
+	}
+
+	memcpy(&n->tuple, &t, sizeof(n->tuple));
+
+	n->buf_len = min_hlen;
+	n->b_is_drop = true;
+	n->sw_id = f->cookie;
+
+	n->tuple.build_hdr(&n->tuple, n->data);
+
+	rc = qede_enqueue_fltr_and_config_searcher(edev, n, 0);
+	if (rc)
+		goto unlock;
+
+	qede_configure_arfs_fltr(edev, n, n->rxq_id, true);
+	rc = qede_poll_arfs_filter_config(edev, n);
+
+unlock:
+	__qede_unlock(edev);
+	return rc;
+}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index d7299af..4b5d98f 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -557,12 +557,66 @@ int qede_setup_tc(struct net_device *ndev, u8 num_tc)
 }
 
 static int
+qede_set_flower(struct qede_dev *edev, struct tc_cls_flower_offload *f,
+		__be16 proto)
+{
+	switch (f->command) {
+	case TC_CLSFLOWER_REPLACE:
+		return qede_add_tc_flower_fltr(edev, proto, f);
+	case TC_CLSFLOWER_DESTROY:
+		return qede_delete_flow_filter(edev, f->cookie);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int qede_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+				  void *cb_priv)
+{
+	struct tc_cls_flower_offload *f;
+	struct qede_dev *edev = cb_priv;
+
+	if (!tc_cls_can_offload_and_chain0(edev->ndev, type_data))
+		return -EOPNOTSUPP;
+
+	switch (type) {
+	case TC_SETUP_CLSFLOWER:
+		f = type_data;
+		return qede_set_flower(edev, f, f->common.protocol);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int qede_setup_tc_block(struct qede_dev *edev,
+			       struct tc_block_offload *f)
+{
+	if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+		return -EOPNOTSUPP;
+
+	switch (f->command) {
+	case TC_BLOCK_BIND:
+		return tcf_block_cb_register(f->block,
+					     qede_setup_tc_block_cb,
+					     edev, edev, f->extack);
+	case TC_BLOCK_UNBIND:
+		tcf_block_cb_unregister(f->block, qede_setup_tc_block_cb, edev);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int
 qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
 		      void *type_data)
 {
+	struct qede_dev *edev = netdev_priv(dev);
 	struct tc_mqprio_qopt *mqprio;
 
 	switch (type) {
+	case TC_SETUP_BLOCK:
+		return qede_setup_tc_block(edev, type_data);
 	case TC_SETUP_QDISC_MQPRIO:
 		mqprio = type_data;
 
@@ -727,7 +781,7 @@ static void qede_init_ndev(struct qede_dev *edev)
 	/* user-changeble features */
 	hw_features = NETIF_F_GRO | NETIF_F_GRO_HW | NETIF_F_SG |
 		      NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		      NETIF_F_TSO | NETIF_F_TSO6;
+		      NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_TC;
 
 	if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1)
 		hw_features |= NETIF_F_NTUPLE;
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCH v4 net-next 0/9] Add support for XGMAC2 in stmmac
From: David Miller @ 2018-08-09 18:16 UTC (permalink / raw)
  To: Jose.Abreu
  Cc: netdev, Joao.Pinto, peppe.cavallaro, alexandre.torgue, andrew,
	f.fainelli
In-Reply-To: <cover.1533715274.git.joabreu@synopsys.com>

From: Jose Abreu <Jose.Abreu@synopsys.com>
Date: Wed,  8 Aug 2018 09:04:28 +0100

> This series adds support for 10Gigabit IP in stmmac.

Series applied, thanks Jose.

^ permalink raw reply

* Re: [PATCH net-next] be2net: Use Kconfig flag to support for enabling/disabling adapters
From: David Miller @ 2018-08-09 21:09 UTC (permalink / raw)
  To: poros
  Cc: netdev, ivecera, sathya.perla, ajit.khaparde,
	sriharsha.basavapatna, somnath.kotur, linux-kernel
In-Reply-To: <20180808113505.550-1-poros@redhat.com>

From: Petr Oros <poros@redhat.com>
Date: Wed,  8 Aug 2018 13:35:01 +0200

> Add flags to enable/disable supported chips in be2net.
> 
> With disable support are removed coresponding PCI IDs and
> also codepaths with [BE2|BE3|BEx|lancer|skyhawk]_chip checks.
> 
> Disable chip will reduce module size by:
> BE2 ~2kb
> BE3 ~3kb
> Lancer ~10kb
> Skyhawk ~9kb
> 
> When enable skyhawk only it will reduce module size by ~20kb
> 
> New help style in Kconfig
> 
> Reviewed-by: Ivan Vecera <ivecera@redhat.com>
> Signed-off-by: Petr Oros <poros@redhat.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] net: skbuff.h: fix using plain integer as NULL warning
From: David Miller @ 2018-08-09 21:10 UTC (permalink / raw)
  To: yuehaibing
  Cc: edumazet, willemb, dja, linux-kernel, netdev, ast, pabeni, posk,
	daniel
In-Reply-To: <20180808114031.12292-1-yuehaibing@huawei.com>

From: YueHaibing <yuehaibing@huawei.com>
Date: Wed, 8 Aug 2018 19:40:31 +0800

> Fixes the following sparse warning:
> ./include/linux/skbuff.h:2365:58: warning: Using plain integer as NULL pointer
> 
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] decnet: fix using plain integer as NULL warning
From: David Miller @ 2018-08-09 21:12 UTC (permalink / raw)
  To: yuehaibing; +Cc: linux-kernel, netdev, keescook, edumazet, linux-decnet-user
In-Reply-To: <20180808115932.12944-1-yuehaibing@huawei.com>

From: YueHaibing <yuehaibing@huawei.com>
Date: Wed, 8 Aug 2018 19:59:32 +0800

> Fixes the following sparse warning:
> net/decnet/dn_route.c:407:30: warning: Using plain integer as NULL pointer
> net/decnet/dn_route.c:1923:22: warning: Using plain integer as NULL pointer
> 
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] mlxsw: spectrum_flower: use PTR_ERR_OR_ZERO()
From: David Miller @ 2018-08-09 21:14 UTC (permalink / raw)
  To: yuehaibing; +Cc: jiri, linux-kernel, netdev, idosch
In-Reply-To: <20180808122908.13664-1-yuehaibing@huawei.com>

From: YueHaibing <yuehaibing@huawei.com>
Date: Wed, 8 Aug 2018 20:29:08 +0800

> Fix ptr_ret.cocci warnings:
>  drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c:543:1-3: WARNING: PTR_ERR_OR_ZERO can be used
> 
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>

Applied.

^ permalink raw reply

* Re: [PATCH] ethernet/qlogic: remove unused array msi_tgt_status
From: David Miller @ 2018-08-09 21:17 UTC (permalink / raw)
  To: colin.king
  Cc: harish.patil, manish.chopra, Dept-GELinuxNICDev, netdev,
	kernel-janitors, linux-kernel
In-Reply-To: <20180808180427.14864-1-colin.king@canonical.com>

From: Colin King <colin.king@canonical.com>
Date: Wed,  8 Aug 2018 19:04:27 +0100

> From: Colin Ian King <colin.king@canonical.com>
> 
> Array msi_tgt_status is defined but never used, hence it is
> redundant and can be removed.
> 
> Cleans up clang warning:
> warning: 'msi_tgt_status' defined but not used [-Wunused-const-variable=]
> 
> Signed-off-by: Colin Ian King <colin.king@canonical.com>

Applied, thank you.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox