Netdev List
 help / color / mirror / Atom feed
* Re: iproute: ss truncates abstract unix domain socket embedding null
From: Isaac Boukris @ 2016-10-18 18:46 UTC (permalink / raw)
  To: netdev
In-Reply-To: <CAC-fF8SMUsj8pPJO+VYdRSQAOcwyBpJY1C9V3VEk3zrFS=Jy4Q@mail.gmail.com>

Hi again,

On Sun, Oct 16, 2016 at 11:43 PM, Isaac Boukris <iboukris@gmail.com> wrote:
> Hello,
>
> The unix(7) man page says that null have no special meaning in
> abstract unix domain socket address (the length is specified
> therefore).
>
> However, when such name (embedding null) is used, ss (and netstat)
> will only show up to the first null occurrence (second technically, if
> we count the null prefix).
> e.g. the name "\0/tmp/fo\0.sock" is displayed as: "@/tmp/fo" (whilst
> strace tool shows it as: sun_path=@"/tmp/fo\0.sock").
>
> Would it be more useful if it printed the whole name and escaped the null?
> If so, would '\0' be ok for escaping the null?


Meanwhile, I've got it to escape the null character with with '\0' as suggested.
Can anyone take a look and advise if I'm on the right track? Thanks!


diff --git a/misc/ss.c b/misc/ss.c
index dd77b81..3e41f44 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -2869,7 +2869,7 @@ static int unix_show_sock(const struct
sockaddr_nl *addr, struct nlmsghdr *nlh,
        struct filter *f = (struct filter *)arg;
        struct unix_diag_msg *r = NLMSG_DATA(nlh);
        struct rtattr *tb[UNIX_DIAG_MAX+1];
-       char name[128];
+       char name[128*2];
        struct sockstat stat = { .name = "*", .peer_name = "*" };

        parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr *)(r+1),
@@ -2891,11 +2891,25 @@ static int unix_show_sock(const struct
sockaddr_nl *addr, struct nlmsghdr *nlh,
        }
        if (tb[UNIX_DIAG_NAME]) {
                int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
+               char *real_name = RTA_DATA(tb[UNIX_DIAG_NAME]);

-               memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
-               name[len] = '\0';
-               if (name[0] == '\0')
+               if (real_name[0] == '\0') {
+                       int i, j;
                        name[0] = '@';
+                       for (i = j = 1; i < len; ++i) {
+                               if (real_name[i] == '\0') {
+                                       name[j++] = '\\';
+                                       name[j++] = '0';
+                               }
+                               else
+                                       name[j++] = real_name[i];
+                       }
+                       name[j] = '\0';
+               } else {
+                       memcpy(name, real_name, len);
+                       name[len] = '\0';
+               }
+
                stat.name = &name[0];
                memcpy(stat.local.data, &stat.name, sizeof(stat.name));
        }

^ permalink raw reply related

* Re: [PATCH v3 net-next 8/8] net: qualcomm: add QCA7000 UART driver
From: David Miller @ 2016-10-18 18:30 UTC (permalink / raw)
  To: stefan.wahren; +Cc: gregkh, jslaby, netdev, linux-kernel
In-Reply-To: <1476790054-27174-9-git-send-email-stefan.wahren@i2se.com>

From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Tue, 18 Oct 2016 13:27:34 +0200

