Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next] bnxt_en: add a dummy definition for bnxt_vf_rep_get_fid()
From: David Miller @ 2017-08-29 16:28 UTC (permalink / raw)
  To: sathya.perla; +Cc: netdev
In-Reply-To: <1503987303-12392-1-git-send-email-sathya.perla@broadcom.com>

From: Sathya Perla <sathya.perla@broadcom.com>
Date: Tue, 29 Aug 2017 11:45:03 +0530

> When bnxt VF-reps are not compiled in (CONFIG_BNXT_SRIOV is off)
> bnxt_tc.c needs a dummy definition of the routine bnxt_vf_rep_get_fid().
> 
> Reported-by: kbuild test robot <fengguang.wu@intel.com>
> Fixes: 2ae7408fedfe ("bnxt_en: bnxt: add TC flower filter offload support")
> Signed-off-by: Sathya Perla <sathya.perla@broadcom.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] staging: irda: update MAINTAINERS
From: David Miller @ 2017-08-29 16:30 UTC (permalink / raw)
  To: gregkh; +Cc: devel, netdev, samuel, joe, linux-kernel
In-Reply-To: <20170829070929.GA15824@kroah.com>

From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: Tue, 29 Aug 2017 09:09:29 +0200

> Now that the IRDA code has moved under drivers/staging/irda/, update the
> MAINTAINERS file with the new location.
> 
> Reported-by: Joe Perches <joe@perches.com>
> Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org

Applied.

^ permalink raw reply

* Re: [PATCH net-next] staging: irda: force to be a kernel module
From: David Miller @ 2017-08-29 16:35 UTC (permalink / raw)
  To: gregkh; +Cc: devel, netdev, samuel, linux-kernel
In-Reply-To: <20170829091417.GA9481@kroah.com>

From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: Tue, 29 Aug 2017 11:14:17 +0200

> Now that the IRDA networking code has moved into drivers/staging/, the
> link order is changed for when it is initialized if built into the
> system.  This can cause a crash when initializing as the netfilter core
> hasn't been initialized yet.
> 
> So force the IRDA code to be built as a module, preventing the crash.
> 
> Reported-by: kernel test robot <fengguang.wu@intel.com>
> Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org

I don't think this is reasonable.

IRDA being built in was broken by moving it to staging, so it's a
regression and we should find a way to fix it.

It's one thing if IRDA on it's own has deteriorated and broken in some
ways over time due to lack of maintainence, it's another to knowingly
do something to it that causes a regression which is what happened
here.

Thanks.

^ permalink raw reply

* Re: pull request (net): ipsec 2017-08-29
From: David Miller @ 2017-08-29 16:37 UTC (permalink / raw)
  To: steffen.klassert; +Cc: herbert, netdev
In-Reply-To: <1504002694-1931-1-git-send-email-steffen.klassert@secunet.com>

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Tue, 29 Aug 2017 12:31:27 +0200

> 1) Fix dst_entry refcount imbalance when using socket policies.
>    From Lorenzo Colitti.
> 
> 2) Fix locking when adding the ESP trailers.
> 
> 3) Fix tailroom calculation for the ESP trailer by using
>    skb_tailroom instead of skb_availroom.
> 
> 4) Fix some info leaks in xfrm_user.
>    From Mathias Krause.
> 
> Please pull or let me know if there are problems.

Pulled, thank you.

^ permalink raw reply

* Re: [PATCH 0/4] irda: move it to drivers/staging so we can delete it
From: David Miller @ 2017-08-29 16:38 UTC (permalink / raw)
  To: geert; +Cc: gregkh, samuel, netdev, linux-kernel, devel
In-Reply-To: <CAMuHMdUefXtqv9bFfgrkbu8NZRXeTD6qR-nErf6TCDz4L+OAWw@mail.gmail.com>

From: Geert Uytterhoeven <geert@linux-m68k.org>
Date: Tue, 29 Aug 2017 12:59:00 +0200

> Hi Greg,
> 
> On Sun, Aug 27, 2017 at 5:03 PM, Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
>> The IRDA code has long been obsolete and broken.  So, to keep people
>> from trying to use it, and to prevent people from having to maintain it,
>> let's move it to drivers/staging/ so that we can delete it entirely from
>> the kernel in a few releases.
> 
> (diving into an early boot crash)
> 
> Have you tried running this? ;-)
> 
> irda_init() and net_dev_init() are both subsys_initcall()s.
> But the former now runs before the latter, leading to:

We must find a way to make the ordering proper again when both are
built-in.

^ permalink raw reply

* Re: [PATCH net-next 0/2] addrlabel: don't use rtnl locking
From: David Miller @ 2017-08-29 16:42 UTC (permalink / raw)
  To: fw; +Cc: netdev
In-Reply-To: <20170829112942.4791-1-fw@strlen.de>

From: Florian Westphal <fw@strlen.de>
Date: Tue, 29 Aug 2017 13:29:40 +0200

> addrlabel doesn't appear to require rtnl lock as the addrlabel
> table uses a spinlock to serialize add/delete operations.
> 
> Also, entries are reference counted so it should be safe
> to call the rtnl ops without the rtnl mutex.

Series applied.

^ permalink raw reply

* Re: [PATCH net-next 1/4] net: Add SRIOV VGT+ support
From: Sabrina Dubroca @ 2017-08-29 16:43 UTC (permalink / raw)
  To: Saeed Mahameed
  Cc: Saeed Mahameed, David S. Miller, Linux Netdev List,
	Eugenia Emantayev, Mohamad Haj Yahia, Hannes Frederic Sowa
In-Reply-To: <CALzJLG8EqGLw66bzBdor629mvJdcN+YOAesTxW8_QYt_teUMiA@mail.gmail.com>

2017-08-29, 13:13:09 +0300, Saeed Mahameed wrote:
> On Mon, Aug 28, 2017 at 6:52 PM, Sabrina Dubroca <sd@queasysnail.net> wrote:
> > 2017-08-27, 14:06:15 +0300, Saeed Mahameed wrote:
> > [...]
> >> +#define VF_VLAN_BITMAP       DIV_ROUND_UP(VF_VLAN_N_VID, sizeof(__u64) * BITS_PER_BYTE)
> >> +struct ifla_vf_vlan_trunk {
> >> +     __u32 vf;
> >> +     __u64 allowed_vlans_8021q_bm[VF_VLAN_BITMAP];
> >> +     __u64 allowed_vlans_8021ad_bm[VF_VLAN_BITMAP];
> >> +};
> >
> > This is huge (1032B). And you put one of these in the netlink message
> > for each VF.  This means that with 51 VF (at least in my environment,
> > where each VF takes 1296B), you're going to overflow the u16 size of a
> > single attribute (IFLA_VFINFO_LIST), and you cannot dump the device
> > anymore. I'm afraid this is going to break existing setups.
> >
> 
> Yes ! We will fix this,
> we are considering to report only a boolean in VFINFO which indecates
> if VGT+ is enable or not
> and provide a new attribute per VF to report only the vlan list of specific VF.

