Netdev List
 help / color / mirror / Atom feed
* Re: [net-next] dummy: expend mtu range for dummy device
From: Sergei Shtylyov @ 2016-12-07 10:14 UTC (permalink / raw)
  To: Zhang Shengju, jarod, netdev
In-Reply-To: <1481103693-16394-1-git-send-email-zhangshengju@cmss.chinamobile.com>

Hello!

On 12/7/2016 12:41 PM, Zhang Shengju wrote:

> After commit 61e84623ace3 ("net: centralize net_device min/max MTU checking"),
> the mtu range for dummy device becomes [68, 1500].
>
> This patch expends it to [0, 65535].

    "Extend" here and in the subject.

> Signed-off-by: Zhang Shengju <zhangshengju@cmss.chinamobile.com>
[...]

MBR, Sergei

^ permalink raw reply

* Re: [PATCH v3 net-next 4/4] bpf: xdp: Add XDP example for head adjustment
From: Jesper Dangaard Brouer @ 2016-12-07 10:34 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: netdev, Alexei Starovoitov, Brenden Blanco, Daniel Borkmann,
	David Miller, Jakub Kicinski, John Fastabend, Saeed Mahameed,
	Tariq Toukan, Kernel Team, brouer
In-Reply-To: <1481088714-54512-5-git-send-email-kafai@fb.com>

On Tue, 6 Dec 2016 21:31:54 -0800
Martin KaFai Lau <kafai@fb.com> wrote:

> The XDP prog checks if the incoming packet matches any VIP:PORT
> combination in the BPF hashmap.  If it is, it will encapsulate
> the packet with a IPv4/v6 header as instructed by the value of
> the BPF hashmap and then XDP_TX it out.
> 
> The VIP:PORT -> IP-Encap-Info can be specified by the cmd args
> of the user prog.
> 
> Acked-by: Alexei Starovoitov <ast@kernel.org>
> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> ---
>  samples/bpf/Makefile              |   4 +
>  samples/bpf/bpf_helpers.h         |   2 +
>  samples/bpf/bpf_load.c            |  94 ++++++++++++++
>  samples/bpf/bpf_load.h            |   1 +
>  samples/bpf/xdp1_user.c           |  93 --------------
>  samples/bpf/xdp_tx_iptnl_common.h |  37 ++++++
>  samples/bpf/xdp_tx_iptnl_kern.c   | 232 ++++++++++++++++++++++++++++++++++
>  samples/bpf/xdp_tx_iptnl_user.c   | 253 ++++++++++++++++++++++++++++++++++++++

I got confused by the file name "iptnl", I didn't realize this was
short for iptunnel, before after reading the actually XDP program code.

These are "samples" XDP programs that normal people are expected to
find/discover, could we name it "xdp_tx_tunnel" or "xdp_tx_iptunnel"?
(To guide peoples search for this)

I will likely add a "xdp_tx_vlan" example as I have a customer use-case
that needs this for DDoS scrubbing[1]

[1] http://prototype-kernel.readthedocs.io/en/latest/networking/XDP/use-cases/xdp_use_case_ddos_scrubber.html#forward-clean-traffic

[...]
> diff --git a/samples/bpf/xdp_tx_iptnl_kern.c b/samples/bpf/xdp_tx_iptnl_kern.c
> new file mode 100644
> index 000000000000..d88c064175aa
> --- /dev/null
> +++ b/samples/bpf/xdp_tx_iptnl_kern.c
> @@ -0,0 +1,232 @@
> +/* Copyright (c) 2016 Facebook
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of version 2 of the GNU General Public
> + * License as published by the Free Software Foundation.

Can we add short description of the program, to let readers know if
this is the sample they are looking for. Max 3 lines, like:

 This program demonstrate how XDP does packet header adjustment, here
 by adding an encapsulation tunnel header based on a BPF hashmap.

> + */
> +#include <uapi/linux/bpf.h>
> +#include <linux/in.h>
> +#include <linux/if_ether.h>
> +#include <linux/if_packet.h>
> +#include <linux/if_vlan.h>
> +#include <linux/ip.h>
> +#include <linux/ipv6.h>
> +#include "bpf_helpers.h"
> +#include "xdp_tx_iptnl_common.h"
> +
> +struct bpf_map_def SEC("maps") rxcnt = {
> +	.type = BPF_MAP_TYPE_PERCPU_ARRAY,
> +	.key_size = sizeof(__u32),
> +	.value_size = sizeof(__u64),
> +	.max_entries = 256,
> +};
> +
> +struct bpf_map_def SEC("maps") vip2tnl = {
> +	.type = BPF_MAP_TYPE_HASH,
> +	.key_size = sizeof(struct vip),
> +	.value_size = sizeof(struct iptnl_info),
> +	.max_entries = MAX_IPTNL_ENTRIES,
> +};

[...]

> diff --git a/samples/bpf/xdp_tx_iptnl_user.c b/samples/bpf/xdp_tx_iptnl_user.c
> new file mode 100644
> index 000000000000..9aeef7579af4
> --- /dev/null
> +++ b/samples/bpf/xdp_tx_iptnl_user.c
> @@ -0,0 +1,253 @@
> +/* Copyright (c) 2016 Facebook
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of version 2 of the GNU General Public
> + * License as published by the Free Software Foundation.
> + */
[...]
> +
> +static void usage(const char *cmd)
> +{

Wondering if there should be a descriptive header, that says e.g. 
"XDP tunnel sample" or if command filename "xdp_tx_iptunnel" or
"xdp_tx_tunnel" would be descriptive enough.


> +	printf("Usage: %s [...]\n", cmd);
> +	printf("    -i <ifindex> Interface Index\n");
> +	printf("    -a <vip-service-address> IPv4 or IPv6\n");
> +	printf("    -p <vip-service-port> A port range (e.g. 433-444) is also allowed\n");
> +	printf("    -s <source-ip> Used in the IPTunnel Header\n");
> +	printf("    -d <dest-ip> Used in the IPTunnel header>\n");
> +	printf("    -m <dest-MAC> Used in sending the IP Tunneled pkt>\n");
> +	printf("    -T <stop-after-X-seconds> Default: 0 (forever)\n");
> +	printf("    -P <IP-Protocol> Default is TCP\n");
> +	printf("    -h Display this help\n");
> +}

-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply

* RE: [PATCH 3/3] netns: fix net_generic() "id - 1" bloat
From: David Laight @ 2016-12-07 10:49 UTC (permalink / raw)
  To: 'Alexey Dobriyan'
  Cc: davem@davemloft.net, netdev@vger.kernel.org, xemul@openvz.org
In-Reply-To: <CACVxJT8axg6i0Lvem=fvKqrjTuOzwg63BDbAuR6bzTPrtLuP+g@mail.gmail.com>

From: Alexey Dobriyan
> Sent: 05 December 2016 14:48
> On Mon, Dec 5, 2016 at 3:49 PM, David Laight <David.Laight@aculab.com> wrote:
> > From: Alexey Dobriyan
> >> Sent: 02 December 2016 01:22
> >> net_generic() function is both a) inline and b) used ~600 times.
> >>
> >> It has the following code inside
> >>
> >>               ...
> >>       ptr = ng->ptr[id - 1];
> >>               ...
> >>
> >> "id" is never compile time constant so compiler is forced to subtract 1.
> >> And those decrements or LEA [r32 - 1] instructions add up.
> >>
> >> We also start id'ing from 1 to catch bugs where pernet sybsystem id
> >> is not initialized and 0. This is quite pointless idea (nothing will
> >> work or immediate interference with first registered subsystem) in
> >> general but it hints what needs to be done for code size reduction.
> >>
> >> Namely, overlaying allocation of pointer array and fixed part of
> >> structure in the beginning and using usual base-0 addressing.
> >>
> >> Ids are just cookies, their exact values do not matter, so lets start
> >> with 3 on x86_64.
> > ...
> >>  struct net_generic {
> >> -     struct {
> >> -             unsigned int len;
> >> -             struct rcu_head rcu;
> >> -     } s;
> >> -
> >> -     void *ptr[0];
> >> +     union {
> >> +             struct {
> >> +                     unsigned int len;
> >> +                     struct rcu_head rcu;
> >> +             } s;
> >> +
> >> +             void *ptr[0];
> >> +     };
> >>  };
> >
> > That union is an accident waiting to happen.
> 
> I kind of disagree. Module authors should not be given matches,
> but it is hard to screw up if net_generic() is all you're given.
> 
> > What might work is to offset the Ids by
> > (offsetof(struct net_generic, ptr)/sizeof (void *)) instead of by 1.
> > The subtract from the offset will then counter the structure offset
> > - which is what you are trying to achieve.
> 
> If you suggest this layout
> 
> struct net_generic {
>         struct {
>         } s;
>         void *ptr[0];
> };
> 
> then is it not optimal because offset of "ptr" needs to be somewhere in code
> either in some LEA or imm8 of the final MOV which is 1 byte more bloaty.
> 
> Here is test program
> 
> struct ng1 {
>         union {
>                 struct {
>                         unsigned int len;
>                 } s;
>                 void *ptr[0];
>         };
> };
> struct ng2 {
>         struct {
>                 unsigned int len;
>         } s;
>         void *ptr[0];
> };
> struct net {
>         int x;
>         struct ng1 *gen1;
>         struct ng2 *gen2;
> };
> void *ng1(const struct net *net, unsigned int id)
> {
>         return net->gen1->ptr[id];
> }
> void *ng2(const struct net *net, unsigned int id)
> {
>         return net->gen2->ptr[id];
> }
> 
> 
> 0000000000000000 <ng1>:
>    0:   48 8b 47 08             mov    rax,QWORD PTR [rdi+0x8]
>    4:   89 f6                   mov    esi,esi
>    6:   48 8b 04 f0             mov    rax,QWORD PTR [rax+rsi*8]
>    a:   c3                      ret
> 
> 
> 0000000000000010 <ng2>:
>   10:   48 8b 47 10             mov    rax,QWORD PTR [rdi+0x10]
>   14:   89 f6                   mov    esi,esi
>   16:   48 8b 44 f0 [[[08]]]          mov    rax,QWORD PTR [rax+rsi*8+0x8]
>   1b:   c3                      ret