> +void
> +qca_tty_receive(struct tty_struct *tty, const unsigned char *cp, char *fp,
> +		int count)
> +{
> +	struct qcauart *qca = tty->disc_data;
> +	struct net_device_stats *n_stats = &qca->net_dev->stats;
> +	int dropped = 0;

Please order local variable declarations from longest to shortest line.

> +netdev_tx_t
> +qcauart_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	struct qcauart *qca = netdev_priv(dev);
> +	struct net_device_stats *n_stats = &dev->stats;
> +	u8 *pos;
> +	u8 pad_len = 0;
> +	int written;

Likewise.

^ permalink raw reply

* Re: [PATCH v3 net-next 5/8] net: qualcomm: move MTU handling to qca_common
From: David Miller @ 2016-10-18 18:29 UTC (permalink / raw)
  To: stefan.wahren; +Cc: gregkh, jslaby, netdev, linux-kernel
In-Reply-To: <1476790054-27174-6-git-send-email-stefan.wahren@i2se.com>

From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Tue, 18 Oct 2016 13:27:31 +0200

> The MTU of the QCA7000 is independent from it's host interface (UART,SPI).
> So move the change_mtu function to qca_common.
> 
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> ---
>  drivers/net/ethernet/qualcomm/qca_common.c | 11 +++++++++++
>  drivers/net/ethernet/qualcomm/qca_common.h |  3 +++
>  drivers/net/ethernet/qualcomm/qca_spi.c    | 13 +------------
>  3 files changed, 15 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/ethernet/qualcomm/qca_common.c b/drivers/net/ethernet/qualcomm/qca_common.c
> index 26453a9..9020c57 100644
> --- a/drivers/net/ethernet/qualcomm/qca_common.c
> +++ b/drivers/net/ethernet/qualcomm/qca_common.c
> @@ -154,3 +154,14 @@ qcafrm_fsm_decode(struct qcafrm_handle *handle, u8 *buf, u16 buf_len, u8 recv_by
>  
>  	return ret;
>  }
> +
> +int
> +qcacmn_netdev_change_mtu(struct net_device *dev, int new_mtu)
> +{
> +	if ((new_mtu < QCAFRM_ETHMINMTU) || (new_mtu > QCAFRM_ETHMAXMTU))
> +		return -EINVAL;

In net-next this limiting is implemented by the driver properly setting
netdev->min_mtu and netdev->max_mtu respectively.

And once you do that, you no longer need this method at all.

^ permalink raw reply

* Re: [PATCH v3 net-next 3/8] net: qualcomm: move qcaspi_tx_cmd to qca_spi.c
From: David Miller @ 2016-10-18 18:28 UTC (permalink / raw)
  To: stefan.wahren; +Cc: gregkh, jslaby, netdev, linux-kernel
In-Reply-To: <1476790054-27174-4-git-send-email-stefan.wahren@i2se.com>

From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Tue, 18 Oct 2016 13:27:29 +0200

> diff --git a/drivers/net/ethernet/qualcomm/qca_7k.h b/drivers/net/ethernet/qualcomm/qca_7k.h
> index 1cad851..b390b1f 100644
> --- a/drivers/net/ethernet/qualcomm/qca_7k.h
> +++ b/drivers/net/ethernet/qualcomm/qca_7k.h
> @@ -67,6 +67,5 @@
>  void qcaspi_spi_error(struct qcaspi *qca);
>  int qcaspi_read_register(struct qcaspi *qca, u16 reg, u16 *result);
>  int qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value);
> -int qcaspi_tx_cmd(struct qcaspi *qca, u16 cmd);
>  
>  #endif /* _QCA_7K_H */
> diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
> index 6e2add9..5bcac62 100644
> --- a/drivers/net/ethernet/qualcomm/qca_spi.c
> +++ b/drivers/net/ethernet/qualcomm/qca_spi.c
> @@ -192,6 +192,30 @@ qcaspi_read_legacy(struct qcaspi *qca, u8 *dst, u32 len)
>  	return len;
>  }
>  
> +int
> +qcaspi_tx_cmd(struct qcaspi *qca, u16 cmd)
> +{

If you do this then you must mark this function 'static'.

^ permalink raw reply

* Re: [PATCH] ipv6: fix signedness of tmp_prefered_lft underflow check
From: David Miller @ 2016-10-18 18:25 UTC (permalink / raw)
  To: jbohac; +Cc: julia.lawall, kuznet, jmorris, yoshfuji, kaber, netdev,
	kbuild-all
In-Reply-To: <20161018150154.4tpivtvxygp7kjpd@dwarf.suse.cz>

From: Jiri Bohac <jbohac@suse.cz>
Date: Tue, 18 Oct 2016 17:01:54 +0200

> Commit 76506a986dc31394fd1f2741db037d29c7e57843 (IPv6: fix
> DESYNC_FACTOR) introduced a buggy check for underflow of
> tmp_prefered_lft. tmp_prefered_lft is unsigned, so the condition
> is always false.
> 
> Signed-off-by: Jiri Bohac <jbohac@suse.cz>
> Reported-by: Julia Lawall <julia.lawall@lip6.fr>
> Fixes: 76506a986dc3 ("IPv6: fix DESYNC_FACTOR")

Does the check make any sense at all?  I'd say just remove it.

^ permalink raw reply

* Re: [PATCH net-next] r8152: add new products of Lenovo
From: David Miller @ 2016-10-18 18:24 UTC (permalink / raw)
  To: hayeswang-Rasf1IRRPZFBDgjK7y7TUQ
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, oliver-GvhC2dPhHPQdnm+yROfE0A,
	nic_swsd-Rasf1IRRPZFBDgjK7y7TUQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1394712342-15778-225-Taiwan-albertk-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>

From: Hayes Wang <hayeswang-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>
Date: Tue, 18 Oct 2016 11:41:48 +0800

> Add the following four products of Lenovo and sort the order of the list.
> 
> 	VID		PID
> 	0x17ef		0x3062
> 	0x17ef		0x3069
> 	0x17ef		0x720c
> 	0x17ef		0x7214
> 
> Signed-off-by: Hayes Wang <hayeswang-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/1] net: vlan: Use sizeof instead of literal number
From: David Miller @ 2016-10-18 18:23 UTC (permalink / raw)
  To: fgao; +Cc: kaber, netdev, gfree.wind
In-Reply-To: <1476751442-12112-1-git-send-email-fgao@ikuai8.com>

From: fgao@ikuai8.com
Date: Tue, 18 Oct 2016 08:44:02 +0800

> From: Gao Feng <fgao@ikuai8.com>
> 
> Use sizeof variable instead of literal number to enhance the readability.
> 
> Signed-off-by: Gao Feng <fgao@ikuai8.com>

Applied.

^ permalink raw reply

* Re: [PATCH 27/28] rocker: fix maybe-uninitialized warning
From: David Miller @ 2016-10-18 18:21 UTC (permalink / raw)
  To: arnd; +Cc: jiri, torvalds, linux-kernel, idosch, dan.carpenter, netdev
In-Reply-To: <20161017221650.1902729-8-arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 18 Oct 2016 00:16:15 +0200

> In some rare configurations, we get a warning about the 'index' variable
> being used without an initialization:
> 
> drivers/net/ethernet/rocker/rocker_ofdpa.c: In function ‘ofdpa_port_fib_ipv4.isra.16.constprop’:
> drivers/net/ethernet/rocker/rocker_ofdpa.c:2425:92: warning: ‘index’ may be used uninitialized in this function [-Wmaybe-uninitialized]
> 
> This is a false positive, the logic is just a bit too complex for gcc
> to follow here. Moving the intialization of 'index' a little further
> down makes it clear to gcc that the function always returns an error
> if it is not initialized.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Applied.

^ permalink raw reply

* Re: [PATCH 21/28] net/hyperv: avoid uninitialized variable
From: David Miller @ 2016-10-18 18:21 UTC (permalink / raw)
  To: arnd
  Cc: kys, haiyangz, torvalds, linux-kernel, vkuznets, stephen, sixiao,
	devel, netdev
In-Reply-To: <20161017221650.1902729-2-arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 18 Oct 2016 00:16:09 +0200

> The hdr_offset variable is only if we deal with a TCP or UDP packet,
> but as the check surrounding its usage tests for skb_is_gso()
> instead, the compiler has no idea if the variable is initialized
> or not at that point:
> 
> drivers/net/hyperv/netvsc_drv.c: In function ‘netvsc_start_xmit’:
> drivers/net/hyperv/netvsc_drv.c:494:42: error: ‘hdr_offset’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
> 
> This adds an additional check for the transport type, which
> tells the compiler that this path cannot happen. Since the
> get_net_transport_info() function should always be inlined
> here, I don't expect this to result in additional runtime
> checks.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Applied.

^ permalink raw reply

* Re: [PATCH 20/28] net: bcm63xx: avoid referencing uninitialized variable
From: David Miller @ 2016-10-18 18:21 UTC (permalink / raw)
  To: arnd
  Cc: torvalds, linux-kernel, tremyfr, f.fainelli,
	bcm-kernel-feedback-list, andrew, netdev, linux-arm-kernel
In-Reply-To: <20161017221650.1902729-1-arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 18 Oct 2016 00:16:08 +0200