I don't see what this is going to look like. Maybe you can describe
more precisely what you want to add to the netlink message? (otherwise
I'll wait for the patches)

If you add large attributes for each VF, this is still going to break.


Thanks.

-- 
Sabrina

^ permalink raw reply

* Re: [PATCH net-next 0/7] rxrpc: Miscellany
From: David Miller @ 2017-08-29 16:44 UTC (permalink / raw)
  To: dhowells; +Cc: netdev, linux-afs, linux-kernel
In-Reply-To: <150400960745.21371.15455867950162722742.stgit@warthog.procyon.org.uk>

From: David Howells <dhowells@redhat.com>
Date: Tue, 29 Aug 2017 13:26:47 +0100

> 
> Here are a number of patches that make some changes/fixes and add a couple
> of extensions to AF_RXRPC for kernel services to use.  The changes and
> fixes are:
 ...
> Tagged thusly:
> 
> 	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
> 	rxrpc-next-20170829

Pulled, thanks David.

^ permalink raw reply

* Re: [PATCH net-next v2] bridge: fdb add and delete tracepoints
From: Florian Fainelli @ 2017-08-29 16:46 UTC (permalink / raw)
  To: Roopa Prabhu, davem; +Cc: netdev, nikolay, bridge
In-Reply-To: <1503980568-35240-1-git-send-email-roopa@cumulusnetworks.com>

On 08/28/2017 09:22 PM, Roopa Prabhu wrote:
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
> 
> A few useful tracepoints to trace bridge forwarding
> database updates.
> 
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Small nit below, but probably not a candidate for a v3

> ---

> +
> +	TP_printk("dev %s addr %02x:%02x:%02x:%02x:%02x:%02x vid %u nlh_flags %04x ndm_flags = %02x",

Small nit, any particular reason why ndm_flags got a special treatment
with an equal character and not the other?

> +		  __get_str(dev), __entry->addr[0], __entry->addr[1],
> +		  __entry->addr[2], __entry->addr[3], __entry->addr[4],
> +		  __entry->addr[5], __entry->vid,
> +		  __entry->nlh_flags, __entry->ndm_flags)
-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next] Revert "ipv4: make net_protocol const"
From: David Ahern @ 2017-08-29 16:47 UTC (permalink / raw)
  To: Bhumika Goyal; +Cc: netdev, David Miller
In-Reply-To: <CAOH+1jF3G+Yo30Tk=cgnAPfD8UNe+FkkLjC1uGUd9eeG-ce5KA@mail.gmail.com>

On 8/29/17 12:46 AM, Bhumika Goyal wrote:
> I am compile testing them. In this case I did:  make
> net/ipv4/af_inet.o and it compiled. Is this error because of
> typecasting net_protocol inside inet_add_protocol function?

Compile testing is not sufficient. Marking data structures read-only
leaves potential land mines for others to trip over at run-time.

You are making these changes based on a code analysis. Extend the
analysis to elements of the structure. In this case early_demux is the
first element. There are only 9 references to early_demux and cscope
very quickly tells you it can be changed:

7 sysctl_net_ipv4.c proc_configure_early_demux  312 ipprot->early_demux
= enabled ? ipprot->early_demux_handler :
8 sysctl_net_ipv4.c proc_configure_early_demux  318 ip6prot->early_demux
= enabled ? ip6prot->early_demux_handler :

^ permalink raw reply

* [PATCH] net: dsa: make some structures const
From: Bhumika Goyal @ 2017-08-29 16:47 UTC (permalink / raw)
  To: julia.lawall, andrew, vivien.didelot, f.fainelli, netdev,
	linux-kernel
  Cc: Bhumika Goyal

Make these const as they are not modified anywhere.

Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 2 +-
 drivers/net/dsa/qca8k.c   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index bbcb405..8492c9d 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -983,7 +983,7 @@ static int bcm_sf2_core_write64(struct b53_device *dev, u8 page, u8 reg,
 	return 0;
 }
 
-static struct b53_io_ops bcm_sf2_io_ops = {
+static const struct b53_io_ops bcm_sf2_io_ops = {
 	.read8	= bcm_sf2_core_read8,
 	.read16	= bcm_sf2_core_read16,
 	.read32	= bcm_sf2_core_read32,
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 17977f0..5ada7a41 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -250,7 +250,7 @@
 
 };
 
-static struct regmap_access_table qca8k_readable_table = {
+static const struct regmap_access_table qca8k_readable_table = {
 	.yes_ranges = qca8k_readable_ranges,
 	.n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges),
 };
-- 
1.9.1

^ permalink raw reply related

* [patch v1 2/2] mlxsw: core: add support for the external thermal zone setting (by DTS)
From: Vadim Pasternak @ 2017-08-29 18:45 UTC (permalink / raw)
  To: robh+dt, davem; +Cc: jiri, ivecera, devicetree, netdev, Vadim Pasternak
In-Reply-To: <1504032311-195988-1-git-send-email-vadimp@mellanox.com>

It allows:
- thermal zone setting for mlxsw based HW and from DTS file;
- binding ASIC temperature sensor to  cooling devices.
It requires setting of CONFIG_OF.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 107 ++++++++++++++++++++-
 drivers/net/ethernet/mellanox/mlxsw/minimal.c      |   6 ++
 2 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index d866c98..c30783e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/device.h>
+#include <linux/of_platform.h>
 #include <linux/sysfs.h>
 #include <linux/thermal.h>
 #include <linux/err.h>
@@ -44,6 +45,7 @@
 #define MLXSW_THERMAL_MAX_TEMP	110000	/* 110C */
 #define MLXSW_THERMAL_MAX_STATE	10
 #define MLXSW_THERMAL_MAX_DUTY	255
+#define MLXSW_THERMAL_TRIP_ELEM	4
 
 struct mlxsw_thermal_trip {
 	int	type;
@@ -98,6 +100,8 @@ struct mlxsw_thermal {
 	struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
 	struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
 	enum thermal_device_mode mode;
+	int ntrips;
+	bool cooling_external;
 };
 
 static inline u8 mlxsw_state_to_duty(int state)
@@ -121,6 +125,10 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
 		if (thermal->cdevs[i] == cdev)
 			return i;
 
+	/* Allow external cooling binding if theres is no local. */
+	if (thermal->cooling_external)
+		return 0;
+
 	return -ENODEV;
 }
 
@@ -334,6 +342,83 @@ static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
 	.set_cur_state	= mlxsw_thermal_set_cur_state,
 };
 
+#ifdef CONFIG_OF
+static int
+mlxsw_thermal_of_init(struct device *dev, struct mlxsw_thermal *thermal)
+{
+	struct device_node *np = dev->of_node;
+	u32 trip[MLXSW_THERMAL_TRIP_ELEM];
+	struct platform_device *pdev;
+	struct device_node *phandle;
+	struct device_node *gchild;
+	struct device_node *child;
+	int ntrips;
+	int i;
+	int ret;
+
+	/* trips */
+	child = of_get_child_by_name(np, "trips");
+
+	/* No trips provided */
+	if (!child) {
+		of_node_put(child);
+		return -EINVAL;
+	}
+
+	/* Cooling device is optional parameter. If it is not defined, driver
+	 * will try to connect PWM which is owned, if any.
+	 */
+	phandle = of_parse_phandle(child, "cooling-phandle", 0);
+	if (phandle) {
+		pdev = of_find_device_by_node(phandle);
+		of_node_put(phandle);
+		if (!pdev) {
+			ret = -ENODEV;
+			goto put_child;
+		}
+
+		thermal->cooling_external = true;
+	}
+
+	ntrips = of_get_child_count(child);
+	if (ntrips == 0) {
+		/* should have at least one child */
+		ret = 0;
+		goto put_child;
+	}
+
+	i = 0;
+	for_each_child_of_node(child, gchild) {
+		ret = of_property_count_u32_elems(gchild, "trip");
+		if (ret != MLXSW_THERMAL_TRIP_ELEM) {
+			ret = -EINVAL;
+			goto put_child;
+		}
+
+		ret = of_property_read_u32_array(gchild, "trip",
+						 trip, ret);
+		if (ret)
+			goto put_gchild;
+
+		memcpy(&thermal->trips[i++], trip, sizeof(trip));
+	}
+	ret = ntrips;
+
+put_gchild:
+	of_node_put(gchild);
+put_child:
+	of_node_put(child);
+
+	return ret;
+}
+#else
+static int
+mlxsw_thermal_of_init(struct device *dev, struct mlxsw_thermal *thermal)
+{
+	return 0;
+}
+#endif
+
 int mlxsw_thermal_init(struct mlxsw_core *core,
 		       const struct mlxsw_bus_info *bus_info,
 		       struct mlxsw_thermal **p_thermal)