On x86 that will make ~0 difference since the offset (in that sequence)
doesn't require an extra instruction.

However if you offset the 'id' values so that only
values 2 up are valid the code becomes:
	return net->gen2->ptr[id - 2];
which will be exactly the same code as:
	return net->gen1->ptr[id];
but it is much more obvious that 'id' values must be >= 2.

The '2' should be generated from the structure offset, but with my method
is doesn't actually matter if it is wrong.

	David


^ permalink raw reply

* Re: [PATCH] net:dsa:mv88e6xxx: delete timer and cancel ppu_work
From: Volodymyr Bendiuga @ 2016-12-07 10:38 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: vivien.didelot, f.fainelli, netdev, volodymyr.bendiuga,
	Jonas Johansson
In-Reply-To: <20161206142226.GD26615@lunn.ch>

OK, will check it.

/Volodymyr

On 2016-12-06 15:22, Andrew Lunn wrote:
> On Tue, Dec 06, 2016 at 01:57:42PM +0100, Volodymyr Bendiuga wrote:
>> Signed-off-by: Jonas Johansson <jonas.johansson@westermo.se>
>> Signed-off-by: Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se>
>> ---
>>   drivers/net/dsa/mv88e6xxx/chip.c | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
>> index ca453f3..4212fb6 100644
>> --- a/drivers/net/dsa/mv88e6xxx/chip.c
>> +++ b/drivers/net/dsa/mv88e6xxx/chip.c
>> @@ -4528,8 +4528,11 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
>>   out_mdio:
>>   	mv88e6xxx_mdio_unregister(chip);
>>   out_g2_irq:
>> -	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT) && chip->irq > 0)
>> +	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT) && chip->irq > 0) {
>>   		mv88e6xxx_g2_irq_free(chip);
>> +		del_timer(&chip->ppu_timer);
>> +		cancel_work_sync(&chip->ppu_work);
>> +	}
> Why do this here, inside this if statement?
>
> Vivien has also just reworked the PPU code. Please take a look at his
> patches and see if they fix the issue.
>
> 	Thanks
> 		Andrew

^ permalink raw reply

* Re: [PATCH net-next v3 1/2] flow dissector: ICMP support
From: Simon Horman @ 2016-12-07 11:11 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Jiri Pirko, Tom Herbert, David Miller, netdev
In-Reply-To: <20161207100148.GA1987@nanopsycho>