> gcc found a reference to an uninitialized variable in the error handling
> of bcm_enet_open, introduced by a recent cleanup:
> 
> drivers/net/ethernet/broadcom/bcm63xx_enet.c: In function 'bcm_enet_open'
> drivers/net/ethernet/broadcom/bcm63xx_enet.c:1129:2: warning: 'phydev' may be used uninitialized in this function [-Wmaybe-uninitialized]
> 
> This makes the use of that variable conditional, so we only reference it
> here after it has been used before. Unlike my normal patches, I have not
> build-tested this one, as I don't currently have mips test in my
> randconfig setup.
> 
> Fixes: 625eb8667d6f ("net: ethernet: broadcom: bcm63xx: use phydev from struct net_device")
> Cc: Philippe Reynes <tremyfr@gmail.com>
> Reported-by: kbuild test robot <fengguang.wu@intel.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Applied.

^ permalink raw reply

* Re: [PATCH net] soreuseport: do not export reuseport_add_sock()
From: David Miller @ 2016-10-18 18:18 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1476739368.5650.60.camel@edumazet-glaptop3.roam.corp.google.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 17 Oct 2016 14:22:48 -0700

> From: Eric Dumazet <edumazet@google.com>
> 
> reuseport_add_sock() is not used from a module,
> no need to export it.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied, thanks Eric.

^ permalink raw reply

* Re: [PATCH 3/3 net] ibmvnic: Update MTU after device initialization
From: David Miller @ 2016-10-18 18:17 UTC (permalink / raw)
  To: tlfalcon; +Cc: netdev
In-Reply-To: <1476736090-13588-3-git-send-email-tlfalcon@linux.vnet.ibm.com>

From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Date: Mon, 17 Oct 2016 15:28:10 -0500

> It is possible for the MTU to be changed during the initialization
> process with the VNIC Server.  Ensure that the net device is updated 
> to reflect the new MTU.
> 
> Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/3 net] ibmvnic: Fix GFP_KERNEL allocation in interrupt context
From: David Miller @ 2016-10-18 18:17 UTC (permalink / raw)
  To: tlfalcon; +Cc: netdev
In-Reply-To: <1476736090-13588-2-git-send-email-tlfalcon@linux.vnet.ibm.com>

From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Date: Mon, 17 Oct 2016 15:28:09 -0500

> Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/3 net v2] ibmvnic: Driver Version 1.0.1
From: David Miller @ 2016-10-18 18:17 UTC (permalink / raw)
  To: tlfalcon; +Cc: netdev
In-Reply-To: <1476737789-17127-1-git-send-email-tlfalcon@linux.vnet.ibm.com>

From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Date: Mon, 17 Oct 2016 15:56:29 -0500

> Increment driver version to reflect features that have
> been added since release.
> 
> Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>

Applied.

^ permalink raw reply

* Re: [PATCH v3 0/4] support smc91x on mainstone and devicetree
From: David Miller @ 2016-10-18 18:14 UTC (permalink / raw)
  To: robert.jarzmik
  Cc: robh+dt, mark.rutland, daniel, haojian.zhuang, jic23, dhowells,
	nico, netdev, devicetree, linux-kernel, linux-arm-kernel,
	linux-am33-list
In-Reply-To: <1476733532-29716-1-git-send-email-robert.jarzmik@free.fr>

From: Robert Jarzmik <robert.jarzmik@free.fr>
Date: Mon, 17 Oct 2016 21:45:28 +0200

> This serie aims at bringing support to mainstone board on a device-tree based
> build, as what is already in place for legacy mainstone.
> 
> The bulk of the mainstone "specific" behavior is that a u16 write doesn't work
> on a address of the form 4*n + 2, while it works on 4*n.
> 
> The legacy workaround was in SMC_outw(), with calls to
> machine_is_mainstone(). These calls don't work with a pxa27x-dt machine type,
> which is used when a generic device-tree pxa27x machine is used to boot the
> mainstone board.
> 
> Therefore, this serie enables the smc91c111 adapter of the mainstone board to
> work on a device-tree build, exaclty as it's been working for years with the
> legacy arch/arm/mach-pxa/mainstone.c definition.
> 
> As a sum up, this extends an existing mechanism to device-tree based pxa platforms.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH v3 net-next 0/7] udp: Flow dissection for tunnels
From: David Miller @ 2016-10-18 18:03 UTC (permalink / raw)
  To: tom; +Cc: netdev, kernel-team
In-Reply-To: <20161018170243.1369807-1-tom@herbertland.com>

From: Tom Herbert <tom@herbertland.com>
Date: Tue, 18 Oct 2016 10:02:36 -0700

> v3:
>   - Fix build issues with modules that call IPv6 functions and
>     CONFIG_INET is not set.
>   - Fix compilation error in init'ing .flow_dissect in IPv6 UDP
>     offload.

Still doesn't build:

net/ipv6/udp_offload.c:208:19: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
   .flow_dissect = udp6_flow_dissect,
                   ^
net/ipv6/udp_offload.c:208:19: note: (near initialization for ‘udpv6_offload.callbacks.flow_dissect’)
cc1: some warnings being treated as errors
scripts/Makefile.build:289: recipe for target 'net/ipv6/udp_offload.o' failed
make[2]: *** [net/ipv6/udp_offload.o] Error 1
make[2]: *** Waiting for unfinished jobs....
scripts/Makefile.build:440: recipe for target 'net/ipv6' failed
make[1]: *** [net/ipv6] Error 2
make[1]: *** Waiting for unfinished jobs....
Makefile:969: recipe for target 'net' failed
make: *** [net] Error 2
make: *** Waiting for unfinished jobs....

The final argument to udp6_flow_dissect() is marked const but that is not what the
method definition wants.

^ permalink raw reply

* Re: [PATCH net-next] ethernet/sfc: use core min/max MTU checking
From: David Miller @ 2016-10-18 17:54 UTC (permalink / raw)
  To: bkenward; +Cc: linux-net-drivers, netdev, jarod
In-Reply-To: <4705a2ea-7734-b549-561c-bc7b6d8710d3@solarflare.com>

From: Bert Kenward <bkenward@solarflare.com>
Date: Tue, 18 Oct 2016 17:47:45 +0100

> Fixes: 61e84623 ("net: centralize net_device min/max MTU checking")
> Signed-off-by: Bert Kenward <bkenward@solarflare.com>