@@ -344,7 +429,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
 	struct mlxsw_thermal *thermal;
 	u16 tacho_active;
 	u8 pwm_active;
-	int err, i;
+	int ntrips;
+	int i;
+	int err;
 
 	thermal = devm_kzalloc(dev, sizeof(*thermal),
 			       GFP_KERNEL);
@@ -353,7 +440,19 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
 
 	thermal->core = core;
 	thermal->bus_info = bus_info;
-	memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
+
+	if (dev->of_node) {
+		ntrips = mlxsw_thermal_of_init(dev, thermal);
+		if (ntrips > 0)
+			thermal->ntrips = ntrips;
+	}
+
+	if (!dev->of_node || ntrips <= 0) {
+		/* Use default if the external setting is not available */
+		memcpy(thermal->trips, default_thermal_trips,
+		       sizeof(thermal->trips));
+		thermal->ntrips = MLXSW_THERMAL_NUM_TRIPS;
+	}
 
 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
 	if (err) {
@@ -398,8 +497,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
 	}
 
 	thermal->tzdev = thermal_zone_device_register("mlxsw",
-						      MLXSW_THERMAL_NUM_TRIPS,
-						      MLXSW_THERMAL_TRIP_MASK,
+						      thermal->ntrips,
+						      BIT(thermal->ntrips) - 1,
 						      thermal,
 						      &mlxsw_thermal_ops,
 						      NULL, 0,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
index 3dd1626..8e3cc13 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
@@ -56,8 +56,14 @@ static const struct i2c_device_id mlxsw_minimal_i2c_id[] = {
 	{ },
 };
 
+static const struct of_device_id mlxsw_minimal_dt_match[] = {
+	{ .compatible = "mellanox,mlxsw_minimal" },
+	{ },
+};
+
 static struct i2c_driver mlxsw_minimal_i2c_driver = {
 	.driver.name = "mlxsw_minimal",
+	.driver.of_match_table = of_match_ptr(mlxsw_minimal_dt_match),
 	.class = I2C_CLASS_HWMON,
 	.id_table = mlxsw_minimal_i2c_id,
 };
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH 0/4] irda: move it to drivers/staging so we can delete it
From: David Miller @ 2017-08-29 16:49 UTC (permalink / raw)
  To: gregkh; +Cc: devel, samuel, netdev, linux-kernel, sbrivio, geert
In-Reply-To: <20170829144850.GC22532@kroah.com>

From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: Tue, 29 Aug 2017 16:48:50 +0200

> On Tue, Aug 29, 2017 at 02:11:39PM +0200, Geert Uytterhoeven wrote:
>> Hi Greg,
>> 
>> On Tue, Aug 29, 2017 at 1:28 PM, Greg Kroah-Hartman
>> <gregkh@linuxfoundation.org> wrote:
>> > On Tue, Aug 29, 2017 at 01:11:31PM +0200, Stefano Brivio wrote:
>> >> On Tue, 29 Aug 2017 12:59:00 +0200
>> >> Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>> >> > On Sun, Aug 27, 2017 at 5:03 PM, Greg Kroah-Hartman
>> >> > <gregkh@linuxfoundation.org> wrote:
>> >> > > The IRDA code has long been obsolete and broken.  So, to keep people
>> >> > > from trying to use it, and to prevent people from having to maintain it,
>> >> > > let's move it to drivers/staging/ so that we can delete it entirely from
>> >> > > the kernel in a few releases.
>> >> >
>> >> > (diving into an early boot crash)
>> >> >
>> >> > Have you tried running this? ;-)
>> >> >
>> >> > irda_init() and net_dev_init() are both subsys_initcall()s.
>> >> > But the former now runs before the latter, leading to:
>> >> >
>> >> > Unable to handle kernel NULL pointer dereference at virtual address 00000004
>> >>
>> >> Should be fixed by https://patchwork.ozlabs.org/patch/807006/
>> >> ("[net-next] staging: irda: force to be a kernel module") I guess...
>> >
>> > Yup, that's the fix for this issue.
>> >
>> > Geert, does that fix the problem for you?
>> 
>> Thanks, that patch fixes the crash, obviously.
>> 
>> It does mean you can no longer have IrDA in a non-modular kernel.
> 
> Given that irda doesn't really work, I doubt anyone is going to care
> about it :)

The initialization with everything built-in worked fine before your
changes.

^ permalink raw reply

* Re: [PATCH net-next 4/7] xdp: separate xdp_redirect tracepoint in error case
From: Alexei Starovoitov @ 2017-08-29 17:02 UTC (permalink / raw)
  To: Jesper Dangaard Brouer; +Cc: netdev, John Fastabend
In-Reply-To: <150401747611.16384.8021135230122395742.stgit@firesoul>

On Tue, Aug 29, 2017 at 04:37:56PM +0200, Jesper Dangaard Brouer wrote:
> There is a need to separate the xdp_redirect tracepoint into two
> tracepoints, for separating the error case from the normal forward
> case.
> 
> Due to the extreme speeds XDP is operating at, loading a tracepoint
> have a measurable impact.  Single core XDP REDIRECT (ethtool tuned
> rx-usecs 25) can do 13.7 Mpps forwarding, but loading a simple
> bpf_prog at the tracepoint (with a return 0) reduce perf to 10.2 Mpps
> (CPU E5-1650 v4 @ 3.60GHz, driver: ixgbe)
> 
> The overhead of loading a bpf-based tracepoint can be calculated to
> cost 25 nanosec ((1/13782002-1/10267937)*10^9 = -24.83 ns).
> 
> Using perf record on the tracepoint event, with a non-matching --filter
> expression, the overhead is much larger. Performance drops to 8.3 Mpps,
> cost 48 nanosec ((1/13782002-1/8312497)*10^9 = -47.74))
> 
> Having a separate tracepoint for err cases, which should be less
> frequent, allow running a continuous monitor for errors while not
> affecting the redirect forward performance (this have also been
> verified by measurements).
> 
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>

thanks for detailed analysis of performance impact of the changes.
looks great to me.
Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply

* Re: [PATCH net-next 7/7] samples/bpf: xdp_monitor tool based on tracepoints
From: Alexei Starovoitov @ 2017-08-29 17:05 UTC (permalink / raw)
  To: Jesper Dangaard Brouer; +Cc: netdev, John Fastabend
In-Reply-To: <150401749138.16384.17129327124102881342.stgit@firesoul>

On Tue, Aug 29, 2017 at 04:38:11PM +0200, Jesper Dangaard Brouer wrote:
> This tool xdp_monitor demonstrate how to use the different xdp_redirect
> tracepoints xdp_redirect{,_map}{,_err} from a BPF program.
> 
> The default mode is to only monitor the error counters, to avoid
> affecting the per packet performance. Tracepoints comes with a base
> overhead of 25 nanosec for an attached bpf_prog, and 48 nanosec for
> using a full perf record (with non-matching filter).  Thus, default
> loading the --stats mode could affect the maximum performance.
> 
> This version of the tool is very simple and count all types of errors
> as one.  It will be natural to extend this later with the different
> types of errors that can occur, which should help users quickly
> identify common mistakes.
> 
> Because the TP_STRUCT was kept in sync all the tracepoints loads the
> same BPF code.  It would also be natural to extend the map version to
> demonstrate how the map information could be used.
> 
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>

Nice. Did you consider using libbbpf (instead of old bpf_load.c hack)
and make full standalone tool out of it? Looks very useful.
Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply

* Re: [PATCH net-next 3/4] net: add NSH header structures and helpers
From: Jiri Benc @ 2017-08-29 17:10 UTC (permalink / raw)
  To: netdev; +Cc: Yi Yang, Eric Garver, Jan Scheurich, Ben Pfaff
In-Reply-To: <4abd24a9ec958622186efacb4e46d709831fbaae.1503948295.git.jbenc@redhat.com>

On Mon, 28 Aug 2017 21:43:23 +0200, Jiri Benc wrote:
> This patch adds NSH header structures and helpers for NSH GSO
> support and Open vSwitch NSH support.
> 
> [1] https://datatracker.ietf.org/doc/draft-ietf-sfc-nsh/

One thing to know before applying this to the kernel: NSH is still a
draft. It's not standardized yet. And the draft evolves, compare the
version from February to the latest one:

https://tools.ietf.org/html/draft-ietf-sfc-nsh-12#section-3.2
https://tools.ietf.org/html/draft-ietf-sfc-nsh-19#section-2.2

There's really no guarantee there won't be further changes.

This patchset by itself is harmless as there's no user and everything
can be changed. We should think through any uAPIs we're going to merge,
though. We don't want to repeat the problems with VXLAN and changed UDP
port.

Again, this patchset is harmless and can be applied even if the draft
changes. Further patches may not be and need to be designed very
carefully.

 Jiri

^ permalink raw reply

* Re: [PATCH] dt-binding: net/phy: fix interrupts description
From: Rob Herring @ 2017-08-29 17:14 UTC (permalink / raw)
  To: Baruch Siach; +Cc: Mark Rutland, David S . Miller, devicetree, netdev
In-Reply-To: <b3756346473feadfeba70ecb71960cad48e66621.1503468660.git.baruch@tkos.co.il>

On Wed, Aug 23, 2017 at 09:11:00AM +0300, Baruch Siach wrote:
> Commit b053dc5a722ea (powerpc: Refactor device tree binding) split the
> Ethernet PHY binding documentation out of the big booting-without-of.txt
> file, leaving a dangling reference to "section 2" in the 'interrupts'
> property description. Drop that reference, and make the description look
> more like the rest.
> 
> While at it, make the example interrupt-parent phandle look more like a
> real world phandle, and use an IRQ_TYPE_ macro for the 'interrupts'
> type.
> 
> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> ---
>  Documentation/devicetree/bindings/net/phy.txt | 10 +++-------
>  1 file changed, 3 insertions(+), 7 deletions(-)

Applied.

Rob

^ permalink raw reply

* Re: [PATCH] dt-binding: net/phy: fix interrupts description
From: Rob Herring @ 2017-08-29 17:15 UTC (permalink / raw)
  To: Baruch Siach
  Cc: David S. Miller, devicetree-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, Mark Rutland
In-Reply-To: <20170828102039.wdylojqcrn2avv2f@tarshish>

On Mon, Aug 28, 2017 at 01:20:39PM +0300, Baruch Siach wrote:
> Hi Dave,
> 
> On Wed, Aug 23, 2017 at 09:11:00AM +0300, Baruch Siach wrote:
> > Commit b053dc5a722ea (powerpc: Refactor device tree binding) split the
> > Ethernet PHY binding documentation out of the big booting-without-of.txt
> > file, leaving a dangling reference to "section 2" in the 'interrupts'
> > property description. Drop that reference, and make the description look
> > more like the rest.
> > 
> > While at it, make the example interrupt-parent phandle look more like a
> > real world phandle, and use an IRQ_TYPE_ macro for the 'interrupts'
> > type.
> 
> This patch is now marked 'Not Applicable' in the netdev patchwork. Why is 
> that? Should it go through some other tree?

If it is only a binding change, I can apply. Though David does often 
pick them up anyway.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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