On Wed, Dec 07, 2016 at 11:01:48AM +0100, Jiri Pirko wrote:
> Wed, Dec 07, 2016 at 10:41:36AM CET, simon.horman@netronome.com wrote:
> >Allow dissection of ICMP(V6) type and code. This should only occur
> >if a packet is ICMP(V6) and the dissector has FLOW_DISSECTOR_KEY_ICMP set.
> >
> >There are currently no users of FLOW_DISSECTOR_KEY_ICMP.
> >A follow-up patch will allow FLOW_DISSECTOR_KEY_ICMP to be used by
> >the flower classifier.
> >---
> >v3
> >* Add FLOW_DISSECTOR_KEY_ICMP and use separate structure for ICMP, struct
> >  flow_dissector_key_icmp, which is a union with struct
> >  flow_dissector_key_ports in struct flow_keys.
> >* Drop checks for !ICMP before accessing port field
> >
> >v2
> >* Include all helpers in this patch
> >---
> > include/net/flow_dissector.h | 55 +++++++++++++++++++++++++++++++++++++++++++-
> > net/core/flow_dissector.c    | 49 +++++++++++++++++++++++++++++++++------
> > 2 files changed, 96 insertions(+), 8 deletions(-)
> >
> >diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
> >index c4f31666afd2..aefb7a8138a6 100644
> >--- a/include/net/flow_dissector.h
> >+++ b/include/net/flow_dissector.h
> >@@ -2,6 +2,7 @@
> > #define _NET_FLOW_DISSECTOR_H
> > 
> > #include <linux/types.h>
> >+#include <linux/in.h>
> > #include <linux/in6.h>
> > #include <uapi/linux/if_ether.h>
> > 
> >@@ -104,6 +105,22 @@ struct flow_dissector_key_ports {
> > 	};
> > };
> > 
> >+/**
> >+ * flow_dissector_key_icmp:
> >+ *	@ports: type and code of ICMP header
> >+ *		icmp: ICMP type (high) and code (low)
> >+ *		type: ICMP type
> >+ *		code: ICMP code
> >+ */
> >+struct flow_dissector_key_icmp {
> >+	union {
> >+		__be16 icmp;
> >+		struct {
> >+			u8 type;
> >+			u8 code;
> >+		};
> >+	};
> >+};
> > 
> > /**
> >  * struct flow_dissector_key_eth_addrs:
> >@@ -122,6 +139,7 @@ enum flow_dissector_key_id {
> > 	FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
> > 	FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
> > 	FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
> >+	FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
> > 	FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
> > 	FLOW_DISSECTOR_KEY_TIPC_ADDRS, /* struct flow_dissector_key_tipc_addrs */
> > 	FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_flow_vlan */
> >@@ -160,7 +178,10 @@ struct flow_keys {
> > 	struct flow_dissector_key_tags tags;
> > 	struct flow_dissector_key_vlan vlan;
> > 	struct flow_dissector_key_keyid keyid;
> >-	struct flow_dissector_key_ports ports;
> >+	union {
> >+		struct flow_dissector_key_ports ports;
> >+		struct flow_dissector_key_icmp icmp;
> >+	};
> 
> Why? You don't need this here.

Thanks, I will remove drop that hunk.

> > 	struct flow_dissector_key_addrs addrs;
> > };
> > 
> >@@ -188,6 +209,38 @@ struct flow_keys_digest {
> > void make_flow_keys_digest(struct flow_keys_digest *digest,
> > 			   const struct flow_keys *flow);
> > 
> >+static inline bool flow_protos_are_icmpv4(__be16 n_proto, u8 ip_proto)
> >+{
> >+	return n_proto == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP;
> >+}
> >+
> >+static inline bool flow_protos_are_icmpv6(__be16 n_proto, u8 ip_proto)
> >+{
> >+	return n_proto == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6;
> >+}
> >+
> >+static inline bool flow_protos_are_icmp_any(__be16 n_proto, u8 ip_proto)
> >+{
> >+	return flow_protos_are_icmpv4(n_proto, ip_proto) ||
> >+		flow_protos_are_icmpv6(n_proto, ip_proto);
> >+}
> >+
> >+static inline bool flow_basic_key_is_icmpv4(const struct flow_dissector_key_basic *basic)
> >+{
> >+	return flow_protos_are_icmpv4(basic->n_proto, basic->ip_proto);
> >+}
> >+
> >+static inline bool flow_basic_key_is_icmpv6(const struct flow_dissector_key_basic *basic)
> >+{
> >+	return flow_protos_are_icmpv6(basic->n_proto, basic->ip_proto);
> >+}
> >+
> >+static inline bool flow_keys_are_icmp_any(const struct flow_keys *keys)
> >+{
> >+	return flow_protos_are_icmp_any(keys->basic.n_proto,
> >+					keys->basic.ip_proto);
> >+}
> >+
> > static inline bool flow_keys_have_l4(const struct flow_keys *keys)
> > {
> > 	return (keys->ports.ports || keys->tags.flow_label);
> >diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
> >index 1eb6f949e5b2..e37ff021a19e 100644
> >--- a/net/core/flow_dissector.c
> >+++ b/net/core/flow_dissector.c
> >@@ -58,6 +58,28 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
> > EXPORT_SYMBOL(skb_flow_dissector_init);
> > 
> > /**
> >+ * skb_flow_get_be16 - extract be16 entity
> >+ * @skb: sk_buff to extract from
> >+ * @poff: offset to extract at
> >+ * @data: raw buffer pointer to the packet
> >+ * @hlen: packet header length
> >+ *
> >+ * The function will try to retrieve a be32 entity at
> >+ * offset poff
> >+ */
> >+__be16 skb_flow_get_be16(const struct sk_buff *skb, int poff, void *data,
> >+			 int hlen)
> >+{
> >+	__be16 *u, _u;
> >+
> >+	u = __skb_header_pointer(skb, poff, sizeof(_u), data, hlen, &_u);
> >+	if (u)
> >+		return *u;
> >+
> >+	return 0;
> >+}
> >+
> >+/**
> >  * __skb_flow_get_ports - extract the upper layer ports and return them
> >  * @skb: sk_buff to extract the ports from
> >  * @thoff: transport header offset
> >@@ -117,6 +139,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
> > 	struct flow_dissector_key_basic *key_basic;
> > 	struct flow_dissector_key_addrs *key_addrs;
> > 	struct flow_dissector_key_ports *key_ports;
> >+	struct flow_dissector_key_icmp *key_icmp;
> > 	struct flow_dissector_key_tags *key_tags;
> > 	struct flow_dissector_key_vlan *key_vlan;
> > 	struct flow_dissector_key_keyid *key_keyid;
> >@@ -537,13 +560,25 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
> > 		break;
> > 	}
> > 
> >-	if (dissector_uses_key(flow_dissector,
> >-			       FLOW_DISSECTOR_KEY_PORTS)) {
> >-		key_ports = skb_flow_dissector_target(flow_dissector,
> >-						      FLOW_DISSECTOR_KEY_PORTS,
> >-						      target_container);
> >-		key_ports->ports = __skb_flow_get_ports(skb, nhoff, ip_proto,
> >-							data, hlen);
> >+	if (flow_protos_are_icmp_any(proto, ip_proto)) {
> 
> You don't need this.
> 
> Just left FLOW_DISSECTOR_KEY_PORTS untouched, and add:
> 
> 	if (dissector_uses_key(flow_dissector,
> 			       FLOW_DISSECTOR_KEY_ICMP)) {
> 			....

Thanks, will do.

> 
> 
> >+		if (dissector_uses_key(flow_dissector,
> >+				       FLOW_DISSECTOR_KEY_ICMP)) {
> >+			key_icmp = skb_flow_dissector_target(flow_dissector,
> >+							     FLOW_DISSECTOR_KEY_ICMP,
> >+							     target_container);
> >+			key_icmp->icmp = skb_flow_get_be16(skb, nhoff, data,
> >+							   hlen);
> >+		}
> >+	} else {
> >+		if (dissector_uses_key(flow_dissector,
> >+				       FLOW_DISSECTOR_KEY_PORTS)) {
> >+			key_ports = skb_flow_dissector_target(flow_dissector,
> >+							      FLOW_DISSECTOR_KEY_PORTS,
> >+							      target_container);
> >+			key_ports->ports = __skb_flow_get_ports(skb, nhoff,
> >+								ip_proto, data,
> >+								hlen);
> >+		}
> > 	}
> > 
> > out_good:
> >-- 
> >2.7.0.rc3.207.g0ac5344
> >

^ permalink raw reply

* [patch] drivers: net: xgene: uninitialized variable in xgene_enet_free_pagepool()
From: Dan Carpenter @ 2016-12-07 11:14 UTC (permalink / raw)
  To: Iyappan Subramanian; +Cc: Keyur Chudgar, netdev, linux-kernel, kernel-janitors

We never set "slots" in this function.

Fixes: a9380b0f7be8 ("drivers: net: xgene: Add support for Jumbo frame")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
I copied how slots gets set in xgene_enet_rx_frame().  Static analysis.
Not tested.

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 6c7eea8b36af..884a334e82d0 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -635,6 +635,7 @@ static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool,
 		return;
 
 	dev = ndev_to_dev(buf_pool->ndev);
+	slots = buf_pool->slots - 1;
 	head = buf_pool->head;
 
 	for (i = 0; i < 4; i++) {

^ permalink raw reply related

* [patch] ser_gigaset: return -ENOMEM on error instead of success
From: Dan Carpenter @ 2016-12-07 11:22 UTC (permalink / raw)
  To: Paul Bolle, Tilman Schmidt
  Cc: Karsten Keil, David S. Miller, gigaset307x-common, netdev,
	kernel-janitors

If we can't allocate the resources in gigaset_initdriver() then we
should return -ENOMEM instead of zero.

Fixes: 2869b23e4b95 ("[PATCH] drivers/isdn/gigaset: new M101 driver (v2)")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
Ancient code.

diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index d1f8ab915b15..b90776ef56ec 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -755,8 +755,10 @@ static int __init ser_gigaset_init(void)
 	driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
 				    GIGASET_MODULENAME, GIGASET_DEVNAME,
 				    &ops, THIS_MODULE);
-	if (!driver)
+	if (!driver) {
+		rc = -ENOMEM;
 		goto error;
+	}
 
 	rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc);
 	if (rc != 0) {

^ permalink raw reply related

* [PATCH net-next v4 0/2] net/sched: cls_flower: Support matching on ICMP
From: Simon Horman @ 2016-12-07 11:34 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Tom Herbert, David Miller, netdev, Simon Horman

Hi,

this series adds support for matching on ICMP type and code to cls_flower.

Changes v3->v4:
* Do not add icmp to struct flow_keys, it is not needed
* Do not test for ICMP protocols in packet in __skb_flow_dissect,
  this is also not needed

Changes v2->v3:
* Add FLOW_DISSECTOR_KEY_ICMP and use separate structure for ICMP

Changes v1->v2:
* Include all dissector helpers in first patch

Simon Horman (2):
  flow dissector: ICMP support
  net/sched: cls_flower: Support matching on ICMP type and code

 include/net/flow_dissector.h | 30 +++++++++++++++++++++++++++
 include/uapi/linux/pkt_cls.h | 10 +++++++++
 net/core/flow_dissector.c    | 31 ++++++++++++++++++++++++++++
 net/sched/cls_flower.c       | 49 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 120 insertions(+)

-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply

* [PATCH net-next v4 1/2] flow dissector: ICMP support
From: Simon Horman @ 2016-12-07 11:34 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Tom Herbert, David Miller, netdev, Simon Horman
In-Reply-To: <1481110452-3129-1-git-send-email-simon.horman@netronome.com>

Allow dissection of ICMP(V6) type and code. This should only occur
if a packet is ICMP(V6) and the dissector has FLOW_DISSECTOR_KEY_ICMP set.

There are currently no users of FLOW_DISSECTOR_KEY_ICMP.
A follow-up patch will allow FLOW_DISSECTOR_KEY_ICMP to be used by
the flower classifier.
---
v4
* Do not add icmp to struct flow_keys, it is not needed
* Do not test for ICMP protocols in packet in __skb_flow_dissect,
  this is also not needed
* Drop now unnecessary helpers

v3
* Add FLOW_DISSECTOR_KEY_ICMP and use separate structure for ICMP, struct
  flow_dissector_key_icmp, which is a union with struct
  flow_dissector_key_ports in struct flow_keys.
* Drop checks for !ICMP before accessing port field

v2
* Include all helpers in this patch
---
 include/net/flow_dissector.h | 30 ++++++++++++++++++++++++++++++
 net/core/flow_dissector.c    | 31 +++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index c4f31666afd2..0b94812cfe09 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -2,6 +2,7 @@
 #define _NET_FLOW_DISSECTOR_H
 
 #include <linux/types.h>
+#include <linux/in.h>
 #include <linux/in6.h>
 #include <uapi/linux/if_ether.h>
 
@@ -104,6 +105,22 @@ struct flow_dissector_key_ports {
 	};
 };
 
+/**
+ * flow_dissector_key_icmp:
+ *	@ports: type and code of ICMP header
+ *		icmp: ICMP type (high) and code (low)
+ *		type: ICMP type
+ *		code: ICMP code
+ */
+struct flow_dissector_key_icmp {
+	union {
+		__be16 icmp;
+		struct {
+			u8 type;
+			u8 code;
+		};
+	};
+};
 
 /**
  * struct flow_dissector_key_eth_addrs:
@@ -122,6 +139,7 @@ enum flow_dissector_key_id {
 	FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
 	FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
 	FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
+	FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
 	FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
 	FLOW_DISSECTOR_KEY_TIPC_ADDRS, /* struct flow_dissector_key_tipc_addrs */
 	FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_flow_vlan */
@@ -188,6 +206,18 @@ struct flow_keys_digest {
 void make_flow_keys_digest(struct flow_keys_digest *digest,
 			   const struct flow_keys *flow);
 
+static inline bool flow_basic_key_is_icmpv4(const struct flow_dissector_key_basic *basic)
+{
+	return basic->n_proto == htons(ETH_P_IP) &&
+		basic->ip_proto == IPPROTO_ICMP;
+}
+
+static inline bool flow_basic_key_is_icmpv6(const struct flow_dissector_key_basic *basic)
+{
+	return basic->n_proto == htons(ETH_P_IPV6) &&
+		basic->ip_proto == IPPROTO_ICMPV6;
+}
+
 static inline bool flow_keys_have_l4(const struct flow_keys *keys)
 {
 	return (keys->ports.ports || keys->tags.flow_label);
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 1eb6f949e5b2..d6447dc10371 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -58,6 +58,28 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
 EXPORT_SYMBOL(skb_flow_dissector_init);
 
 /**
+ * skb_flow_get_be16 - extract be16 entity
+ * @skb: sk_buff to extract from
+ * @poff: offset to extract at
+ * @data: raw buffer pointer to the packet
+ * @hlen: packet header length
+ *
+ * The function will try to retrieve a be32 entity at
+ * offset poff
+ */
+__be16 skb_flow_get_be16(const struct sk_buff *skb, int poff, void *data,
+			 int hlen)
+{
+	__be16 *u, _u;
+
+	u = __skb_header_pointer(skb, poff, sizeof(_u), data, hlen, &_u);
+	if (u)
+		return *u;
+
+	return 0;
+}
+
+/**
  * __skb_flow_get_ports - extract the upper layer ports and return them
  * @skb: sk_buff to extract the ports from
  * @thoff: transport header offset
@@ -117,6 +139,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 	struct flow_dissector_key_basic *key_basic;
 	struct flow_dissector_key_addrs *key_addrs;
 	struct flow_dissector_key_ports *key_ports;
+	struct flow_dissector_key_icmp *key_icmp;
 	struct flow_dissector_key_tags *key_tags;
 	struct flow_dissector_key_vlan *key_vlan;
 	struct flow_dissector_key_keyid *key_keyid;
@@ -546,6 +569,14 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 							data, hlen);
 	}
 
+	if (dissector_uses_key(flow_dissector,
+			       FLOW_DISSECTOR_KEY_ICMP)) {
+		key_icmp = skb_flow_dissector_target(flow_dissector,
+						     FLOW_DISSECTOR_KEY_ICMP,
+						     target_container);
+		key_icmp->icmp = skb_flow_get_be16(skb, nhoff, data, hlen);
+	}
+
 out_good:
 	ret = true;
 
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related

* [PATCH net-next v4 2/2] net/sched: cls_flower: Support matching on ICMP type and code
From: Simon Horman @ 2016-12-07 11:34 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Tom Herbert, David Miller, netdev, Simon Horman
In-Reply-To: <1481110452-3129-1-git-send-email-simon.horman@netronome.com>

Support matching on ICMP type and code.

Example usage:

tc qdisc add dev eth0 ingress

tc filter add dev eth0 protocol ip parent ffff: flower \
	indev eth0 ip_proto icmp type 8 code 0 action drop

tc filter add dev eth0 protocol ipv6 parent ffff: flower \
	indev eth0 ip_proto icmpv6 type 128 code 0 action drop

Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v3
* Use separate dissector key FLOW_DISSECTOR_KEY_ICMP
* Use separate structure to hold icmp fields, this does not share
  storage with ports

v2
* Move helpers to another patch
---
 include/uapi/linux/pkt_cls.h | 10 +++++++++
 net/sched/cls_flower.c       | 49 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 1adc0b654996..884c5aa515c4 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -458,6 +458,16 @@ enum {
 	TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,	/* be16 */
 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT,	/* be16 */
 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,	/* be16 */
+
+	TCA_FLOWER_KEY_ICMPV4_CODE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
+	TCA_FLOWER_KEY_ICMPV4_TYPE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_CODE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_TYPE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
+
 	__TCA_FLOWER_MAX,
 };
 
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 29a9e6d9f274..56df0368125a 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -39,6 +39,7 @@ struct fl_flow_key {
 		struct flow_dissector_key_ipv6_addrs ipv6;
 	};
 	struct flow_dissector_key_ports tp;
+	struct flow_dissector_key_icmp icmp;
 	struct flow_dissector_key_keyid enc_key_id;
 	union {
 		struct flow_dissector_key_ipv4_addrs enc_ipv4;
@@ -386,6 +387,14 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
 	[TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK]	= { .type = NLA_U16 },
 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]	= { .type = NLA_U16 },
 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK]	= { .type = NLA_U16 },
+	[TCA_FLOWER_KEY_ICMPV4_TYPE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV4_TYPE_MASK] = { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV4_CODE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV4_CODE_MASK] = { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_TYPE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_TYPE_MASK] = { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_CODE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_CODE_MASK] = { .type = NLA_U8 },
 };
 
 static void fl_set_key_val(struct nlattr **tb,
@@ -502,6 +511,24 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
 		fl_set_key_val(tb, &key->tp.dst, TCA_FLOWER_KEY_SCTP_DST,
 			       &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
 			       sizeof(key->tp.dst));
+	} else if (flow_basic_key_is_icmpv4(&key->basic)) {
+		fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV4_TYPE,
+			       &mask->icmp.type,
+			       TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
+			       sizeof(key->icmp.type));
+		fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
+			       &mask->icmp.code,
+			       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+			       sizeof(key->icmp.code));
+	} else if (flow_basic_key_is_icmpv6(&key->basic)) {
+		fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV6_TYPE,
+			       &mask->icmp.type,
+			       TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
+			       sizeof(key->icmp.type));
+		fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
+			       &mask->icmp.code,
+			       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+			       sizeof(key->icmp.code));
 	}
 
 	if (tb[TCA_FLOWER_KEY_ENC_IPV4_SRC] ||
@@ -612,6 +639,8 @@ static void fl_init_dissector(struct cls_fl_head *head,
 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
 			     FLOW_DISSECTOR_KEY_PORTS, tp);
 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
+			     FLOW_DISSECTOR_KEY_ICMP, icmp);
+	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
 			     FLOW_DISSECTOR_KEY_VLAN, vlan);
 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
 			     FLOW_DISSECTOR_KEY_ENC_KEYID, enc_key_id);