Applied with Fixes tag fixed up to use a 12 character SHA1-ID.

^ permalink raw reply

* Re: [PATCH net v2] bridge: multicast: restore perm router ports on multicast enable
From: David Miller @ 2016-10-18 17:53 UTC (permalink / raw)
  To: nikolay; +Cc: netdev, sashok, roopa, herbert, stephen
In-Reply-To: <1476806988-20557-1-git-send-email-nikolay@cumulusnetworks.com>

From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Date: Tue, 18 Oct 2016 18:09:48 +0200

> Satish reported a problem with the perm multicast router ports not getting
> reenabled after some series of events, in particular if it happens that the
> multicast snooping has been disabled and the port goes to disabled state
> then it will be deleted from the router port list, but if it moves into
> non-disabled state it will not be re-added because the mcast snooping is
> still disabled, and enabling snooping later does nothing.
> 
> Here are the steps to reproduce, setup br0 with snooping enabled and eth1
> added as a perm router (multicast_router = 2):
> 1. $ echo 0 > /sys/class/net/br0/bridge/multicast_snooping
> 2. $ ip l set eth1 down
> ^ This step deletes the interface from the router list
> 3. $ ip l set eth1 up
> ^ This step does not add it again because mcast snooping is disabled
> 4. $ echo 1 > /sys/class/net/br0/bridge/multicast_snooping
> 5. $ bridge -d -s mdb show
> <empty>
> 
> At this point we have mcast enabled and eth1 as a perm router (value = 2)
> but it is not in the router list which is incorrect.
> 
> After this change:
> 1. $ echo 0 > /sys/class/net/br0/bridge/multicast_snooping
> 2. $ ip l set eth1 down
> ^ This step deletes the interface from the router list
> 3. $ ip l set eth1 up
> ^ This step does not add it again because mcast snooping is disabled
> 4. $ echo 1 > /sys/class/net/br0/bridge/multicast_snooping
> 5. $ bridge -d -s mdb show
> router ports on br0: eth1
> 
> Note: we can directly do br_multicast_enable_port for all because the
> querier timer already has checks for the port state and will simply
> expire if it's in blocking/disabled. See the comment added by
> commit 9aa66382163e7 ("bridge: multicast: add a comment to
> br_port_state_selection about blocking state")
> 
> Fixes: 561f1103a2b7 ("bridge: Add multicast_snooping sysfs toggle")
> Reported-by: Satish Ashok <sashok@cumulusnetworks.com>
> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

Applied and queued up for -stable, thanks!

^ permalink raw reply

* [PATCH net-next] bpf: Detect identical PTR_TO_MAP_VALUE_OR_NULL registers
From: Thomas Graf @ 2016-10-18 17:51 UTC (permalink / raw)
  To: davem; +Cc: netdev, alexei.starovoitov, daniel, jbacik

A BPF program is required to check the return register of a
map_elem_lookup() call before accessing memory. The verifier keeps
track of this by converting the type of the result register from
PTR_TO_MAP_VALUE_OR_NULL to PTR_TO_MAP_VALUE after a conditional
jump ensures safety. This check is currently exclusively performed
for the result register 0.

In the event the compiler reorders instructions, BPF_MOV64_REG
instructions may be moved before the conditional jump which causes
them to keep their type PTR_TO_MAP_VALUE_OR_NULL to which the
verifier objects when the register is accessed:

0: (b7) r1 = 10
1: (7b) *(u64 *)(r10 -8) = r1
2: (bf) r2 = r10
3: (07) r2 += -8
4: (18) r1 = 0x59c00000
6: (85) call 1
7: (bf) r4 = r0
8: (15) if r0 == 0x0 goto pc+1
 R0=map_value(ks=8,vs=8) R4=map_value_or_null(ks=8,vs=8) R10=fp
9: (7a) *(u64 *)(r4 +0) = 0
R4 invalid mem access 'map_value_or_null'

This commit extends the verifier to keep track of all identical
PTR_TO_MAP_VALUE_OR_NULL registers after a map_elem_lookup() by
assigning them an ID and then marking them all when the conditional
jump is observed.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Reviewed-by: Josef Bacik <jbacik@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 include/linux/bpf_verifier.h                |  2 +-
 kernel/bpf/verifier.c                       | 61 +++++++++++++++++-------
 tools/testing/selftests/bpf/test_verifier.c | 72 +++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+), 17 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 7035b99..ac5b393 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -23,13 +23,13 @@ struct bpf_reg_state {
 	 * result in a bad access.
 	 */
 	u64 min_value, max_value;
+	u32 id;
 	union {
 		/* valid when type == CONST_IMM | PTR_TO_STACK | UNKNOWN_VALUE */
 		s64 imm;
 
 		/* valid when type == PTR_TO_PACKET* */
 		struct {
-			u32 id;
 			u16 off;
 			u16 range;
 		};
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 99a7e5b..846d7ce 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -212,9 +212,10 @@ static void print_verifier_state(struct bpf_verifier_state *state)
 		else if (t == CONST_PTR_TO_MAP || t == PTR_TO_MAP_VALUE ||
 			 t == PTR_TO_MAP_VALUE_OR_NULL ||
 			 t == PTR_TO_MAP_VALUE_ADJ)
-			verbose("(ks=%d,vs=%d)",
+			verbose("(ks=%d,vs=%d,id=%u)",
 				reg->map_ptr->key_size,
-				reg->map_ptr->value_size);
+				reg->map_ptr->value_size,
+				reg->id);
 		if (reg->min_value != BPF_REGISTER_MIN_RANGE)
 			verbose(",min_value=%llu",
 				(unsigned long long)reg->min_value);
@@ -447,6 +448,7 @@ static void mark_reg_unknown_value(struct bpf_reg_state *regs, u32 regno)
 {
 	BUG_ON(regno >= MAX_BPF_REG);
 	regs[regno].type = UNKNOWN_VALUE;
+	regs[regno].id = 0;
 	regs[regno].imm = 0;
 }
 
@@ -1252,6 +1254,7 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
 			return -EINVAL;
 		}
 		regs[BPF_REG_0].map_ptr = meta.map_ptr;
+		regs[BPF_REG_0].id = ++env->id_gen;
 	} else {
 		verbose("unknown return type %d of func %d\n",
 			fn->ret_type, func_id);
@@ -1644,8 +1647,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
 						insn->src_reg);
 					return -EACCES;
 				}