* [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, Tom Herbert

This patch set adds a new offload type to perform flow dissection for
specific protocols (either by EtherType or by IP protocol). This is
primary useful to crack open UDP encapsulations (like VXLAN, GUE) for
the purposes of parsing the encapsulated packet.

Items in this patch set:
- Constify skb argument to UDP lookup functions
- Create new protocol case in __skb_dissect for ETH_P_TEB. This is based
  on the code in the GRE dissect function and the special handling in
  GRE can now be removed (it sets protocol to ETH_P_TEB and returns so
  goto proto_again is done)
- Add infrastructure for protocol specific flow dissection offload
- Add infrastructure to perform UDP flow dissection. Uses same model of
  GRO where a flow_dissect callback can be associated with a UDP
  socket
- Use the infrastructure to support flow dissection of VXLAN and GUE

Tested:

Forced RPS to call flow dissection for VXLAN, FOU, and GUE. Observed
that inner packet was being properly dissected.

Tom Herbert (6):
  flow_dissector: Move ETH_P_TEB processing to main switch
  udp: Constify skb argument in lookup functions
  flow_dissector: Add protocol specific flow dissection offload
  udp: flow dissector offload
  fou: Support flow dissection
  vxlan: support flow dissect

 drivers/net/vxlan.c          |  50 ++++++++++++
 include/linux/netdevice.h    |   7 ++
 include/linux/udp.h          |   8 ++
 include/net/flow_dissector.h |   9 +++
 include/net/ip.h             |   2 +-
 include/net/sock_reuseport.h |   2 +-
 include/net/udp.h            |  19 +++--
 include/net/udp_tunnel.h     |   8 ++
 net/core/dev.c               |  14 ++++
 net/core/flow_dissector.c    | 176 +++++++++++++++++++++++++++++--------------
 net/core/sock_reuseport.c    |   5 +-
 net/ipv4/fou.c               |  63 ++++++++++++++++
 net/ipv4/route.c             |   4 +-
 net/ipv4/udp.c               |  11 +--
 net/ipv4/udp_offload.c       |  45 +++++++++++
 net/ipv4/udp_tunnel.c        |   1 +
 net/ipv6/udp.c               |  10 +--
 net/ipv6/udp_offload.c       |  13 ++++
 18 files changed, 369 insertions(+), 78 deletions(-)

-- 
2.11.0

^ permalink raw reply

* [PATCH net-next 1/6] flow_dissector: Move ETH_P_TEB processing to main switch
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, Tom Herbert
In-Reply-To: <20170829171942.8974-1-tom@quantonium.net>

Support for processing TEB is currently in GRE flow dissection as a
special case. This can be moved to be a case the main proto switch in
__skb_flow_dissect.
---
 net/core/flow_dissector.c | 44 +++++++++++++++++++++++---------------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index e2eaa1ff948d..12302acdb073 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -288,27 +288,8 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 	if (hdr->flags & GRE_SEQ)
 		offset += sizeof(((struct pptp_gre_header *) 0)->seq);
 
-	if (gre_ver == 0) {
-		if (*p_proto == htons(ETH_P_TEB)) {
-			const struct ethhdr *eth;
-			struct ethhdr _eth;
-
-			eth = __skb_header_pointer(skb, *p_nhoff + offset,
-						   sizeof(_eth),
-						   data, *p_hlen, &_eth);
-			if (!eth)
-				return FLOW_DISSECT_RET_OUT_BAD;
-			*p_proto = eth->h_proto;
-			offset += sizeof(*eth);
-
-			/* Cap headers that we access via pointers at the
-			 * end of the Ethernet header as our maximum alignment
-			 * at that point is only 2 bytes.
-			 */
-			if (NET_IP_ALIGN)
-				*p_hlen = *p_nhoff + offset;
-		}
-	} else { /* version 1, must be PPTP */
+	/* version 1, must be PPTP */
+	if (gre_ver == 1) {
 		u8 _ppp_hdr[PPP_HDRLEN];
 		u8 *ppp_hdr;
 
@@ -573,6 +554,27 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 
 		break;
 	}
+	case htons(ETH_P_TEB): {
+		const struct ethhdr *eth;
+		struct ethhdr _eth;
+
+		eth = __skb_header_pointer(skb, nhoff, sizeof(_eth),
+					   data, hlen, &_eth);
+		if (!eth)
+			goto out_bad;
+
+		proto = eth->h_proto;
+		nhoff += sizeof(*eth);
+
+		/* Cap headers that we access via pointers at the
+		 * end of the Ethernet header as our maximum alignment
+		 * at that point is only 2 bytes.
+		 */
+		if (NET_IP_ALIGN)
+			hlen = nhoff;
+
+		goto proto_again;
+	}
 	case htons(ETH_P_8021AD):
 	case htons(ETH_P_8021Q): {
 		const struct vlan_hdr *vlan;
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 2/6] udp: Constify skb argument in lookup functions
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, Tom Herbert
In-Reply-To: <20170829171942.8974-1-tom@quantonium.net>

For UDP socket lookup functions, and associateed functions that take an
skbuf as argument, declare the skb argument as constant.

One caveat is that reuseport_select_sock can be called from the UDP
lookup functions with an skb argument. This function temporarily
modifies the skbuff data pointer (in bpf_run via a pull/push sequence).
To resolve compiler warning I added a local skbuf declaration that is
not const and assigned to the skb argument with an explicit cast.
---
 include/net/ip.h             |  2 +-
 include/net/sock_reuseport.h |  2 +-
 include/net/udp.h            | 11 ++++++-----
 net/core/sock_reuseport.c    |  5 +++--
 net/ipv4/udp.c               | 11 ++++++-----
 net/ipv6/udp.c               | 10 +++++-----
 6 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index 9896f46cbbf1..8c0d84ffc659 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -79,7 +79,7 @@ struct ipcm_cookie {
 #define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
 
 /* return enslaved device index if relevant */
-static inline int inet_sdif(struct sk_buff *skb)
+static inline int inet_sdif(const struct sk_buff *skb)
 {
 #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
 	if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h
index aecd30308d50..d25352a848d9 100644
--- a/include/net/sock_reuseport.h
+++ b/include/net/sock_reuseport.h
@@ -20,7 +20,7 @@ extern int reuseport_add_sock(struct sock *sk, struct sock *sk2);
 extern void reuseport_detach_sock(struct sock *sk);
 extern struct sock *reuseport_select_sock(struct sock *sk,
 					  u32 hash,
-					  struct sk_buff *skb,
+					  const struct sk_buff *skb,
 					  int hdr_len);
 extern struct bpf_prog *reuseport_attach_prog(struct sock *sk,
 					      struct bpf_prog *prog);
diff --git a/include/net/udp.h b/include/net/udp.h
index 4e5f23fec35e..f3d1de6f0983 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -167,7 +167,7 @@ static inline void udp_csum_pull_header(struct sk_buff *skb)
 	UDP_SKB_CB(skb)->cscov -= sizeof(struct udphdr);
 }
 
-typedef struct sock *(*udp_lookup_t)(struct sk_buff *skb, __be16 sport,
+typedef struct sock *(*udp_lookup_t)(const struct sk_buff *skb, __be16 sport,
 				     __be16 dport);
 
 struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
@@ -288,8 +288,9 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
 			     __be32 daddr, __be16 dport, int dif);
 struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
 			       __be32 daddr, __be16 dport, int dif, int sdif,
-			       struct udp_table *tbl, struct sk_buff *skb);
-struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
+			       struct udp_table *tbl,
+			       const struct sk_buff *skb);
+struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
 				 __be16 sport, __be16 dport);
 struct sock *udp6_lib_lookup(struct net *net,
 			     const struct in6_addr *saddr, __be16 sport,
@@ -299,8 +300,8 @@ struct sock *__udp6_lib_lookup(struct net *net,
 			       const struct in6_addr *saddr, __be16 sport,
 			       const struct in6_addr *daddr, __be16 dport,
 			       int dif, int sdif, struct udp_table *tbl,
-			       struct sk_buff *skb);
-struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
+			       const struct sk_buff *skb);
+struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
 				 __be16 sport, __be16 dport);
 
 /* UDP uses skb->dev_scratch to cache as much information as possible and avoid
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
index eed1ebf7f29d..a17f13b33189 100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -164,9 +164,10 @@ void reuseport_detach_sock(struct sock *sk)
 EXPORT_SYMBOL(reuseport_detach_sock);
 
 static struct sock *run_bpf(struct sock_reuseport *reuse, u16 socks,
-			    struct bpf_prog *prog, struct sk_buff *skb,
+			    struct bpf_prog *prog, const struct sk_buff *_skb,
 			    int hdr_len)
 {
+	struct sk_buff *skb = (struct sk_buff *)_skb; /* Override const */
 	struct sk_buff *nskb = NULL;
 	u32 index;
 
@@ -205,7 +206,7 @@ static struct sock *run_bpf(struct sock_reuseport *reuse, u16 socks,
  */
 struct sock *reuseport_select_sock(struct sock *sk,
 				   u32 hash,
-				   struct sk_buff *skb,
+				   const struct sk_buff *skb,
 				   int hdr_len)
 {
 	struct sock_reuseport *reuse;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index bf6c406bf5e7..a851026ef28b 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -135,7 +135,8 @@ EXPORT_SYMBOL(udp_memory_allocated);
 #define PORTS_PER_CHAIN (MAX_UDP_PORTS / UDP_HTABLE_SIZE_MIN)
 
 /* IPCB reference means this can not be used from early demux */
-static bool udp_lib_exact_dif_match(struct net *net, struct sk_buff *skb)
+static bool udp_lib_exact_dif_match(struct net *net,
+				    const struct sk_buff *skb)
 {
 #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
 	if (!net->ipv4.sysctl_udp_l3mdev_accept &&
@@ -445,7 +446,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
 				     __be32 daddr, unsigned int hnum,
 				     int dif, int sdif, bool exact_dif,
 				     struct udp_hslot *hslot2,
-				     struct sk_buff *skb)
+				     const struct sk_buff *skb)
 {
 	struct sock *sk, *result;
 	int score, badness, matches = 0, reuseport = 0;
@@ -484,7 +485,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
  */
 struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
 		__be16 sport, __be32 daddr, __be16 dport, int dif,
-		int sdif, struct udp_table *udptable, struct sk_buff *skb)
+		int sdif, struct udp_table *udptable, const struct sk_buff *skb)
 {
 	struct sock *sk, *result;
 	unsigned short hnum = ntohs(dport);
@@ -552,7 +553,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
 }
 EXPORT_SYMBOL_GPL(__udp4_lib_lookup);
 
-static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
+static inline struct sock *__udp4_lib_lookup_skb(const struct sk_buff *skb,
 						 __be16 sport, __be16 dport,
 						 struct udp_table *udptable)
 {
@@ -563,7 +564,7 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
 				 inet_sdif(skb), udptable, skb);
 }
 
-struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
+struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
 				 __be16 sport, __be16 dport)
 {
 	return __udp4_lib_lookup_skb(skb, sport, dport, &udp_table);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 976f30391356..e9aa4db3ba53 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -56,7 +56,7 @@
 #include <trace/events/skb.h>
 #include "udp_impl.h"
 
-static bool udp6_lib_exact_dif_match(struct net *net, struct sk_buff *skb)
+static bool udp6_lib_exact_dif_match(struct net *net, const struct sk_buff *skb)
 {
 #if defined(CONFIG_NET_L3_MASTER_DEV)
 	if (!net->ipv4.sysctl_udp_l3mdev_accept &&
@@ -181,7 +181,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
 		const struct in6_addr *saddr, __be16 sport,
 		const struct in6_addr *daddr, unsigned int hnum,
 		int dif, int sdif, bool exact_dif,
-		struct udp_hslot *hslot2, struct sk_buff *skb)
+		struct udp_hslot *hslot2, const struct sk_buff *skb)
 {
 	struct sock *sk, *result;
 	int score, badness, matches = 0, reuseport = 0;
@@ -221,7 +221,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
 			       const struct in6_addr *saddr, __be16 sport,
 			       const struct in6_addr *daddr, __be16 dport,
 			       int dif, int sdif, struct udp_table *udptable,
-			       struct sk_buff *skb)
+			       const struct sk_buff *skb)
 {
 	struct sock *sk, *result;
 	unsigned short hnum = ntohs(dport);
@@ -290,7 +290,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
 }
 EXPORT_SYMBOL_GPL(__udp6_lib_lookup);
 
-static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
+static struct sock *__udp6_lib_lookup_skb(const struct sk_buff *skb,
 					  __be16 sport, __be16 dport,
 					  struct udp_table *udptable)
 {
@@ -301,7 +301,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
 				 inet6_sdif(skb), udptable, skb);
 }
 
-struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
+struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
 				 __be16 sport, __be16 dport)
 {
 	const struct ipv6hdr *iph = ipv6_hdr(skb);
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, Tom Herbert
In-Reply-To: <20170829171942.8974-1-tom@quantonium.net>

Add offload capability for performing protocol specific flow dissection
(either by EtherType or IP protocol).

Specifically:

- Add flow_dissect to offload callbacks
- Move flow_dissect_ret enum to flow_dissector.h, cleanup names and add a
  couple of values
- Create GOTO_BY_RESULT macro to use in the main flow dissector switch to
  simplify handling of functions that return flow_dissect_ret enum
- In __skb_flow_dissect, add default case for switch(proto) as well as
  switch(ip_proto) that looks up and calls protocol specific flow
  dissection
---
 include/linux/netdevice.h    |   7 +++
 include/net/flow_dissector.h |   9 +++
 net/core/dev.c               |  14 +++++
 net/core/flow_dissector.c    | 132 +++++++++++++++++++++++++++++++------------
 net/ipv4/route.c             |   4 +-
 5 files changed, 128 insertions(+), 38 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c5475b37a631..90ccb434e127 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2208,6 +2208,12 @@ struct offload_callbacks {
 	struct sk_buff		**(*gro_receive)(struct sk_buff **head,
 						 struct sk_buff *skb);
 	int			(*gro_complete)(struct sk_buff *skb, int nhoff);
+	enum flow_dissect_ret (*flow_dissect)(const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags);
 };
 
 struct packet_offload {
@@ -3253,6 +3259,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi);
 gro_result_t napi_gro_frags(struct napi_struct *napi);
 struct packet_offload *gro_find_receive_by_type(__be16 type);
 struct packet_offload *gro_find_complete_by_type(__be16 type);
+struct packet_offload *flow_dissect_find_by_type(__be16 type);
 
 static inline void napi_free_frags(struct napi_struct *napi)
 {
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index e2663e900b0a..ad75bbfd1c9c 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -19,6 +19,14 @@ struct flow_dissector_key_control {
 #define FLOW_DIS_FIRST_FRAG	BIT(1)
 #define FLOW_DIS_ENCAPSULATION	BIT(2)
 
+enum flow_dissect_ret {
+	FLOW_DISSECT_RET_OUT_GOOD,
+	FLOW_DISSECT_RET_OUT_BAD,
+	FLOW_DISSECT_RET_PROTO_AGAIN,
+	FLOW_DISSECT_RET_IPPROTO_AGAIN,
+	FLOW_DISSECT_RET_CONTINUE,
+};
+
 /**
  * struct flow_dissector_key_basic:
  * @thoff: Transport header offset
@@ -205,6 +213,7 @@ enum flow_dissector_key_id {
 #define FLOW_DISSECTOR_F_STOP_AT_L3		BIT(1)
 #define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL	BIT(2)
 #define FLOW_DISSECTOR_F_STOP_AT_ENCAP		BIT(3)
+#define FLOW_DISSECTOR_F_STOP_AT_L4		BIT(4)
 
 struct flow_dissector_key {
 	enum flow_dissector_key_id key_id;
diff --git a/net/core/dev.c b/net/core/dev.c
index 270b54754821..22ea8daa930c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4860,6 +4860,20 @@ struct packet_offload *gro_find_receive_by_type(__be16 type)
 }
 EXPORT_SYMBOL(gro_find_receive_by_type);
 
+struct packet_offload *flow_dissect_find_by_type(__be16 type)
+{
+	struct list_head *offload_head = &offload_base;
+	struct packet_offload *ptype;
+
+	list_for_each_entry_rcu(ptype, offload_head, list) {
+		if (ptype->type != type || !ptype->callbacks.flow_dissect)
+			continue;
+		return ptype;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(flow_dissect_find_by_type);
+
 struct packet_offload *gro_find_complete_by_type(__be16 type)
 {
 	struct list_head *offload_head = &offload_base;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 12302acdb073..6a2cf240069a 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -9,6 +9,7 @@
 #include <net/ipv6.h>
 #include <net/gre.h>
 #include <net/pptp.h>
+#include <net/protocol.h>
 #include <linux/igmp.h>
 #include <linux/icmp.h>
 #include <linux/sctp.h>
@@ -115,12 +116,6 @@ __be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
 }
 EXPORT_SYMBOL(__skb_flow_get_ports);
 
-enum flow_dissect_ret {
-	FLOW_DISSECT_RET_OUT_GOOD,
-	FLOW_DISSECT_RET_OUT_BAD,
-	FLOW_DISSECT_RET_OUT_PROTO_AGAIN,
-};
-
 static enum flow_dissect_ret
 __skb_flow_dissect_mpls(const struct sk_buff *skb,
 			struct flow_dissector *flow_dissector,
@@ -322,7 +317,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 	if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
 		return FLOW_DISSECT_RET_OUT_GOOD;
 
-	return FLOW_DISSECT_RET_OUT_PROTO_AGAIN;
+	return FLOW_DISSECT_RET_PROTO_AGAIN;
 }
 
 static void
@@ -383,6 +378,27 @@ __skb_flow_dissect_ipv6(const struct sk_buff *skb,
 	key_ip->ttl = iph->hop_limit;
 }
 
+#define GOTO_BY_RESULT(ret) do {				\
+	switch (ret) {						\
+	case FLOW_DISSECT_RET_OUT_GOOD:				\
+		goto out_good;					\
+	case FLOW_DISSECT_RET_PROTO_AGAIN:			\
+		goto proto_again;				\
+	case FLOW_DISSECT_RET_IPPROTO_AGAIN:			\
+		goto ip_proto_again;				\
+	case FLOW_DISSECT_RET_OUT_BAD:				\
+	default:						\
+		goto out_bad;					\
+	}							\
+} while (0)
+
+#define GOTO_OR_CONT_BY_RESULT(ret) do {			\
+	enum flow_dissect_ret __ret = (ret);			\
+								\
+	if (__ret != FLOW_DISSECT_RET_CONTINUE)			\
+		GOTO_BY_RESULT(__ret);				\
+} while (0)
+
 /**
  * __skb_flow_dissect - extract the flow_keys struct and return it
  * @skb: sk_buff to extract the flow from, can be NULL if the rest are specified
@@ -659,15 +675,10 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 	case htons(ETH_P_MPLS_UC):
 	case htons(ETH_P_MPLS_MC):
 mpls:
-		switch (__skb_flow_dissect_mpls(skb, flow_dissector,
-						target_container, data,
-						nhoff, hlen)) {
-		case FLOW_DISSECT_RET_OUT_GOOD:
-			goto out_good;
-		case FLOW_DISSECT_RET_OUT_BAD:
-		default:
-			goto out_bad;
-		}
+		GOTO_BY_RESULT(__skb_flow_dissect_mpls(skb, flow_dissector,
+						       target_container, data,
+						       nhoff, hlen));
+
 	case htons(ETH_P_FCOE):
 		if ((hlen - nhoff) < FCOE_HEADER_LEN)
 			goto out_bad;
@@ -677,32 +688,44 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 
 	case htons(ETH_P_ARP):
 	case htons(ETH_P_RARP):
-		switch (__skb_flow_dissect_arp(skb, flow_dissector,
-					       target_container, data,
-					       nhoff, hlen)) {
-		case FLOW_DISSECT_RET_OUT_GOOD:
-			goto out_good;
-		case FLOW_DISSECT_RET_OUT_BAD:
-		default:
-			goto out_bad;
+		GOTO_BY_RESULT(__skb_flow_dissect_arp(skb, flow_dissector,
+						      target_container, data,
+						      nhoff, hlen));
+
+	default: {
+		struct packet_offload *ptype;
+		enum flow_dissect_ret ret;
+
+		rcu_read_lock();
+
+		ptype = flow_dissect_find_by_type(proto);
+
+		if (ptype) {
+			ret = ptype->callbacks.flow_dissect(skb, key_control,
+						flow_dissector,
+						target_container,
+						data, &proto, &ip_proto, &nhoff,
+						&hlen, flags);
+			rcu_read_unlock();
+
+			GOTO_BY_RESULT(ret);
+		} else {
+			rcu_read_unlock();
 		}
-	default:
+
 		goto out_bad;
 	}
+	}
 
 ip_proto_again:
 	switch (ip_proto) {
 	case IPPROTO_GRE:
-		switch (__skb_flow_dissect_gre(skb, key_control, flow_dissector,
-					       target_container, data,
-					       &proto, &nhoff, &hlen, flags)) {
-		case FLOW_DISSECT_RET_OUT_GOOD:
-			goto out_good;
-		case FLOW_DISSECT_RET_OUT_BAD:
-			goto out_bad;
-		case FLOW_DISSECT_RET_OUT_PROTO_AGAIN:
-			goto proto_again;
-		}
+		GOTO_BY_RESULT(__skb_flow_dissect_gre(skb, key_control,
+						      flow_dissector,
+						      target_container, data,
+						      &proto, &nhoff, &hlen,
+						      flags));
+
 	case NEXTHDR_HOP:
 	case NEXTHDR_ROUTING:
 	case NEXTHDR_DEST: {
@@ -768,9 +791,43 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 		__skb_flow_dissect_tcp(skb, flow_dissector, target_container,
 				       data, nhoff, hlen);
 		break;
-	default:
+	default: {
+		const struct net_offload *ops = NULL;
+
+		if (flags & FLOW_DISSECTOR_F_STOP_AT_L4)
+			break;
+
+		rcu_read_lock();
+
+		switch (proto) {
+		case htons(ETH_P_IP):
+			ops = rcu_dereference(inet_offloads[ip_proto]);
+			break;
+		case htons(ETH_P_IPV6):
+			ops = rcu_dereference(inet6_offloads[ip_proto]);
+			break;
+		default:
+			break;
+		}
+
+		if (ops && ops->callbacks.flow_dissect) {
+			enum flow_dissect_ret ret;
+
+			ret = ops->callbacks.flow_dissect(skb, key_control,
+						flow_dissector,
+						target_container,
+						data, &proto, &ip_proto, &nhoff,
+						&hlen, flags);
+			rcu_read_unlock();
+
+			GOTO_OR_CONT_BY_RESULT(ret);
+		} else {
+			rcu_read_unlock();
+		}
+
 		break;
 	}
+	}
 
 	if (dissector_uses_key(flow_dissector,
 			       FLOW_DISSECTOR_KEY_PORTS)) {
@@ -935,7 +992,8 @@ static inline u32 ___skb_get_hash(const struct sk_buff *skb,
 				  struct flow_keys *keys, u32 keyval)
 {
 	skb_flow_dissect_flow_keys(skb, keys,
-				   FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
+				   FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL |
+				   FLOW_DISSECTOR_F_STOP_AT_L4);
 
 	return __flow_hash_from_keys(keys, keyval);
 }
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 94d4cd2d5ea4..85f12b8e0b7f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1811,7 +1811,9 @@ int fib_multipath_hash(const struct fib_info *fi, const struct flowi4 *fl4,
 	case 1:
 		/* skb is currently provided only when forwarding */
 		if (skb) {
-			unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
+			unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP |
+					    FLOW_DISSECTOR_F_STOP_AT_L4;
+;
 			struct flow_keys keys;
 
 			/* short-circuit if we already have L4 hash present */
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 4/6] udp: flow dissector offload
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, Tom Herbert
In-Reply-To: <20170829171942.8974-1-tom@quantonium.net>

Add support to perform UDP specific flow dissection. This is
primarily intended for dissecting encapsulated packets in UDP
encapsulation.

This patch adds a flow_dissect offload for UDP4 and UDP6. The backend
function performs a socket lookup and calls the flow_dissect function
if a socket is found.
---
 include/linux/udp.h      |  8 ++++++++
 include/net/udp.h        |  8 ++++++++
 include/net/udp_tunnel.h |  8 ++++++++
 net/ipv4/udp_offload.c   | 45 +++++++++++++++++++++++++++++++++++++++++++++
 net/ipv4/udp_tunnel.c    |  1 +
 net/ipv6/udp_offload.c   | 13 +++++++++++++
 6 files changed, 83 insertions(+)

diff --git a/include/linux/udp.h b/include/linux/udp.h
index eaea63bc79bb..2e90b189ef6a 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -79,6 +79,14 @@ struct udp_sock {
 	int			(*gro_complete)(struct sock *sk,
 						struct sk_buff *skb,
 						int nhoff);
+	/* Flow dissector function for a UDP socket */
+	enum flow_dissect_ret (*flow_dissect)(struct sock *sk,
+			const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags);
 
 	/* udp_recvmsg try to use this before splicing sk_receive_queue */
 	struct sk_buff_head	reader_queue ____cacheline_aligned_in_smp;
diff --git a/include/net/udp.h b/include/net/udp.h
index f3d1de6f0983..499e4faf8b14 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -174,6 +174,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
 				 struct udphdr *uh, udp_lookup_t lookup);
 int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup);
 
+enum flow_dissect_ret udp_flow_dissect(const struct sk_buff *skb,
+			udp_lookup_t lookup,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags);
+
 static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)
 {
 	struct udphdr *uh;
diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
index 10cce0dd4450..b7102e0f41a9 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -69,6 +69,13 @@ 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 enum flow_dissect_ret (*udp_tunnel_flow_dissect_t)(struct sock *sk,
+			const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags);
 
 struct udp_tunnel_sock_cfg {
 	void *sk_user_data;     /* user data used by encap_rcv call back */
@@ -78,6 +85,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_offload.c b/net/ipv4/udp_offload.c
index 97658bfc1b58..7f0a7ed4a6f7 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -328,11 +328,56 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
 	return udp_gro_complete(skb, nhoff, udp4_lib_lookup_skb);
 }
 
+enum flow_dissect_ret udp_flow_dissect(const struct sk_buff *skb,
+			udp_lookup_t lookup,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags)
+{
+	enum flow_dissect_ret ret = FLOW_DISSECT_RET_CONTINUE;
+	struct udphdr *uh, _uh;
+	struct sock *sk;
+
+	uh = __skb_header_pointer(skb, *p_nhoff, sizeof(_uh), data,
+				  *p_hlen, &_uh);
+	if (!uh)
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	rcu_read_lock();
+
+	sk = (*lookup)(skb, uh->source, uh->dest);
+
+	if (sk && udp_sk(sk)->flow_dissect)
+		ret = udp_sk(sk)->flow_dissect(sk, skb, key_control,
+					       flow_dissector, target_container,
+					       data, p_proto, p_ip_proto,
+					       p_nhoff, p_hlen, flags);
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(udp_flow_dissect);
+
+static enum flow_dissect_ret udp4_flow_dissect(const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags)
+{
+	return udp_flow_dissect(skb, udp4_lib_lookup_skb, key_control,
+				flow_dissector, target_container, data,
+				p_proto, p_ip_proto, p_nhoff, p_hlen, flags);
+}
+
 static const struct net_offload udpv4_offload = {
 	.callbacks = {
 		.gso_segment = udp4_tunnel_segment,
 		.gro_receive  =	udp4_gro_receive,
 		.gro_complete =	udp4_gro_complete,
+		.flow_dissect = udp4_flow_dissect,
 	},
 };
 
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c
index 6539ff15e9a3..a4eec2a044d2 100644
--- a/net/ipv4/udp_tunnel.c
+++ b/net/ipv4/udp_tunnel.c
@@ -71,6 +71,7 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
 	udp_sk(sk)->encap_destroy = cfg->encap_destroy;
 	udp_sk(sk)->gro_receive = cfg->gro_receive;
 	udp_sk(sk)->gro_complete = cfg->gro_complete;
+	udp_sk(sk)->flow_dissect = cfg->flow_dissect;
 
 	udp_tunnel_encap_enable(sock);
 }
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 455fd4e39333..99ade504eaf7 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -73,11 +73,24 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff)
 	return udp_gro_complete(skb, nhoff, udp6_lib_lookup_skb);
 }
 