@@ -977,6 +1006,26 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
 				  &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
 				  sizeof(key->tp.dst))))
 		goto nla_put_failure;
+	else if (flow_basic_key_is_icmpv4(&key->basic) &&
+		 (fl_dump_key_val(skb, &key->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV4_TYPE, &mask->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
+				  sizeof(key->icmp.type)) ||
+		  fl_dump_key_val(skb, &key->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV4_CODE, &mask->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+				  sizeof(key->icmp.code))))
+		goto nla_put_failure;
+	else if (flow_basic_key_is_icmpv6(&key->basic) &&
+		 (fl_dump_key_val(skb, &key->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV6_TYPE, &mask->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
+				  sizeof(key->icmp.type)) ||
+		  fl_dump_key_val(skb, &key->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV6_CODE, &mask->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV6_CODE_MASK,
+				  sizeof(key->icmp.code))))
+		goto nla_put_failure;
 
 	if (key->enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS &&
 	    (fl_dump_key_val(skb, &key->enc_ipv4.src,
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related

* Re: [PATCH net-next v4 2/2] net/sched: cls_flower: Support matching on ICMP type and code
From: Jiri Pirko @ 2016-12-07 11:39 UTC (permalink / raw)
  To: Simon Horman; +Cc: Jiri Pirko, Tom Herbert, David Miller, netdev
In-Reply-To: <1481110452-3129-3-git-send-email-simon.horman@netronome.com>

Wed, Dec 07, 2016 at 12:34:12PM CET, simon.horman@netronome.com wrote:
>Support matching on ICMP type and code.
>
>Example usage:
>
>tc qdisc add dev eth0 ingress
>
>tc filter add dev eth0 protocol ip parent ffff: flower \
>	indev eth0 ip_proto icmp type 8 code 0 action drop
>
>tc filter add dev eth0 protocol ipv6 parent ffff: flower \
>	indev eth0 ip_proto icmpv6 type 128 code 0 action drop
>
>Signed-off-by: Simon Horman <simon.horman@netronome.com>
>---
>v3
>* Use separate dissector key FLOW_DISSECTOR_KEY_ICMP
>* Use separate structure to hold icmp fields, this does not share
>  storage with ports
>
>v2
>* Move helpers to another patch
>---
> include/uapi/linux/pkt_cls.h | 10 +++++++++
> net/sched/cls_flower.c       | 49 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 59 insertions(+)
>
>diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
>index 1adc0b654996..884c5aa515c4 100644
>--- a/include/uapi/linux/pkt_cls.h
>+++ b/include/uapi/linux/pkt_cls.h
>@@ -458,6 +458,16 @@ enum {
> 	TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,	/* be16 */
> 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT,	/* be16 */
> 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,	/* be16 */
>+
>+	TCA_FLOWER_KEY_ICMPV4_CODE,	/* u8 */
>+	TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
>+	TCA_FLOWER_KEY_ICMPV4_TYPE,	/* u8 */
>+	TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
>+	TCA_FLOWER_KEY_ICMPV6_CODE,	/* u8 */
>+	TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
>+	TCA_FLOWER_KEY_ICMPV6_TYPE,	/* u8 */
>+	TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
>+
> 	__TCA_FLOWER_MAX,
> };
> 
>diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
>index 29a9e6d9f274..56df0368125a 100644
>--- a/net/sched/cls_flower.c
>+++ b/net/sched/cls_flower.c
>@@ -39,6 +39,7 @@ struct fl_flow_key {
> 		struct flow_dissector_key_ipv6_addrs ipv6;
> 	};
> 	struct flow_dissector_key_ports tp;
>+	struct flow_dissector_key_icmp icmp;
> 	struct flow_dissector_key_keyid enc_key_id;
> 	union {
> 		struct flow_dissector_key_ipv4_addrs enc_ipv4;
>@@ -386,6 +387,14 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
> 	[TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK]	= { .type = NLA_U16 },
> 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]	= { .type = NLA_U16 },
> 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK]	= { .type = NLA_U16 },
>+	[TCA_FLOWER_KEY_ICMPV4_TYPE]	= { .type = NLA_U8 },
>+	[TCA_FLOWER_KEY_ICMPV4_TYPE_MASK] = { .type = NLA_U8 },
>+	[TCA_FLOWER_KEY_ICMPV4_CODE]	= { .type = NLA_U8 },
>+	[TCA_FLOWER_KEY_ICMPV4_CODE_MASK] = { .type = NLA_U8 },
>+	[TCA_FLOWER_KEY_ICMPV6_TYPE]	= { .type = NLA_U8 },
>+	[TCA_FLOWER_KEY_ICMPV6_TYPE_MASK] = { .type = NLA_U8 },
>+	[TCA_FLOWER_KEY_ICMPV6_CODE]	= { .type = NLA_U8 },
>+	[TCA_FLOWER_KEY_ICMPV6_CODE_MASK] = { .type = NLA_U8 },
> };
> 
> static void fl_set_key_val(struct nlattr **tb,
>@@ -502,6 +511,24 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
> 		fl_set_key_val(tb, &key->tp.dst, TCA_FLOWER_KEY_SCTP_DST,
> 			       &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
> 			       sizeof(key->tp.dst));
>+	} else if (flow_basic_key_is_icmpv4(&key->basic)) {

Please just use:
key->basic.n_proto and key->basic.ip_proto
like the rest of the code. And drop the helpers.

The rest looks fine to me.


>+		fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV4_TYPE,
>+			       &mask->icmp.type,
>+			       TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
>+			       sizeof(key->icmp.type));
>+		fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
>+			       &mask->icmp.code,
>+			       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
>+			       sizeof(key->icmp.code));
>+	} else if (flow_basic_key_is_icmpv6(&key->basic)) {
>+		fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV6_TYPE,
>+			       &mask->icmp.type,
>+			       TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
>+			       sizeof(key->icmp.type));
>+		fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
>+			       &mask->icmp.code,
>+			       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
>+			       sizeof(key->icmp.code));
> 	}
> 
> 	if (tb[TCA_FLOWER_KEY_ENC_IPV4_SRC] ||
>@@ -612,6 +639,8 @@ static void fl_init_dissector(struct cls_fl_head *head,
> 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
> 			     FLOW_DISSECTOR_KEY_PORTS, tp);
> 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
>+			     FLOW_DISSECTOR_KEY_ICMP, icmp);
>+	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
> 			     FLOW_DISSECTOR_KEY_VLAN, vlan);
> 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
> 			     FLOW_DISSECTOR_KEY_ENC_KEYID, enc_key_id);
>@@ -977,6 +1006,26 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
> 				  &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
> 				  sizeof(key->tp.dst))))
> 		goto nla_put_failure;
>+	else if (flow_basic_key_is_icmpv4(&key->basic) &&
>+		 (fl_dump_key_val(skb, &key->icmp.type,
>+				  TCA_FLOWER_KEY_ICMPV4_TYPE, &mask->icmp.type,
>+				  TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
>+				  sizeof(key->icmp.type)) ||
>+		  fl_dump_key_val(skb, &key->icmp.code,
>+				  TCA_FLOWER_KEY_ICMPV4_CODE, &mask->icmp.code,
>+				  TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
>+				  sizeof(key->icmp.code))))
>+		goto nla_put_failure;
>+	else if (flow_basic_key_is_icmpv6(&key->basic) &&
>+		 (fl_dump_key_val(skb, &key->icmp.type,
>+				  TCA_FLOWER_KEY_ICMPV6_TYPE, &mask->icmp.type,
>+				  TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
>+				  sizeof(key->icmp.type)) ||
>+		  fl_dump_key_val(skb, &key->icmp.code,
>+				  TCA_FLOWER_KEY_ICMPV6_CODE, &mask->icmp.code,
>+				  TCA_FLOWER_KEY_ICMPV6_CODE_MASK,
>+				  sizeof(key->icmp.code))))
>+		goto nla_put_failure;
> 
> 	if (key->enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS &&
> 	    (fl_dump_key_val(skb, &key->enc_ipv4.src,
>-- 
>2.7.0.rc3.207.g0ac5344
>

^ permalink raw reply

* [patch net-next] net: mvneta: Indent some statements
From: Dan Carpenter @ 2016-12-07 11:32 UTC (permalink / raw)
  To: Thomas Petazzoni, Marcin Wojtas; +Cc: netdev, kernel-janitors

These two statements were not indented correctly so it's sort of
confusing.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 5e5b259dd2cc..e05e22705cf7 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -3578,9 +3578,10 @@ static int mvneta_stop(struct net_device *dev)
 		mvneta_stop_dev(pp);
 		mvneta_mdio_remove(pp);
 
-	cpuhp_state_remove_instance_nocalls(online_hpstate, &pp->node_online);
-	cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
-					    &pp->node_dead);
+		cpuhp_state_remove_instance_nocalls(online_hpstate,
+						    &pp->node_online);
+		cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+						    &pp->node_dead);
 		on_each_cpu(mvneta_percpu_disable, pp, true);
 		free_percpu_irq(dev->irq, pp->ports);
 	} else {

^ permalink raw reply related

* Re: [PATCH v3 net-next 1/4] bpf: xdp: Allow head adjustment in XDP prog
From: Jakub Kicinski @ 2016-12-07 11:41 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: Martin KaFai Lau, netdev, Alexei Starovoitov, Brenden Blanco,
	David Miller, Jesper Dangaard Brouer, John Fastabend,
	Saeed Mahameed, Tariq Toukan, Kernel Team
In-Reply-To: <5847D723.3020908@iogearbox.net>

On Wed, 07 Dec 2016 10:32:19 +0100, Daniel Borkmann wrote:
> Hi Martin,
> 
> On 12/07/2016 06:31 AM, Martin KaFai Lau wrote:
> [...]
> > diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> > index 49a81f1fc1d6..6261157f444e 100644
> > --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> > +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> > @@ -2794,6 +2794,9 @@ static int mlx4_xdp(struct net_device *dev, struct netdev_xdp *xdp)
> >   	case XDP_QUERY_PROG:
> >   		xdp->prog_attached = mlx4_xdp_attached(dev);
> >   		return 0;
> > +	case XDP_QUERY_FEATURES:
> > +		xdp->features = 0;
> > +		return 0;
> >   	default:
> >   		return -EINVAL;
> >   	}  
> [...]
> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > index 1ff5ea6e1221..786ad7c67215 100644
> > --- a/include/linux/netdevice.h
> > +++ b/include/linux/netdevice.h
> > @@ -30,6 +30,7 @@
> >   #include <linux/delay.h>
> >   #include <linux/atomic.h>
> >   #include <linux/prefetch.h>
> > +#include <linux/bitops.h>
> >   #include <asm/cache.h>
> >   #include <asm/byteorder.h>
> >
> > @@ -805,6 +806,13 @@ struct tc_to_netdev {
> >   	bool egress_dev;
> >   };
> >
> > +/* Driver must allow a XDP prog to extend header by
> > + * up to XDP_PACKET_HEADROOM.  It must also fill out
> > + * the data_hard_start value in struct xdp_buff
> > + * before calling out the xdp_prog.
> > + */
> > +#define XDP_F_ADJUST_HEAD	BIT(0)
> > +
> >   /* These structures hold the attributes of xdp state that are being passed
> >    * to the netdevice through the xdp op.
> >    */
> > @@ -821,6 +829,8 @@ enum xdp_netdev_command {
> >   	 * return true if a program is currently attached and running.
> >   	 */
> >   	XDP_QUERY_PROG,
> > +	/* Check what XDP features are supported by a device */
> > +	XDP_QUERY_FEATURES,
> >   };
> >
> >   struct netdev_xdp {
> > @@ -830,6 +840,8 @@ struct netdev_xdp {
> >   		struct bpf_prog *prog;
> >   		/* XDP_QUERY_PROG */
> >   		bool prog_attached;
> > +		/* XDP_QUERY_FEATURES */
> > +		u32 features;
> >   	};
> >   };
> >  
> [...]
> > diff --git a/net/core/dev.c b/net/core/dev.c
> > index bffb5253e778..90696f7e6b59 100644
> > --- a/net/core/dev.c
> > +++ b/net/core/dev.c
> > @@ -6722,6 +6722,15 @@ int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags)
> >   		prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
> >   		if (IS_ERR(prog))
> >   			return PTR_ERR(prog);
> > +
> > +		xdp.command = XDP_QUERY_FEATURES;
> > +		err = ops->ndo_xdp(dev, &xdp);
> > +		if (err)
> > +			return err;
> > +
> > +		if (prog->xdp_adjust_head &&
> > +		    !(xdp.features & XDP_F_ADJUST_HEAD))
> > +			return -ENOTSUPP;
> >   	}
> >
> >   	memset(&xdp, 0, sizeof(xdp));  
> 
> I think this interface wrt feature flags is rather odd. Why can't this be
> done the usual/expected way we already have today for drivers with NETIF_F_*
> flags?
>
> We have include/linux/netdev_features.h, there, we add all NETIF_F_XDP_*
> feature flags that the device would then select during init, perhaps some of
> them in future might depend on a certain setups, etc, calculating them in a
> separate ndo_xdp() seems odd also in the sense that in-kernel users always
> need to call ops->ndo_xdp() with XDP_QUERY_FEATURES instead of just simply
> doing the test on dev->features & NETIF_F_XDP_* directly. This is global to
> the device anyway and doesn't need to be stored somewhere in private data
> area.