-				regs[insn->dst_reg].type = UNKNOWN_VALUE;
-				regs[insn->dst_reg].map_ptr = NULL;
+				mark_reg_unknown_value(regs, insn->dst_reg);
 			}
 		} else {
 			/* case: R = imm
@@ -1907,6 +1909,38 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
 	check_reg_overflow(true_reg);
 }
 
+static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
+			 enum bpf_reg_type type)
+{
+	struct bpf_reg_state *reg = &regs[regno];
+
+	if (reg->type == PTR_TO_MAP_VALUE_OR_NULL && reg->id == id) {
+		reg->type = type;
+		if (type == UNKNOWN_VALUE)
+			mark_reg_unknown_value(regs, regno);
+	}
+}
+
+/* The logic is similar to find_good_pkt_pointers(), both could eventually
+ * be folded together at some point.
+ */
+static void mark_map_regs(struct bpf_verifier_state *state, u32 regno,
+			  enum bpf_reg_type type)
+{
+	struct bpf_reg_state *regs = state->regs;
+	int i;
+
+	for (i = 0; i < MAX_BPF_REG; i++)
+		mark_map_reg(regs, i, regs[regno].id, type);
+
+	for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
+		if (state->stack_slot_type[i] != STACK_SPILL)
+			continue;
+		mark_map_reg(state->spilled_regs, i / BPF_REG_SIZE,
+			     regs[regno].id, type);
+	}
+}
+
 static int check_cond_jmp_op(struct bpf_verifier_env *env,
 			     struct bpf_insn *insn, int *insn_idx)
 {
@@ -1994,18 +2028,13 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
 	if (BPF_SRC(insn->code) == BPF_K &&
 	    insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
 	    dst_reg->type == PTR_TO_MAP_VALUE_OR_NULL) {
-		if (opcode == BPF_JEQ) {
-			/* next fallthrough insn can access memory via
-			 * this register
-			 */
-			regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
-			/* branch targer cannot access it, since reg == 0 */
-			mark_reg_unknown_value(other_branch->regs,
-					       insn->dst_reg);
-		} else {
-			other_branch->regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
-			mark_reg_unknown_value(regs, insn->dst_reg);
-		}
+		/* Mark all identical map registers in each branch as either
+		 * safe or unknown depending R == 0 or R != 0 conditional.
+		 */
+		mark_map_regs(this_branch, insn->dst_reg,
+			      opcode == BPF_JEQ ? PTR_TO_MAP_VALUE : UNKNOWN_VALUE);
+		mark_map_regs(other_branch, insn->dst_reg,
+			      opcode == BPF_JEQ ? UNKNOWN_VALUE : PTR_TO_MAP_VALUE);
 	} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
 		   dst_reg->type == PTR_TO_PACKET &&
 		   regs[insn->src_reg].type == PTR_TO_PACKET_END) {
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index ff5df12..0ef8eaf 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -2588,6 +2588,78 @@ static struct bpf_test tests[] = {
 		.result_unpriv = REJECT,
 		.result = REJECT,
 	},
+	{
+		"multiple registers share map_lookup_elem result",
+		.insns = {
+			BPF_MOV64_IMM(BPF_REG_1, 10),
+			BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+			BPF_LD_MAP_FD(BPF_REG_1, 0),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+			BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+			BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+			BPF_EXIT_INSN(),
+		},
+		.fixup_map1 = { 4 },
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SCHED_CLS
+	},
+	{
+		"invalid memory access with multiple map_lookup_elem calls",
+		.insns = {
+			BPF_MOV64_IMM(BPF_REG_1, 10),
+			BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+			BPF_LD_MAP_FD(BPF_REG_1, 0),
+			BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
+			BPF_MOV64_REG(BPF_REG_7, BPF_REG_2),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+			BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+			BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+			BPF_EXIT_INSN(),
+		},
+		.fixup_map1 = { 4 },
+		.result = REJECT,
+		.errstr = "R4 !read_ok",
+		.prog_type = BPF_PROG_TYPE_SCHED_CLS
+	},
+	{
+		"valid indirect map_lookup_elem access with 2nd lookup in branch",
+		.insns = {
+			BPF_MOV64_IMM(BPF_REG_1, 10),
+			BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+			BPF_LD_MAP_FD(BPF_REG_1, 0),
+			BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
+			BPF_MOV64_REG(BPF_REG_7, BPF_REG_2),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_MOV64_IMM(BPF_REG_2, 10),
+			BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0, 3),
+			BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+			BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+			BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+			BPF_EXIT_INSN(),
+		},
+		.fixup_map1 = { 4 },
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SCHED_CLS
+	},
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH net-next] ethernet/sfc: use core min/max MTU checking
From: Sergei Shtylyov @ 2016-10-18 17:21 UTC (permalink / raw)
  To: Bert Kenward, Dave Miller
  Cc: Solarflare Linux Maintainers, netdev, Jarod Wilson
In-Reply-To: <4705a2ea-7734-b549-561c-bc7b6d8710d3@solarflare.com>

On 10/18/2016 07:47 PM, Bert Kenward wrote:

> Fixes: 61e84623 ("net: centralize net_device min/max MTU checking")

    The commit SHA1 should be at least 12 digits here.

> Signed-off-by: Bert Kenward <bkenward@solarflare.com>
[...]

MBR, Sergei

^ permalink raw reply

* Re: [PATCH -next] qed: Remove useless set memory to zero use memset()
From: Sergei Shtylyov @ 2016-10-18 17:20 UTC (permalink / raw)
  To: Wei Yongjun, Yuval Mintz, Ariel Elior
  Cc: Wei Yongjun, everest-linux-l2, netdev
In-Reply-To: <1476806090-4456-1-git-send-email-weiyj.lk@gmail.com>

On 10/18/2016 06:54 PM, Wei Yongjun wrote:

> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> The memory return by kzalloc() has already be set to zero, so

    Returned?

> remove useless memset(0).
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
[...]

MBR, Sergei

^ permalink raw reply

* [PATCH net-next] bnx2x: ethtool -x full support
From: Eric Dumazet @ 2016-10-18 17:08 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Ariel Elior

From: Eric Dumazet <edumazet@google.com>

Implement ethtool -x full support, so that rss key can be fetched
instead of assuming it matches /proc/sys/net/core/netdev_rss_key
content.