+static enum flow_dissect_ret udp6_flow_dissect(const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags)
+{
+	return udp_flow_dissect(skb, udp6_lib_lookup_skb, key_control,
+				flow_dissector, target_container, data,
+				p_proto, p_ip_proto, p_nhoff, p_hlen, flags);
+}
+
 static const struct net_offload udpv6_offload = {
 	.callbacks = {
 		.gso_segment	=	udp6_tunnel_segment,
 		.gro_receive	=	udp6_gro_receive,
 		.gro_complete	=	udp6_gro_complete,
+		.flow_dissect	=	udp6_flow_dissect,
 	},
 };
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 5/6] fou: Support flow dissection
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, Tom Herbert
In-Reply-To: <20170829171942.8974-1-tom@quantonium.net>

Populate offload flow_dissect callabck appropriately for fou and gue.
---
 net/ipv4/fou.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 1540db65241a..a831dd49fb28 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -282,6 +282,20 @@ static int fou_gro_complete(struct sock *sk, struct sk_buff *skb,
 	return err;
 }
 
+static enum flow_dissect_ret fou_flow_dissect(struct sock *sk,
+			const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags)
+{
+	*p_ip_proto = fou_from_sock(sk)->protocol;
+	*p_nhoff += sizeof(struct udphdr);
+
+	return FLOW_DISSECT_RET_IPPROTO_AGAIN;
+}
+
 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,
@@ -500,6 +514,53 @@ static int gue_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
 	return err;
 }
 
+static enum flow_dissect_ret gue_flow_dissect(struct sock *sk,
+			const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags)
+{
+	struct guehdr *guehdr, _guehdr;
+
+	guehdr = __skb_header_pointer(skb, *p_nhoff + sizeof(struct udphdr),
+				      sizeof(_guehdr), data, *p_hlen, &_guehdr);
+	if (!guehdr)
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	switch (guehdr->version) {
+	case 0:
+		if (unlikely(guehdr->control))
+			return FLOW_DISSECT_RET_CONTINUE;
+
+		*p_ip_proto = guehdr->proto_ctype;
+		*p_nhoff += sizeof(struct udphdr) +
+		    sizeof(*guehdr) + (guehdr->hlen << 2);
+
+		break;
+	case 1:
+		switch (((struct iphdr *)guehdr)->version) {
+		case 4:
+			*p_ip_proto = IPPROTO_IPIP;
+			break;
+		case 6:
+			*p_ip_proto = IPPROTO_IPV6;
+			break;
+		default:
+			return FLOW_DISSECT_RET_CONTINUE;
+		}
+
+		*p_nhoff += sizeof(struct udphdr);
+
+		break;
+	default:
+		return FLOW_DISSECT_RET_CONTINUE;
+	}
+
+	return FLOW_DISSECT_RET_IPPROTO_AGAIN;
+}
+
 static int fou_add_to_port_list(struct net *net, struct fou *fou)
 {
 	struct fou_net *fn = net_generic(net, fou_net_id);
@@ -570,12 +631,14 @@ 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;
+		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;
+		tunnel_cfg.flow_dissect = gue_flow_dissect;
 		break;
 	default:
 		err = -EINVAL;
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 6/6] vxlan: support flow dissect
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, Tom Herbert
In-Reply-To: <20170829171942.8974-1-tom@quantonium.net>

Populate offload flow_dissect callback appropriately for VXLAN and
VXLAN-GPE.
---
 drivers/net/vxlan.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index ae3a1da703c2..41e50de40af4 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1336,6 +1336,55 @@ static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph,
 	return err <= 1;
 }
 
+static enum flow_dissect_ret vxlan_flow_dissect(struct sock *sk,
+			const struct sk_buff *skb,
+			struct flow_dissector_key_control *key_control,
+			struct flow_dissector *flow_dissector,
+			void *target_container, void *data,
+			__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+			int *p_hlen, unsigned int flags)
+{
+	__be16 protocol = htons(ETH_P_TEB);
+	struct vxlanhdr *vhdr, _vhdr;
+	struct vxlan_sock *vs;
+
+	vhdr = __skb_header_pointer(skb, *p_nhoff + sizeof(struct udphdr),
+				    sizeof(_vhdr), data, *p_hlen, &_vhdr);
+	if (!vhdr)
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	vs = rcu_dereference_sk_user_data(sk);
+	if (!vs)
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	if (vs->flags & VXLAN_F_GPE) {
+		struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vhdr;
+
+		/* Need to have Next Protocol set for interfaces in GPE mode. */
+		if (gpe->version != 0 || !gpe->np_applied || gpe->oam_flag)
+			return FLOW_DISSECT_RET_CONTINUE;
+
+		switch (gpe->next_protocol) {
+		case VXLAN_GPE_NP_IPV4:
+			protocol = htons(ETH_P_IP);
+			break;
+		case VXLAN_GPE_NP_IPV6:
+			protocol = htons(ETH_P_IPV6);
+			break;
+		case VXLAN_GPE_NP_ETHERNET:
+			protocol = htons(ETH_P_TEB);
+			break;
+		default:
+			return FLOW_DISSECT_RET_CONTINUE;
+		}
+	}
+
+	*p_nhoff += sizeof(struct udphdr) + sizeof(_vhdr);
+	*p_proto = protocol;
+
+	return FLOW_DISSECT_RET_PROTO_AGAIN;
+}
+
 /* Callback from net/ipv4/udp.c to receive packets */
 static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
 {
@@ -2864,6 +2913,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
 	tunnel_cfg.encap_destroy = NULL;
 	tunnel_cfg.gro_receive = vxlan_gro_receive;
 	tunnel_cfg.gro_complete = vxlan_gro_complete;
+	tunnel_cfg.flow_dissect = vxlan_flow_dissect;
 
 	setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
 
-- 
2.11.0

^ 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