If I may offer one potential disadvantage of just using netdev
features :)
- if we ever want to report something more than flags (say the length
of headroom) we will need another interface.  People who care about
memory savings may also get upset if we extend struct netdevice given
there is no way to compile XDP out, that would be an argument for
keeping the ndo invocation.

> I see nothing wrong if this is exposed/made visible in the usual way through
> ethtool -k as well. I guess at least that would be the expected way to query
> for such driver capabilities.

+1 on exposing this to user space.  Whether via ethtool -k or a
separate XDP-specific netlink message is mostly a question of whether
we expect the need to expose more complex capabilities than bits.

Thanks!

^ permalink raw reply

* [net-next v2] dummy: extend mtu range for dummy device
From: Zhang Shengju @ 2016-12-07 11:56 UTC (permalink / raw)
  To: jarod, netdev, sergei.shtylyov

After commit 61e84623ace3 ("net: centralize net_device min/max MTU checking"),
the mtu range for dummy device becomes [68, 1500].

This patch extends it to [0, 65535].

v2
 - fix typo in commit message

Signed-off-by: Zhang Shengju <zhangshengju@cmss.chinamobile.com>
---
 drivers/net/dummy.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 69fc840..6421835 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -154,6 +154,9 @@ static void dummy_setup(struct net_device *dev)
 	dev->hw_features |= dev->features;
 	dev->hw_enc_features |= dev->features;
 	eth_hw_addr_random(dev);