We might add "ethtool --rxfh" support later to set a different rss key.

Tested:

lpk51:~# ethtool --show-rxfh eth0
RX flow hash indirection table for eth0 with 4 RX ring(s):
    0:      0     1     2     3     0     1     2     3
    8:      0     1     2     3     0     1     2     3
   16:      0     1     2     3     0     1     2     3
   24:      0     1     2     3     0     1     2     3
   32:      0     1     2     3     0     1     2     3
   40:      0     1     2     3     0     1     2     3
   48:      0     1     2     3     0     1     2     3
   56:      0     1     2     3     0     1     2     3
   64:      0     1     2     3     0     1     2     3
   72:      0     1     2     3     0     1     2     3
   80:      0     1     2     3     0     1     2     3
   88:      0     1     2     3     0     1     2     3
   96:      0     1     2     3     0     1     2     3
  104:      0     1     2     3     0     1     2     3
  112:      0     1     2     3     0     1     2     3
  120:      0     1     2     3     0     1     2     3
RSS hash key:
8b:a9:3a:ff:3e:f8:44:bd:5a:44:b7:b5:6d:e8:2d:f0:f0:72:98:54:03:86:8f:39:a4:42:5a:b3:84:71:5c:4f:1c:18:d6:a3:04:68:85:ac
lpk51:~# cat /proc/sys/net/core/netdev_rss_key
8b:a9:3a:ff:3e:f8:44:bd:5a:44:b7:b5:6d:e8:2d:f0:f0:72:98:54:03:86:8f:39:a4:42:5a:b3:84:71:5c:4f:1c:18:d6:a3:04:68:85:ac:22:1f:50:76:d4:c8:a5:20:7b:61:3c:0c

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ariel Elior <ariel.elior@qlogic.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c     |    2 
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c |   47 ++++++----
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c      |    2 
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h      |    5 -
 4 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 0a9108cd4c45..b979bb7c4ffb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2106,7 +2106,7 @@ int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
 
 	if (config_hash) {
 		/* RSS keys */
-		netdev_rss_key_fill(params.rss_key, T_ETH_RSS_KEY * 4);
+		netdev_rss_key_fill(&rss_obj->rss_key, T_ETH_RSS_KEY * 4);
 		__set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
 	}
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 85a7800bfc12..28bc9479fc74 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -3421,6 +3421,13 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
 	return T_ETH_INDIRECTION_TABLE_SIZE;
 }
 
+static u32 bnx2x_get_rxfh_key_size(struct net_device *dev)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+
+	return (bp->port.pmf || !CHIP_IS_E1x(bp)) ? T_ETH_RSS_KEY * 4 : 0;
+}
+
 static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
 			  u8 *hfunc)
 {
@@ -3430,23 +3437,30 @@ static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
 
 	if (hfunc)
 		*hfunc = ETH_RSS_HASH_TOP;
-	if (!indir)
-		return 0;
 
-	/* Get the current configuration of the RSS indirection table */
-	bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
-
-	/*
-	 * We can't use a memcpy() as an internal storage of an
-	 * indirection table is a u8 array while indir->ring_index
-	 * points to an array of u32.
-	 *
-	 * Indirection table contains the FW Client IDs, so we need to
-	 * align the returned table to the Client ID of the leading RSS
-	 * queue.
-	 */
-	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++)
-		indir[i] = ind_table[i] - bp->fp->cl_id;
+	if (key) {
+		if (bp->port.pmf || !CHIP_IS_E1x(bp))
+			memcpy(key, &bp->rss_conf_obj.rss_key, T_ETH_RSS_KEY * 4);
+		else
+			memset(key, 0, T_ETH_RSS_KEY * 4);
+	}
+
+	if (indir) {
+		/* Get the current configuration of the RSS indirection table */
+		bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
+
+		/*
+		 * We can't use a memcpy() as an internal storage of an
+		 * indirection table is a u8 array while indir->ring_index
+		 * points to an array of u32.
+		 *
+		 * Indirection table contains the FW Client IDs, so we need to
+		 * align the returned table to the Client ID of the leading RSS
+		 * queue.
+		 */
+		for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++)
+			indir[i] = ind_table[i] - bp->fp->cl_id;
+	}
 
 	return 0;
 }
@@ -3628,6 +3642,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.get_ethtool_stats	= bnx2x_get_ethtool_stats,
 	.get_rxnfc		= bnx2x_get_rxnfc,
 	.set_rxnfc		= bnx2x_set_rxnfc,
+	.get_rxfh_key_size	= bnx2x_get_rxfh_key_size,
 	.get_rxfh_indir_size	= bnx2x_get_rxfh_indir_size,
 	.get_rxfh		= bnx2x_get_rxfh,
 	.set_rxfh		= bnx2x_set_rxfh,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index cea6bdcde33f..3b1becc23160 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -4538,7 +4538,7 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
 	/* RSS keys */
 	if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
 		u8 *dst = (u8 *)(data->rss_key) + sizeof(data->rss_key);
-		const u8 *src = (const u8 *)p->rss_key;
+		const u8 *src = (const u8 *)o->rss_key;
 		int i;
 
 		/* Apparently, bnx2x reads this array in reverse order
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 0bf2fd470819..0092991796d3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -744,9 +744,6 @@ struct bnx2x_config_rss_params {
 	/* Indirection table */
 	u8		ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
 
-	/* RSS hash values */
-	u32		rss_key[10];
-
 	/* valid only iff BNX2X_RSS_UPDATE_TOE is set */
 	u16		toe_rss_bitmap;
 };
@@ -760,6 +757,8 @@ struct bnx2x_rss_config_obj {
 	/* Last configured indirection table */
 	u8			ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
 
+	u32     rss_key[T_ETH_RSS_KEY];
+
 	/* flags for enabling 4-tupple hash on UDP */
 	u8			udp_rss_v4;
 	u8			udp_rss_v6;

^ permalink raw reply related

* [PATCH v3 net-next 7/7] fou: Support flow dissection
From: Tom Herbert @ 2016-10-18 17:02 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161018170243.1369807-1-tom@herbertland.com>

This patch performs flow dissection for GUE and FOU. This is an
optional feature on the receiver and is set by FOU_ATTR_DEEP_HASH
netlink configuration. When enable the UDP socket flow_dissect
function is set to fou_flow_dissect or gue_flow_dissect as
appropriate. These functions return FLOW_DIS_RET_IPPROTO and
set ip protocol argument. In the case of GUE the header is
parsed to find the protocol number.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/uapi/linux/fou.h |  1 +
 net/ipv4/fou.c           | 68 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h
index d2947c5..2c837eb 100644
--- a/include/uapi/linux/fou.h
+++ b/include/uapi/linux/fou.h
@@ -15,6 +15,7 @@ enum {
 	FOU_ATTR_IPPROTO,			/* u8 */
 	FOU_ATTR_TYPE,				/* u8 */
 	FOU_ATTR_REMCSUM_NOPARTIAL,		/* flag */
+	FOU_ATTR_DEEP_HASH,			/* flag */
 
 	__FOU_ATTR_MAX,
 };
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index cf50f7e..95ac5a8 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -27,7 +27,8 @@ struct fou {
 	struct rcu_head rcu;
 };
 
-#define FOU_F_REMCSUM_NOPARTIAL BIT(0)
+#define FOU_F_REMCSUM_NOPARTIAL	BIT(0)
+#define FOU_F_DEEP_HASH		BIT(1)
 
 struct fou_cfg {
 	u16 type;
@@ -281,6 +282,16 @@ static int fou_gro_complete(struct sock *sk, struct sk_buff *skb,
 	return err;
 }
 
+static int fou_flow_dissect(struct sock *sk, const struct sk_buff *skb,
+			    void *data, int hlen, int *nhoff, u8 *ip_proto,
+			    __be16 *proto)
+{
+	*ip_proto = fou_from_sock(sk)->protocol;
+	*nhoff += sizeof(struct udphdr);
+
+	return FLOW_DIS_RET_IPPROTO;
+}
+
 static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
 				      struct guehdr *guehdr, void *data,
 				      size_t hdrlen, struct gro_remcsum *grc,
@@ -498,6 +509,48 @@ static int gue_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
 	return err;
 }
 
+static int gue_flow_dissect(struct sock *sk, const struct sk_buff *skb,
+			    void *data, int hlen, int *nhoff, u8 *ip_proto,
+			    __be16 *proto)
+{
+	struct guehdr _hdr, *hdr;
+
+	hdr = __skb_header_pointer(skb, *nhoff + sizeof(struct udphdr),
+				   sizeof(_hdr), data, hlen, &_hdr);
+	if (!hdr)
+		return FLOW_DIS_RET_BAD;
+
+	switch (hdr->version) {
+	case 0: /* Full GUE header present */
+		if (hdr->control)
+			return FLOW_DIS_RET_PASS;
+
+		*nhoff += sizeof(struct udphdr) + sizeof(_hdr) +
+			  (hdr->hlen << 2);
+		*ip_proto = hdr->proto_ctype;
+
+		return FLOW_DIS_RET_IPPROTO;
+	case 1:
+		/* Direct encasulation of IPv4 or IPv6 */
+
+		switch (((struct iphdr *)hdr)->version) {
+		case 4:
+			*nhoff += sizeof(struct udphdr);
+			*ip_proto = IPPROTO_IPIP;
+			return FLOW_DIS_RET_IPPROTO;
+		case 6:
+			*nhoff += sizeof(struct udphdr);
+			*ip_proto = IPPROTO_IPV6;
+			return FLOW_DIS_RET_IPPROTO;
+		default:
+			return FLOW_DIS_RET_PASS;
+		}
+
+	default:
+		return FLOW_DIS_RET_PASS;
+	}
+}
+
 static int fou_add_to_port_list(struct net *net, struct fou *fou)
 {
 	struct fou_net *fn = net_generic(net, fou_net_id);
@@ -568,12 +621,16 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
 		tunnel_cfg.encap_rcv = fou_udp_recv;
 		tunnel_cfg.gro_receive = fou_gro_receive;
 		tunnel_cfg.gro_complete = fou_gro_complete;
+		if (cfg->flags & FOU_F_DEEP_HASH)
+			tunnel_cfg.flow_dissect = fou_flow_dissect;
 		fou->protocol = cfg->protocol;
 		break;
 	case FOU_ENCAP_GUE:
 		tunnel_cfg.encap_rcv = gue_udp_recv;
 		tunnel_cfg.gro_receive = gue_gro_receive;
 		tunnel_cfg.gro_complete = gue_gro_complete;
+		if (cfg->flags & FOU_F_DEEP_HASH)
+			tunnel_cfg.flow_dissect = gue_flow_dissect;
 		break;
 	default:
 		err = -EINVAL;
@@ -637,6 +694,7 @@ static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
 	[FOU_ATTR_IPPROTO] = { .type = NLA_U8, },
 	[FOU_ATTR_TYPE] = { .type = NLA_U8, },
 	[FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, },
+	[FOU_ATTR_DEEP_HASH] = { .type = NLA_FLAG },
 };
 
 static int parse_nl_config(struct genl_info *info,
@@ -677,6 +735,9 @@ static int parse_nl_config(struct genl_info *info,
 	if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL])
 		cfg->flags |= FOU_F_REMCSUM_NOPARTIAL;
 
+	if (info->attrs[FOU_ATTR_DEEP_HASH])
+		cfg->flags |= FOU_F_DEEP_HASH;
+
 	return 0;
 }
 
@@ -717,6 +778,11 @@ static int fou_fill_info(struct fou *fou, struct sk_buff *msg)
 	if (fou->flags & FOU_F_REMCSUM_NOPARTIAL)
 		if (nla_put_flag(msg, FOU_ATTR_REMCSUM_NOPARTIAL))
 			return -1;
+
+	if (fou->flags & FOU_F_DEEP_HASH)
+		if (nla_put_flag(msg, FOU_ATTR_DEEP_HASH))
+			return -1;
+
 	return 0;
 }
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH v3 net-next 6/7] udp: UDP tunnel flow dissection infrastructure
From: Tom Herbert @ 2016-10-18 17:02 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161018170243.1369807-1-tom@herbertland.com>

Add infrastructure to allow UDP tunnels to setup flow dissecion.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/udp_tunnel.h | 5 +++++
 net/ipv4/udp_tunnel.c    | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