+
+	dev->min_mtu = 0;
+	dev->max_mtu = ETH_MAX_MTU;
 }
 
 static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCH 1/1] net: wireless: intersil: fix improper return value
From: Kalle Valo @ 2016-12-07 12:00 UTC (permalink / raw)
  To: Pan Bian; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <1480760572-4444-1-git-send-email-bianpan2016@163.com>

Pan Bian <bianpan2016@163.com> writes:

> Function orinoco_ioctl_commit() returns 0 (indicates success) when the
> call to orinoco_lock() fails. Thus, the return value is inconsistent with
> the execution status. It may be better to return "-EBUSY" when the call 
> to orinoco_lock() fails.
>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188671
>
> Signed-off-by: Pan Bian <bianpan2016@163.com>
> ---
>  drivers/net/wireless/intersil/orinoco/wext.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Please use prefix "orinoco:", more info:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#subject_name

-- 
Kalle Valo

^ permalink raw reply

* [PATCH net-next V3 0/2] net/sched: cls_flower: Add support for matching on dissection flags
From: Or Gerlitz @ 2016-12-07 12:03 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, Jiri Pirko, Roi Dayan, Hadar Har-Zion, Or Gerlitz

Hi Dave,

This series add the UAPI to provide set of flags for matching, where the 
flags provided from user-space are mapped to flow-dissector flags.

The 1st flag allows to match on whether the packet is an
IP fragment and corresponds to the FLOW_DIS_IS_FRAGMENT flag.

Or

v2->v3:
  - replace BIT() with << (kbuild test robot)

v1->v2:
 - dropped the flow dissector patch (#1) as no changes are needed there (Jiri)
 - applied code review comments from Jiri to the flower patch

Or Gerlitz (2):
  net/sched: cls_flower: Add support for matching on flags
  net/mlx5e: Offload TC matching on packets being IP fragments

 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 12 ++++
 include/uapi/linux/pkt_cls.h                    |  7 +++
 net/sched/cls_flower.c                          | 76 +++++++++++++++++++++++++
 3 files changed, 95 insertions(+)

-- 
2.3.7

^ permalink raw reply

* [PATCH net-next V3 2/2] net/mlx5e: Offload TC matching on packets being IP fragments
From: Or Gerlitz @ 2016-12-07 12:03 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, Jiri Pirko, Roi Dayan, Hadar Har-Zion, Or Gerlitz
In-Reply-To: <1481112191-14115-1-git-send-email-ogerlitz@mellanox.com>

Enable offloading of matching on packets being fragments.

Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Paul Blakey <paulb@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index f07ef8c..f8829b5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -31,6 +31,7 @@
  */
 
 #include <net/flow_dissector.h>
+#include <net/sch_generic.h>
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
 #include <net/tc_act/tc_skbedit.h>
@@ -363,7 +364,18 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
 			skb_flow_dissector_target(f->dissector,
 						  FLOW_DISSECTOR_KEY_CONTROL,
 						  f->key);
+
+		struct flow_dissector_key_control *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_CONTROL,
+						  f->mask);
 		addr_type = key->addr_type;
+
+		if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
+			MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
+			MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
+				 key->flags & FLOW_DIS_IS_FRAGMENT);
+		}
 	}
 
 	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
-- 
2.3.7

^ permalink raw reply related

* [PATCH net-next V3 1/2] net/sched: cls_flower: Add support for matching on flags
From: Or Gerlitz @ 2016-12-07 12:03 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, Jiri Pirko, Roi Dayan, Hadar Har-Zion, Or Gerlitz
In-Reply-To: <1481112191-14115-1-git-send-email-ogerlitz@mellanox.com>

Add UAPI to provide set of flags for matching, where the flags
provided from user-space are mapped to flow-dissector flags.

The 1st flag allows to match on whether the packet is an
IP fragment and corresponds to the FLOW_DIS_IS_FRAGMENT flag.

Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Paul Blakey <paulb@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 include/uapi/linux/pkt_cls.h |  7 ++++
 net/sched/cls_flower.c       | 76 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 86786d4..42ee221 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -457,11 +457,18 @@ enum {
 	TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,	/* be16 */
 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT,	/* be16 */
 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,	/* be16 */
+
+	TCA_FLOWER_KEY_FLAGS,		/* be32 */
+	TCA_FLOWER_KEY_FLAGS_MASK,	/* be32 */
 	__TCA_FLOWER_MAX,
 };
 
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
 
+enum {
+	TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
+};
+
 /* Match-all classifier */
 
 enum {
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index c5cea78..0efbeb0 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -383,6 +383,8 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
 	[TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK]	= { .type = NLA_U16 },
 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]	= { .type = NLA_U16 },
 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK]	= { .type = NLA_U16 },
+	[TCA_FLOWER_KEY_FLAGS]		= { .type = NLA_U32 },
+	[TCA_FLOWER_KEY_FLAGS_MASK]	= { .type = NLA_U32 },
 };
 
 static void fl_set_key_val(struct nlattr **tb,
@@ -417,6 +419,39 @@ static void fl_set_key_vlan(struct nlattr **tb,
 	}
 }
 
+static void fl_set_key_flag(u32 flower_key, u32 flower_mask,
+			    u32 *dissector_key, u32 *dissector_mask,
+			    u32 flower_flag_bit, u32 dissector_flag_bit)
+{
+	if (flower_mask & flower_flag_bit) {
+		*dissector_mask |= dissector_flag_bit;
+		if (flower_key & flower_flag_bit)
+			*dissector_key |= dissector_flag_bit;
+	}
+}
+
+static void fl_set_key_flags(struct nlattr **tb,
+			     u32 *flags_key, u32 *flags_mask)
+{
+	u32 key, mask;
+
+	if (!tb[TCA_FLOWER_KEY_FLAGS])
+		return;
+
+	key = be32_to_cpu(nla_get_u32(tb[TCA_FLOWER_KEY_FLAGS]));
+
+	if (!tb[TCA_FLOWER_KEY_FLAGS_MASK])
+		mask = ~0;
+	else
+		mask = be32_to_cpu(nla_get_u32(tb[TCA_FLOWER_KEY_FLAGS_MASK]));
+
+	*flags_key  = 0;
+	*flags_mask = 0;
+
+	fl_set_key_flag(key, mask, flags_key, flags_mask,
+			TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOW_DIS_IS_FRAGMENT);
+}
+
 static int fl_set_key(struct net *net, struct nlattr **tb,
 		      struct fl_flow_key *key, struct fl_flow_key *mask)
 {
@@ -543,6 +578,8 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
 		       &mask->enc_tp.dst, TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,
 		       sizeof(key->enc_tp.dst));
 
+	fl_set_key_flags(tb, &key->control.flags, &mask->control.flags);
+
 	return 0;
 }
 
@@ -877,6 +914,42 @@ static int fl_dump_key_vlan(struct sk_buff *skb,
 	return 0;
 }
 
+static void fl_get_key_flag(u32 dissector_key, u32 dissector_mask,
+			    u32 *flower_key, u32 *flower_mask,
+			    u32 flower_flag_bit, u32 dissector_flag_bit)
+{
+	if (dissector_mask & dissector_flag_bit) {
+		*flower_mask |= flower_flag_bit;
+		if (dissector_key & dissector_flag_bit)
+			*flower_key |= flower_flag_bit;
+	}
+}
+
+static int fl_dump_key_flags(struct sk_buff *skb, u32 flags_key, u32 flags_mask)
+{
+	u32 key, mask;
+	__be32 _key, _mask;
+	int err;
+
+	if (!memchr_inv(&flags_mask, 0, sizeof(flags_mask)))
+		return 0;
+
+	key = 0;
+	mask = 0;
+
+	fl_get_key_flag(flags_key, flags_mask, &key, &mask,
+			TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOW_DIS_IS_FRAGMENT);
+
+	_key = cpu_to_be32(key);
+	_mask = cpu_to_be32(mask);
+
+	err = nla_put(skb, TCA_FLOWER_KEY_FLAGS, 4, &_key);
+	if (err)
+		return err;
+
+	return nla_put(skb, TCA_FLOWER_KEY_FLAGS_MASK, 4, &_mask);
+}
+
 static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
 		   struct sk_buff *skb, struct tcmsg *t)
 {
@@ -1012,6 +1085,9 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
 			    sizeof(key->enc_tp.dst)))
 		goto nla_put_failure;
 