index 02c5be0..81d2584 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -69,6 +69,10 @@ typedef struct sk_buff **(*udp_tunnel_gro_receive_t)(struct sock *sk,
 						     struct sk_buff *skb);
 typedef int (*udp_tunnel_gro_complete_t)(struct sock *sk, struct sk_buff *skb,
 					 int nhoff);
+typedef int (*udp_tunnel_flow_dissect_t)(struct sock *sk,
+					 const struct sk_buff *skb,
+					 void *data, int hlen, int *nhoff,
+					 u8 *ip_proto, __be16 *proto);
 
 struct udp_tunnel_sock_cfg {
 	void *sk_user_data;     /* user data used by encap_rcv call back */
@@ -78,6 +82,7 @@ struct udp_tunnel_sock_cfg {
 	udp_tunnel_encap_destroy_t encap_destroy;
 	udp_tunnel_gro_receive_t gro_receive;
 	udp_tunnel_gro_complete_t gro_complete;
+	udp_tunnel_flow_dissect_t flow_dissect;
 };
 
 /* Setup the given (UDP) sock to receive UDP encapsulated packets */
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c
index 58bd39f..4459288 100644
--- a/net/ipv4/udp_tunnel.c
+++ b/net/ipv4/udp_tunnel.c
@@ -72,6 +72,11 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
 	udp_sk(sk)->gro_receive = cfg->gro_receive;
 	udp_sk(sk)->gro_complete = cfg->gro_complete;
 
+	if (cfg->flow_dissect) {
+		udp_sk(sk)->flow_dissect = cfg->flow_dissect;
+		udp_flow_dissect_enable();
+	}
+
 	udp_tunnel_encap_enable(sock);
 }
 EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
-- 
2.9.3

^ permalink raw reply related

* [PATCH v3 net-next 5/7] udp: Add UDP flow dissection functions to IPv4 and IPv6
From: Tom Herbert @ 2016-10-18 17:02 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161018170243.1369807-1-tom@herbertland.com>

Add per protocol offload callbacks for flow_dissect to UDP for
IPv4 and IPv6. The callback functions extract the port number
information and with the packet addresses (given in an argument with
type flow_dissector_key_addrs) it performs a lookup on the UDP
socket. If a socket is found and flow_dissect is set for the
socket then that function is called.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv4/udp_offload.c | 39 +++++++++++++++++++++++++++++++++++++++
 net/ipv6/udp_offload.c | 40 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index f9333c9..c7753ba 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -377,11 +377,50 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
 	return udp_gro_complete(skb, nhoff, udp4_lib_lookup_skb);
 }
 
+/* Assumes rcu lock is held */
+static int udp4_flow_dissect(const struct sk_buff *skb, void *data, int hlen,
+			     int *nhoff, u8 *ip_proto, __be16 *proto,
+			     struct flow_dissector_key_addrs *key_addrs)
+{
+	u16 _ports[2], *ports;
+	struct net *net;
+	struct sock *sk;
+	int dif = -1;
+
+	/* See if there is a flow dissector in the UDP socket */
+
+	if (skb->dev) {
+		net = dev_net(skb->dev);
+		dif = skb->dev->ifindex;
+	} else if (skb->sk) {
+		net = sock_net(skb->sk);
+	} else {
+		return FLOW_DIS_RET_PASS;
+	}
+
+	ports = __skb_header_pointer(skb, *nhoff, sizeof(_ports),
+				     data, hlen, &_ports);
+	if (!ports)
+		return FLOW_DIS_RET_BAD;
+
+	sk = udp4_lib_lookup_noref(net,
+				   key_addrs->v4addrs.src, ports[0],
+				   key_addrs->v4addrs.dst, ports[1],
+				   dif);
+
+	if (sk && udp_sk(sk)->flow_dissect)
+		return udp_sk(sk)->flow_dissect(sk, skb, data, hlen, nhoff,
+						ip_proto, proto);
+	else
+		return FLOW_DIS_RET_PASS;
+}
+
 static const struct net_offload udpv4_offload = {
 	.callbacks = {
 		.gso_segment = udp4_ufo_fragment,
 		.gro_receive  =	udp4_gro_receive,
 		.gro_complete =	udp4_gro_complete,
+		.flow_dissect = udp4_flow_dissect,
 	},
 };
 
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index ac858c4..12d9a92 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -1,5 +1,5 @@
 /*
- *	IPV6 GSO/GRO offload support
+ *	ipv6 gso/gro offload support
  *	Linux INET6 implementation
  *
  *	This program is free software; you can redistribute it and/or
@@ -163,11 +163,49 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff)
 	return udp_gro_complete(skb, nhoff, udp6_lib_lookup_skb);
 }
 
+/* Assumes rcu lock is held */
+static int udp6_flow_dissect(const struct sk_buff *skb, void *data, int hlen,
+			     int *nhoff, u8 *ip_proto, __be16 *proto,
+			     const struct flow_dissector_key_addrs *key_addrs)
+{
+	u16 _ports[2], *ports;
+	struct net *net;
+	struct sock *sk;
+	int dif = -1;
+
+	/* See if there is a flow dissector in the UDP socket */
+
+	if (skb->dev) {
+		net = dev_net(skb->dev);
+		dif = skb->dev->ifindex;
+	} else if (skb->sk) {
+		net = sock_net(skb->sk);
+	} else {
+		return FLOW_DIS_RET_PASS;
+	}
+
+	ports = __skb_header_pointer(skb, *nhoff, sizeof(_ports),
+				     data, hlen, &_ports);
+	if (!ports)
+		return FLOW_DIS_RET_BAD;
+
+	sk = udp6_lib_lookup_noref(net,
+				   &key_addrs->v6addrs.src, ports[0],
+				   &key_addrs->v6addrs.dst, ports[1],
+				   dif);
+
+	if (sk && udp_sk(sk)->flow_dissect)
+		return udp_sk(sk)->flow_dissect(sk, skb, data, hlen, nhoff,
+						ip_proto, proto);
+	return FLOW_DIS_RET_PASS;
+}
+
 static const struct net_offload udpv6_offload = {
 	.callbacks = {
 		.gso_segment	=	udp6_ufo_fragment,
 		.gro_receive	=	udp6_gro_receive,
 		.gro_complete	=	udp6_gro_complete,
+		.flow_dissect	=	udp6_flow_dissect,
 	},
 };
 
-- 
2.9.3

^ permalink raw reply related


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