+	if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags))
+		goto nla_put_failure;
+
 	nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags);
 
 	if (tcf_exts_dump(skb, &f->exts))
-- 
2.3.7

^ permalink raw reply related

* [PATCH net-next v5 0/2] net/sched: cls_flower: Support matching on ICMP
From: Simon Horman @ 2016-12-07 12:14 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Tom Herbert, David Miller, netdev, Simon Horman

Hi,

this series adds support for matching on ICMP type and code to cls_flower.

Changes v4->v5:
* Drop all helpers

Changes v3->v4:
* Do not add icmp to struct flow_keys, it is not needed
* Do not test for ICMP protocols in packet in __skb_flow_dissect,
  this is also not needed

Changes v2->v3:
* Add FLOW_DISSECTOR_KEY_ICMP and use separate structure for ICMP

Changes v1->v2:
* Include all dissector helpers in first patch


Simon Horman (2):
  flow dissector: ICMP support
  net/sched: cls_flower: Support matching on ICMP type and code

 include/net/flow_dissector.h | 17 ++++++++++++++
 include/uapi/linux/pkt_cls.h | 10 +++++++++
 net/core/flow_dissector.c    | 31 ++++++++++++++++++++++++++
 net/sched/cls_flower.c       | 53 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 111 insertions(+)

-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply

* [PATCH net-next v5 1/2] flow dissector: ICMP support
From: Simon Horman @ 2016-12-07 12:14 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Tom Herbert, David Miller, netdev, Simon Horman
In-Reply-To: <1481112880-9801-1-git-send-email-simon.horman@netronome.com>

Allow dissection of ICMP(V6) type and code. This should only occur
if a packet is ICMP(V6) and the dissector has FLOW_DISSECTOR_KEY_ICMP set.

There are currently no users of FLOW_DISSECTOR_KEY_ICMP.
A follow-up patch will allow FLOW_DISSECTOR_KEY_ICMP to be used by
the flower classifier.
---
v5
* Drop remaining helpers

v4
* Do not add icmp to struct flow_keys, it is not needed
* Do not test for ICMP protocols in packet in __skb_flow_dissect,
  this is also not needed
* Drop now unnecessary helpers

v3
* Add FLOW_DISSECTOR_KEY_ICMP and use separate structure for ICMP, struct
  flow_dissector_key_icmp, which is a union with struct
  flow_dissector_key_ports in struct flow_keys.
* Drop checks for !ICMP before accessing port field

v2
* Include all helpers in this patch
---
 include/net/flow_dissector.h | 17 +++++++++++++++++
 net/core/flow_dissector.c    | 31 +++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index c4f31666afd2..d896a33e00d4 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -104,6 +104,22 @@ struct flow_dissector_key_ports {
 	};
 };
 
+/**
+ * flow_dissector_key_icmp:
+ *	@ports: type and code of ICMP header
+ *		icmp: ICMP type (high) and code (low)
+ *		type: ICMP type
+ *		code: ICMP code
+ */
+struct flow_dissector_key_icmp {
+	union {
+		__be16 icmp;
+		struct {
+			u8 type;
+			u8 code;
+		};
+	};
+};
 
 /**
  * struct flow_dissector_key_eth_addrs:
@@ -122,6 +138,7 @@ enum flow_dissector_key_id {
 	FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
 	FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
 	FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
+	FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
 	FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
 	FLOW_DISSECTOR_KEY_TIPC_ADDRS, /* struct flow_dissector_key_tipc_addrs */
 	FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_flow_vlan */
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 1eb6f949e5b2..d6447dc10371 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -58,6 +58,28 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
 EXPORT_SYMBOL(skb_flow_dissector_init);
 
 /**
+ * skb_flow_get_be16 - extract be16 entity
+ * @skb: sk_buff to extract from
+ * @poff: offset to extract at
+ * @data: raw buffer pointer to the packet
+ * @hlen: packet header length
+ *
+ * The function will try to retrieve a be32 entity at
+ * offset poff
+ */
+__be16 skb_flow_get_be16(const struct sk_buff *skb, int poff, void *data,
+			 int hlen)
+{
+	__be16 *u, _u;
+
+	u = __skb_header_pointer(skb, poff, sizeof(_u), data, hlen, &_u);
+	if (u)
+		return *u;
+
+	return 0;
+}
+
+/**
  * __skb_flow_get_ports - extract the upper layer ports and return them
  * @skb: sk_buff to extract the ports from
  * @thoff: transport header offset
@@ -117,6 +139,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 	struct flow_dissector_key_basic *key_basic;
 	struct flow_dissector_key_addrs *key_addrs;
 	struct flow_dissector_key_ports *key_ports;
+	struct flow_dissector_key_icmp *key_icmp;
 	struct flow_dissector_key_tags *key_tags;
 	struct flow_dissector_key_vlan *key_vlan;
 	struct flow_dissector_key_keyid *key_keyid;
@@ -546,6 +569,14 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 							data, hlen);
 	}
 
+	if (dissector_uses_key(flow_dissector,
+			       FLOW_DISSECTOR_KEY_ICMP)) {
+		key_icmp = skb_flow_dissector_target(flow_dissector,
+						     FLOW_DISSECTOR_KEY_ICMP,
+						     target_container);
+		key_icmp->icmp = skb_flow_get_be16(skb, nhoff, data, hlen);
+	}
+
 out_good:
 	ret = true;
 
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related

* [PATCH net-next v5 2/2] net/sched: cls_flower: Support matching on ICMP type and code
From: Simon Horman @ 2016-12-07 12:14 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Tom Herbert, David Miller, netdev, Simon Horman
In-Reply-To: <1481112880-9801-1-git-send-email-simon.horman@netronome.com>

Support matching on ICMP type and code.

Example usage:

tc qdisc add dev eth0 ingress

tc filter add dev eth0 protocol ip parent ffff: flower \
	indev eth0 ip_proto icmp type 8 code 0 action drop

tc filter add dev eth0 protocol ipv6 parent ffff: flower \
	indev eth0 ip_proto icmpv6 type 128 code 0 action drop

Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v5
* Open-code checking for icmp protocols rather than using helpers

v4
* No change

v3
* Use separate dissector key FLOW_DISSECTOR_KEY_ICMP
* Use separate structure to hold icmp fields, this does not share
  storage with ports

v2
* Move helpers to another patch
---
 include/uapi/linux/pkt_cls.h | 10 +++++++++
 net/sched/cls_flower.c       | 53 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 1adc0b654996..884c5aa515c4 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -458,6 +458,16 @@ enum {
 	TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,	/* be16 */
 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT,	/* be16 */
 	TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,	/* be16 */
+
+	TCA_FLOWER_KEY_ICMPV4_CODE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
+	TCA_FLOWER_KEY_ICMPV4_TYPE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_CODE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_TYPE,	/* u8 */
+	TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
+
 	__TCA_FLOWER_MAX,
 };
 
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 29a9e6d9f274..f61f11b3194e 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -39,6 +39,7 @@ struct fl_flow_key {
 		struct flow_dissector_key_ipv6_addrs ipv6;
 	};
 	struct flow_dissector_key_ports tp;
+	struct flow_dissector_key_icmp icmp;
 	struct flow_dissector_key_keyid enc_key_id;
 	union {
 		struct flow_dissector_key_ipv4_addrs enc_ipv4;
@@ -386,6 +387,14 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
 	[TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK]	= { .type = NLA_U16 },
 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]	= { .type = NLA_U16 },
 	[TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK]	= { .type = NLA_U16 },
+	[TCA_FLOWER_KEY_ICMPV4_TYPE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV4_TYPE_MASK] = { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV4_CODE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV4_CODE_MASK] = { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_TYPE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_TYPE_MASK] = { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_CODE]	= { .type = NLA_U8 },
+	[TCA_FLOWER_KEY_ICMPV6_CODE_MASK] = { .type = NLA_U8 },
 };
 
 static void fl_set_key_val(struct nlattr **tb,
@@ -502,6 +511,26 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
 		fl_set_key_val(tb, &key->tp.dst, TCA_FLOWER_KEY_SCTP_DST,
 			       &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
 			       sizeof(key->tp.dst));
+	} else if (key->basic.n_proto == htons(ETH_P_IP) &&
+		   key->basic.ip_proto == IPPROTO_ICMP) {
+		fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV4_TYPE,
+			       &mask->icmp.type,
+			       TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
+			       sizeof(key->icmp.type));
+		fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
+			       &mask->icmp.code,
+			       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+			       sizeof(key->icmp.code));
+	} else if (key->basic.n_proto == htons(ETH_P_IPV6) &&
+		   key->basic.ip_proto == IPPROTO_ICMPV6) {
+		fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV6_TYPE,
+			       &mask->icmp.type,
+			       TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
+			       sizeof(key->icmp.type));
+		fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
+			       &mask->icmp.code,
+			       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+			       sizeof(key->icmp.code));
 	}
 
 	if (tb[TCA_FLOWER_KEY_ENC_IPV4_SRC] ||
@@ -612,6 +641,8 @@ static void fl_init_dissector(struct cls_fl_head *head,
 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
 			     FLOW_DISSECTOR_KEY_PORTS, tp);
 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
+			     FLOW_DISSECTOR_KEY_ICMP, icmp);
+	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
 			     FLOW_DISSECTOR_KEY_VLAN, vlan);
 	FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
 			     FLOW_DISSECTOR_KEY_ENC_KEYID, enc_key_id);
@@ -977,6 +1008,28 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
 				  &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
 				  sizeof(key->tp.dst))))
 		goto nla_put_failure;
+	else if (key->basic.n_proto == htons(ETH_P_IP) &&
+		 key->basic.ip_proto == IPPROTO_ICMP &&
+		 (fl_dump_key_val(skb, &key->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV4_TYPE, &mask->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
+				  sizeof(key->icmp.type)) ||
+		  fl_dump_key_val(skb, &key->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV4_CODE, &mask->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+				  sizeof(key->icmp.code))))
+		goto nla_put_failure;
+	else if (key->basic.n_proto == htons(ETH_P_IPV6) &&
+		 key->basic.ip_proto == IPPROTO_ICMPV6 &&
+		 (fl_dump_key_val(skb, &key->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV6_TYPE, &mask->icmp.type,
+				  TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
+				  sizeof(key->icmp.type)) ||
+		  fl_dump_key_val(skb, &key->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV6_CODE, &mask->icmp.code,
+				  TCA_FLOWER_KEY_ICMPV6_CODE_MASK,
+				  sizeof(key->icmp.code))))
+		goto nla_put_failure;
 
 	if (key->enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS &&
 	    (fl_dump_key_val(skb, &key->enc_ipv4.src,
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related

* [PATCH] net: ll_temac: Utilize of_get_mac_address()
From: Tobias Klauser @ 2016-12-07 12:25 UTC (permalink / raw)
  To: netdev; +Cc: michal.simek, soren.brinkmann, Florian Fainelli
In-Reply-To: <20161207122529.29508-1-tklauser@distanz.ch>

Do not open code getting the MAC address exclusively from the
"local-mac-address" property, but instead use of_get_mac_address()
which looks up the MAC address using the 3 typical property names.

Also avoid casting away the const qualifier of the return value by
making temac_init_mac_address() take a const void* address.

Follows commit b34296a9c047 ("net: ethoc: Utilize
of_get_mac_address()").

Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
 drivers/net/ethernet/xilinx/ll_temac_main.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index bcd7b76dde9f..d73da8afe08e 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -37,6 +37,7 @@
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_mdio.h>
+#include <linux/of_net.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/skbuff.h>
@@ -332,7 +333,7 @@ static void temac_do_set_mac_address(struct net_device *ndev)
 	mutex_unlock(&lp->indirect_mutex);
 }
 
-static int temac_init_mac_address(struct net_device *ndev, void *address)
+static int temac_init_mac_address(struct net_device *ndev, const void *address)
 {
 	memcpy(ndev->dev_addr, address, ETH_ALEN);
 	if (!is_valid_ether_addr(ndev->dev_addr))
@@ -982,7 +983,7 @@ static int temac_of_probe(struct platform_device *op)
 	struct net_device *ndev;
 	const void *addr;
 	__be32 *p;
-	int size, rc = 0;
+	int rc = 0;
 
 	/* Init network device structure */
 	ndev = alloc_etherdev(sizeof(*lp));
@@ -1074,13 +1075,13 @@ static int temac_of_probe(struct platform_device *op)
 
 
 	/* Retrieve the MAC address */
-	addr = of_get_property(op->dev.of_node, "local-mac-address", &size);
-	if ((!addr) || (size != 6)) {
+	addr = of_get_mac_address(op->dev.of_node);
+	if (!addr) {
 		dev_err(&op->dev, "could not find MAC address\n");
 		rc = -ENODEV;
 		goto err_iounmap_2;
 	}
-	temac_init_mac_address(ndev, (void *)addr);
+	temac_init_mac_address(ndev, addr);
 
 	rc = temac_mdio_setup(lp, op->dev.of_node);
 	if (rc)
-- 
2.11.0

^ permalink raw reply related

* [PATCH] net: axienet: Utilize of_get_mac_address()
From: Tobias Klauser @ 2016-12-07 12:25 UTC (permalink / raw)
  To: netdev; +Cc: michal.simek, soren.brinkmann, Florian Fainelli

Do not open code getting the MAC address exclusively from the
"local-mac-address" property, but instead use of_get_mac_address()
which looks up the MAC address using the 3 typical property names.

Also avoid casting away the const qualifier of the return value by
making axienet_set_mac_address() take a const void* address.

Follows commit b34296a9c047 ("net: ethoc: Utilize
of_get_mac_address()").

Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index c9c8a3be9f1b..b96e96919e31 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/of_mdio.h>
+#include <linux/of_net.h>
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
@@ -292,7 +293,8 @@ static int axienet_dma_bd_init(struct net_device *ndev)
  * This function is called to initialize the MAC address of the Axi Ethernet
  * core. It writes to the UAW0 and UAW1 registers of the core.
  */
-static void axienet_set_mac_address(struct net_device *ndev, void *address)
+static void axienet_set_mac_address(struct net_device *ndev,
+				    const void *address)
 {
 	struct axienet_local *lp = netdev_priv(ndev);
 
@@ -1456,7 +1458,7 @@ static int axienet_probe(struct platform_device *pdev)
 	struct device_node *np;
 	struct axienet_local *lp;
 	struct net_device *ndev;
-	u8 mac_addr[6];
+	const void *mac_addr;
 	struct resource *ethres, dmares;
 	u32 value;
 
@@ -1567,13 +1569,12 @@ static int axienet_probe(struct platform_device *pdev)
 	}
 
 	/* Retrieve the MAC address */
-	ret = of_property_read_u8_array(pdev->dev.of_node,
-					"local-mac-address", mac_addr, 6);
-	if (ret) {
+	mac_addr = of_get_mac_address(pdev->dev.of_node);
+	if (!mac_addr) {
 		dev_err(&pdev->dev, "could not find MAC address\n");
 		goto free_netdev;
 	}
-	axienet_set_mac_address(ndev, (void *)mac_addr);
+	axienet_set_mac_address(ndev, mac_addr);
 
 	lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
 	lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
-- 
2.11.0

^ permalink raw reply related

* [PATCH] net: axienet: Utilize of_get_mac_address()
From: Tobias Klauser @ 2016-12-07 12:24 UTC (permalink / raw)
  To: netdev; +Cc: anirudh, John.Linn, michal.simek, soren.brinkmann,
	Florian Fainelli

Do not open code getting the MAC address exclusively from the
"local-mac-address" property, but instead use of_get_mac_address()
which looks up the MAC address using the 3 typical property names.

Also avoid casting away the const qualifier of the return value by
making axienet_set_mac_address() take a const void* address.

Follows commit b34296a9c047 ("net: ethoc: Utilize
of_get_mac_address()").

Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index c9c8a3be9f1b..b96e96919e31 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/of_mdio.h>
+#include <linux/of_net.h>
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
@@ -292,7 +293,8 @@ static int axienet_dma_bd_init(struct net_device *ndev)
  * This function is called to initialize the MAC address of the Axi Ethernet
  * core. It writes to the UAW0 and UAW1 registers of the core.
  */
-static void axienet_set_mac_address(struct net_device *ndev, void *address)
+static void axienet_set_mac_address(struct net_device *ndev,
+				    const void *address)
 {
 	struct axienet_local *lp = netdev_priv(ndev);
 
@@ -1456,7 +1458,7 @@ static int axienet_probe(struct platform_device *pdev)
 	struct device_node *np;
 	struct axienet_local *lp;
 	struct net_device *ndev;
-	u8 mac_addr[6];
+	const void *mac_addr;
 	struct resource *ethres, dmares;
 	u32 value;
 
@@ -1567,13 +1569,12 @@ static int axienet_probe(struct platform_device *pdev)
 	}
 
 	/* Retrieve the MAC address */
-	ret = of_property_read_u8_array(pdev->dev.of_node,
-					"local-mac-address", mac_addr, 6);
-	if (ret) {
+	mac_addr = of_get_mac_address(pdev->dev.of_node);
+	if (!mac_addr) {
 		dev_err(&pdev->dev, "could not find MAC address\n");
 		goto free_netdev;
 	}
-	axienet_set_mac_address(ndev, (void *)mac_addr);
+	axienet_set_mac_address(ndev, mac_addr);
 
 	lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
 	lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH net-next v5 1/2] flow dissector: ICMP support
From: Jiri Pirko @ 2016-12-07 12:26 UTC (permalink / raw)
  To: Simon Horman; +Cc: Jiri Pirko, Tom Herbert, David Miller, netdev
In-Reply-To: <1481112880-9801-2-git-send-email-simon.horman@netronome.com>

Wed, Dec 07, 2016 at 01:14:39PM CET, simon.horman@netronome.com wrote:
>Allow dissection of ICMP(V6) type and code. This should only occur
>if a packet is ICMP(V6) and the dissector has FLOW_DISSECTOR_KEY_ICMP set.
>
>There are currently no users of FLOW_DISSECTOR_KEY_ICMP.
>A follow-up patch will allow FLOW_DISSECTOR_KEY_ICMP to be used by
>the flower classifier.


You are missing signedoff line.

^ 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