* Re: [PATCH net-next 00/15] ethernet: use core min/max MTU checking
From: David Miller @ 2016-10-18 15:34 UTC (permalink / raw)
To: jarod; +Cc: linux-kernel, netdev
In-Reply-To: <20161017195417.48259-1-jarod@redhat.com>
From: Jarod Wilson <jarod@redhat.com>
Date: Mon, 17 Oct 2016 15:54:02 -0400
> Now that the network stack core min/max MTU checking infrastructure is in
> place, time to start making drivers use it. We'll start with the easiest
> ones, the ethernet drivers, split roughly by vendor, with a catch-all
> patch at the end.
>
> For the most part, every patch does the same essential thing: removes the
> MTU range checking from the drivers' ndo_change_mtu function, puts those
> ranges into the core net_device min_mtu and max_mtu fields, and where
> possible, removes ndo_change_mtu functions entirely.
>
> These patches have all been built through the 0-day build infrastructure
> provided by Intel, on top of net-next as of October 17.
Series applied, thanks Jarod.
^ permalink raw reply
* Re: [PATCH net-next 0/2] Move to BPF selftests
From: David Miller @ 2016-10-18 15:36 UTC (permalink / raw)
To: daniel; +Cc: alexei.starovoitov, netdev
In-Reply-To: <cover.1476705709.git.daniel@iogearbox.net>
From: Daniel Borkmann <daniel@iogearbox.net>
Date: Mon, 17 Oct 2016 14:28:34 +0200
> This set improves the test_verifier and test_maps suite and moves
> it over to a new BPF selftest directory, so we can keep improving
> it under kernel selftest umbrella. This also integrates a test
> script for checking test_bpf.ko under various JIT options.
Series applied, thanks Daniel.
^ permalink raw reply
* Re: [PATCH v3 net-next 00/11] net: Fix netdev adjacency tracking
From: David Miller @ 2016-10-18 15:46 UTC (permalink / raw)
To: dsa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR
Cc: jiri-VPRAkNaXOzVWk0Htik3J/w, netdev-u79uwXL29TY76Z2rM5mHXA,
dledford-H+wXaHxf7aLQT0dZR+AlfA,
sean.hefty-ral2JQCrhuEAvxtiuMwx3w,
hal.rosenstock-Re5JQEeQqe8AvxtiuMwx3w,
linux-rdma-u79uwXL29TY76Z2rM5mHXA,
j.vosburgh-Re5JQEeQqe8AvxtiuMwx3w, vfalico-Re5JQEeQqe8AvxtiuMwx3w,
andy-QlMahl40kYEqcZcGjlUOXw,
jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
intel-wired-lan-qjLDD68F18P21nG7glBr7A
In-Reply-To: <1476756953-30923-1-git-send-email-dsa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org>
From: David Ahern <dsa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org>
Date: Mon, 17 Oct 2016 19:15:42 -0700
> The netdev adjacency tracking is failing to create proper dependencies
> for some topologies. For example this topology
...
> hits 1 of 2 problems depending on the order of enslavement. The base set of
> commands for both cases:
...
> Case 1 enslave macvlan to the vrf before enslaving the bond to the bridge:
...
> Attempts to delete the VRF:
> ip link delete myvrf
>
> trigger the BUG in __netdev_adjacent_dev_remove:
...
> When the BUG is converted to a WARN_ON it shows 4 missing adjacencies:
> eth3 - myvrf, mvrf - eth3, bond1 - myvrf and myvrf - bond1
>
> All of those are because the __netdev_upper_dev_link function does not
> properly link macvlan lower devices to myvrf when it is enslaved.
...
> Rather than try to maintain a linked list of all upper and lower devices
> per netdevice, only track the direct neighbors. The remaining stack can
> be determined by recursively walking the neighbors.
>
> The existing netdev_for_each_all_upper_dev_rcu,
> netdev_for_each_all_lower_dev and netdev_for_each_all_lower_dev_rcu macros
> are replaced with APIs that walk the upper and lower device lists. The
> new APIs take a callback function and a data arg that is passed to the
> callback for each device in the list. Drivers using the old macros are
> converted in separate patches to make it easier on reviewers. It is an
> API conversion only; no functional change is intended.
Series applied, but the recursion is disappointing.
If we run into problems due to kernel stack depth because of this with
some configurations (reasonable or not, if we allow it then it can't
crash the kernel), we will either need to find a way to make this walk
iterative or revert these changes.
Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" 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 v2 net-next 0/7] udp: Flow dissection for tunnels
From: David Miller @ 2016-10-18 15:48 UTC (permalink / raw)
To: tom; +Cc: netdev, kernel-team
In-Reply-To: <20161017194202.3510238-1-tom@herbertland.com>
From: Tom Herbert <tom@herbertland.com>
Date: Mon, 17 Oct 2016 12:41:55 -0700
> Now that we have a means to perform a UDP socket lookup without taking
> a reference, it is feasible to have flow dissector crack open UDP
> encapsulated packets. Generally, we would expect that the UDP source
> port or the flow label in IPv6 would contain enough entropy about
> the encapsulated flow. However, there will be cases, such as a static
> UDP tunnel with fixed ports, where dissecting the encapsulated packet
> is valuable.
>
> The model is here is similar to that implemented for UDP GRO. A
> tunnel implementation (e.g. GUE) may set a flow_dissect function
> in the udp_sk. In __skb_flow_dissect a case has been added for
> UDP to check if there is a socket with flow_dissect set. If there
> is the function is called. The (per tunnel implementation)
> function can parse the encapsulation headers and return the
> next protocol for __skb_flow_dissect to process and it's position
> in nhoff.
>
> Since performing a UDP lookup on every packet might be expensive
> I added a static key check to bypass the lookup if there are no
> sockets with flow_dissect set. I should mention that doing the
> lookup wasn't particularly a big hit anyway.
>
> Fou/gue was modified to perform tunnel dissection. This is enabled
> on each listener socket via a netlink configuration option.
Series applied, thanks Tom.
^ permalink raw reply
* Re: [PATCH v2 net-next 0/7] udp: Flow dissection for tunnels
From: David Miller @ 2016-10-18 15:52 UTC (permalink / raw)
To: tom; +Cc: netdev, kernel-team
In-Reply-To: <20161018.114837.323859592404227389.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Tue, 18 Oct 2016 11:48:37 -0400 (EDT)
> Series applied, thanks Tom.
Actually, reverted.
Tom, would you mind build testing with ipv6 enabled? :-)
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’)
^ permalink raw reply
* [PATCH -next] net: dsa: mv88e6xxx: fix non static symbol warning
From: Wei Yongjun @ 2016-10-18 15:53 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot, Florian Fainelli; +Cc: Wei Yongjun, netdev
From: Wei Yongjun <weiyongjun1@huawei.com>
Fixes the following sparse warning:
drivers/net/dsa/mv88e6xxx/chip.c:2866:5: warning:
symbol 'mv88e6xxx_g1_set_switch_mac' was not declared. Should it be static?
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index ac03297..157360f 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2863,7 +2863,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
return mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, 0x0000);
}
-int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
+static int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
{
int err;
^ permalink raw reply related
* [PATCH -next] qed: Remove useless set memory to zero use memset()
From: Wei Yongjun @ 2016-10-18 15:54 UTC (permalink / raw)
To: Yuval Mintz, Ariel Elior; +Cc: Wei Yongjun, everest-linux-l2, netdev
From: Wei Yongjun <weiyongjun1@huawei.com>
The memory return by kzalloc() has already be set to zero, so
remove useless memset(0).
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/qlogic/qed/qed_roce.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c
index f3a825a..6a353ff 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_roce.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c
@@ -2658,7 +2658,6 @@ static int qed_roce_ll2_start(struct qed_dev *cdev,
DP_ERR(cdev, "qed roce ll2 start: failed memory allocation\n");
return -ENOMEM;
}
- memset(roce_ll2, 0, sizeof(*roce_ll2));
roce_ll2->handle = QED_LL2_UNUSED_HANDLE;
roce_ll2->cbs = params->cbs;
roce_ll2->cb_cookie = params->cb_cookie;
^ permalink raw reply related
* Re: [PATCH -next] net: dsa: mv88e6xxx: fix non static symbol warning
From: Andrew Lunn @ 2016-10-18 15:56 UTC (permalink / raw)
To: Wei Yongjun; +Cc: Vivien Didelot, Florian Fainelli, Wei Yongjun, netdev
In-Reply-To: <1476806017-4290-1-git-send-email-weiyj.lk@gmail.com>
On Tue, Oct 18, 2016 at 03:53:37PM +0000, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> Fixes the following sparse warning:
>
> drivers/net/dsa/mv88e6xxx/chip.c:2866:5: warning:
> symbol 'mv88e6xxx_g1_set_switch_mac' was not declared. Should it be static?
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH v5 0/4] Add support for led triggers on phy link state change
From: David Miller @ 2016-10-18 15:57 UTC (permalink / raw)
To: zach.brown
Cc: devel, florian.c.schilhabel, f.fainelli, andrew, netdev,
linux-kernel, rpurdie, gregkh, Larry.Finger, j.anaszewski,
linux-leds, mlindner
In-Reply-To: <1476719395-28273-1-git-send-email-zach.brown@ni.com>
From: Zach Brown <zach.brown@ni.com>
Date: Mon, 17 Oct 2016 10:49:51 -0500
> Fix skge driver that declared enum contants that conflicted with enum
> constants in linux/leds.h
>
> Create function that encapsulates actions taken during the adjust phy link step
> of phy state changes.
>
> Create function that provides list of speeds currently supported by the phy.
>
> Add support for led triggers on phy link state changes by adding
> a config option. When set the config option will create a set of led triggers
> for each phy device. Users can use the led triggers to represent link state
> changes on the phy.
Ok this looks good enough for now, we can expand and improve upon it
later if necessary.
Series applied, thanks Zach.
^ permalink raw reply
* Re: [PATCH v3 net-next 00/11] net: Fix netdev adjacency tracking
From: David Ahern @ 2016-10-18 15:58 UTC (permalink / raw)
To: David Miller
Cc: jiri, netdev, dledford, sean.hefty, hal.rosenstock, linux-rdma,
j.vosburgh, vfalico, andy, jeffrey.t.kirsher, intel-wired-lan
In-Reply-To: <20161018.114631.1954199143257806104.davem@davemloft.net>
On 10/18/16 9:46 AM, David Miller wrote:
> Series applied, but the recursion is disappointing.
>
> If we run into problems due to kernel stack depth because of this with
> some configurations (reasonable or not, if we allow it then it can't
> crash the kernel), we will either need to find a way to make this walk
> iterative or revert these changes.
understood.
Since 4.9 is tagged as the next LTS I would like to see the series applied to it at some point - assuming no problems show up with wider exposure in net-next.
^ permalink raw reply
* Re: [PATCH net v2 0/3] Tunneling fixes
From: Juerg Haefliger @ 2016-10-18 16:03 UTC (permalink / raw)
To: jesse; +Cc: netdev, Juerg Haefliger
[-- Attachment #1.1: Type: text/plain, Size: 3090 bytes --]
> This series fixes a problem that was reported where encapsulated packets
> do not have their encapsulation offload markers stripped off when being
> decapsulated. This causes a significant performance drop if the packets
> are later retransmitted.
>
> Fixing this revealed two other bugs which are also addressed as prerequisites:
> * GRO can aggregate packets for multiple layers of encapsulation which the
> stack cannot properly handle.
> * IPIP packets which are combined by GRO are not marked properly with their
> GSO type.
>
> Note that this is based off the net-next tree as the current target for
> bug fixes.
I need to backport this series to the 4.4 kernel to fix a performance issue we're seeing. The series
applies but commit a09a4c8dd1ec (tunnels: Remove encapsulation offloads on decap) breaks compilation
when CONFIG_IPV6_SIT is enabled. This is because the patch uses iptunnel_pull_header() whose usage
changed with commit 7f290c94352e (iptunnel: scrub packet in iptunnel_pull_header) which is not in 4.4.
7f290c94352e seems to be a cleanup patch which also requires c9e78efb6f66 (vxlan: move vxlan device
lookup before iptunnel_pull_header) and potentially others. Rather than pulling in a slew of cleanup
patches, I was wondering if the following from commit a09a4c8dd1ec can be rewritten without using
the 'new' iptunnel_pull_header() function:
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index f45b8ffc2840..83384308d032 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -681,14 +681,16 @@ static int ipip6_rcv(struct sk_buff *skb)
skb->mac_header = skb->network_header;
skb_reset_network_header(skb);
IPCB(skb)->flags = 0;
- skb->protocol = htons(ETH_P_IPV6);
+ skb->dev = tunnel->dev;
if (packet_is_spoofed(skb, iph, tunnel)) {
tunnel->dev->stats.rx_errors++;
goto out;
}
- __skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
+ if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6),
+ !net_eq(tunnel->net, dev_net(tunnel->dev))))
+ goto out;
Thanks
...Juerg
> v2: No code changes, just additional information in commit messages and
> a new cover letter.
>
> Jesse Gross (3):
> ipip: Properly mark ipip GRO packets as encapsulated.
> tunnels: Don't apply GRO to multiple layers of encapsulation.
> tunnels: Remove encapsulation offloads on decap.
>
> include/linux/netdevice.h | 4 ++--
> include/net/ip_tunnels.h | 16 ++++++++++++++++
> net/core/dev.c | 2 +-
> net/ipv4/af_inet.c | 24 ++++++++++++++++++++++--
> net/ipv4/fou.c | 13 +++++++++++--
> net/ipv4/gre_offload.c | 5 +++++
> net/ipv4/ip_tunnel_core.c | 3 ++-
> net/ipv4/udp_offload.c | 6 +++---
> net/ipv6/ip6_offload.c | 15 ++++++++++++++-
> net/ipv6/sit.c | 6 ++++--
> 10 files changed, 80 insertions(+), 14 deletions(-)
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply related
* [PATCH net v2] bridge: multicast: restore perm router ports on multicast enable
From: Nikolay Aleksandrov @ 2016-10-18 16:09 UTC (permalink / raw)
To: netdev; +Cc: sashok, roopa, herbert, stephen, davem, Nikolay Aleksandrov
In-Reply-To: <1476796238-9384-1-git-send-email-nikolay@cumulusnetworks.com>
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>
---
v2: just call br_multicast_enable_port for all ports and use
br_multicast_open
net/bridge/br_multicast.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index c5fea9393946..2136e45f5277 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -972,13 +972,12 @@ static void br_multicast_enable(struct bridge_mcast_own_query *query)
mod_timer(&query->timer, jiffies);
}
-void br_multicast_enable_port(struct net_bridge_port *port)
+static void __br_multicast_enable_port(struct net_bridge_port *port)
{
struct net_bridge *br = port->br;
- spin_lock(&br->multicast_lock);
if (br->multicast_disabled || !netif_running(br->dev))
- goto out;
+ return;
br_multicast_enable(&port->ip4_own_query);
#if IS_ENABLED(CONFIG_IPV6)
@@ -987,8 +986,14 @@ void br_multicast_enable_port(struct net_bridge_port *port)
if (port->multicast_router == MDB_RTR_TYPE_PERM &&
hlist_unhashed(&port->rlist))
br_multicast_add_router(br, port);
+}
-out:
+void br_multicast_enable_port(struct net_bridge_port *port)
+{
+ struct net_bridge *br = port->br;
+
+ spin_lock(&br->multicast_lock);
+ __br_multicast_enable_port(port);
spin_unlock(&br->multicast_lock);
}
@@ -1994,8 +1999,9 @@ static void br_multicast_start_querier(struct net_bridge *br,
int br_multicast_toggle(struct net_bridge *br, unsigned long val)
{
- int err = 0;
struct net_bridge_mdb_htable *mdb;
+ struct net_bridge_port *port;
+ int err = 0;
spin_lock_bh(&br->multicast_lock);
if (br->multicast_disabled == !val)
@@ -2023,10 +2029,9 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
goto rollback;
}
- br_multicast_start_querier(br, &br->ip4_own_query);
-#if IS_ENABLED(CONFIG_IPV6)
- br_multicast_start_querier(br, &br->ip6_own_query);
-#endif
+ br_multicast_open(br);
+ list_for_each_entry(port, &br->port_list, list)
+ __br_multicast_enable_port(port);
unlock:
spin_unlock_bh(&br->multicast_lock);
--
2.1.4
^ permalink raw reply related
* Re: [PATCH v3 4/4] net: smsc91x: add u16 workaround for pxa platforms
From: Rob Herring @ 2016-10-18 16:39 UTC (permalink / raw)
To: Robert Jarzmik
Cc: Mark Rutland, Daniel Mack, Haojian Zhuang, Jonathan Cameron,
David Howells, Nicolas Pitre, David S. Miller, netdev, devicetree,
linux-kernel, linux-arm-kernel, linux-am33-list, Jeremy Linton
In-Reply-To: <1476733532-29716-5-git-send-email-robert.jarzmik@free.fr>
On Mon, Oct 17, 2016 at 09:45:32PM +0200, Robert Jarzmik wrote:
> Add a workaround for mainstone, idp and stargate2 boards, for u16 writes
> which must be aligned on 32 bits addresses.
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> Cc: Jeremy Linton <jeremy.linton@arm.com>
> ---
> Since v1: rename dt property to pxa-u16-align4
> change the binding documentation file
> ---
> Documentation/devicetree/bindings/net/smsc-lan91c111.txt | 2 ++
> 1 file changed, 2 insertions(+)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH net-next] ethernet/sfc: use core min/max MTU checking
From: Bert Kenward @ 2016-10-18 16:47 UTC (permalink / raw)
To: Dave Miller; +Cc: Solarflare Linux Maintainers, netdev, Jarod Wilson
Fixes: 61e84623 ("net: centralize net_device min/max MTU checking")
Signed-off-by: Bert Kenward <bkenward@solarflare.com>
---
drivers/net/ethernet/sfc/efx.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 3cf3557..b626da6 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -2263,18 +2263,6 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
rc = efx_check_disabled(efx);
if (rc)
return rc;
- if (new_mtu > EFX_MAX_MTU) {
- netif_err(efx, drv, efx->net_dev,
- "Requested MTU of %d too big (max: %d)\n",
- new_mtu, EFX_MAX_MTU);
- return -EINVAL;
- }
- if (new_mtu < EFX_MIN_MTU) {
- netif_err(efx, drv, efx->net_dev,
- "Requested MTU of %d too small (min: %d)\n",
- new_mtu, EFX_MIN_MTU);
- return -EINVAL;
- }
netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
@@ -2478,6 +2466,8 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->priv_flags |= IFF_UNICAST_FLT;
net_dev->ethtool_ops = &efx_ethtool_ops;
net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
+ net_dev->min_mtu = EFX_MIN_MTU;
+ net_dev->max_mtu = EFX_MAX_MTU;
rtnl_lock();
--
2.7.4
^ permalink raw reply related
* [patch net 1/6] switchdev: Execute bridge ndos only for bridge ports
From: Jiri Pirko @ 2016-10-18 16:50 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, eladr, yotamg, nogahf, ogerlitz, roopa, nikolay,
linville, andy, f.fainelli, dsa, jhs, vivien.didelot, andrew,
ivecera
From: Ido Schimmel <idosch@mellanox.com>
We recently got the following warning after setting up a vlan device on
top of an offloaded bridge and executing 'bridge link':
WARNING: CPU: 0 PID: 18566 at drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c:81 mlxsw_sp_port_orig_get.part.9+0x55/0x70 [mlxsw_spectrum]
[...]
CPU: 0 PID: 18566 Comm: bridge Not tainted 4.8.0-rc7 #1
Hardware name: Mellanox Technologies Ltd. Mellanox switch/Mellanox switch, BIOS 4.6.5 05/21/2015
0000000000000286 00000000e64ab94f ffff880406e6f8f0 ffffffff8135eaa3
0000000000000000 0000000000000000 ffff880406e6f930 ffffffff8108c43b
0000005106e6f988 ffff8803df398840 ffff880403c60108 ffff880406e6f990
Call Trace:
[<ffffffff8135eaa3>] dump_stack+0x63/0x90
[<ffffffff8108c43b>] __warn+0xcb/0xf0
[<ffffffff8108c56d>] warn_slowpath_null+0x1d/0x20
[<ffffffffa01420d5>] mlxsw_sp_port_orig_get.part.9+0x55/0x70 [mlxsw_spectrum]
[<ffffffffa0142195>] mlxsw_sp_port_attr_get+0xa5/0xb0 [mlxsw_spectrum]
[<ffffffff816f151f>] switchdev_port_attr_get+0x4f/0x140
[<ffffffff816f15d0>] switchdev_port_attr_get+0x100/0x140
[<ffffffff816f15d0>] switchdev_port_attr_get+0x100/0x140
[<ffffffff816f1d6b>] switchdev_port_bridge_getlink+0x5b/0xc0
[<ffffffff816f2680>] ? switchdev_port_fdb_dump+0x90/0x90
[<ffffffff815f5427>] rtnl_bridge_getlink+0xe7/0x190
[<ffffffff8161a1b2>] netlink_dump+0x122/0x290
[<ffffffff8161b0df>] __netlink_dump_start+0x15f/0x190
[<ffffffff815f5340>] ? rtnl_bridge_dellink+0x230/0x230
[<ffffffff815fab46>] rtnetlink_rcv_msg+0x1a6/0x220
[<ffffffff81208118>] ? __kmalloc_node_track_caller+0x208/0x2c0
[<ffffffff815f5340>] ? rtnl_bridge_dellink+0x230/0x230
[<ffffffff815fa9a0>] ? rtnl_newlink+0x890/0x890
[<ffffffff8161cf54>] netlink_rcv_skb+0xa4/0xc0
[<ffffffff815f56f8>] rtnetlink_rcv+0x28/0x30
[<ffffffff8161c92c>] netlink_unicast+0x18c/0x240
[<ffffffff8161ccdb>] netlink_sendmsg+0x2fb/0x3a0
[<ffffffff815c5a48>] sock_sendmsg+0x38/0x50
[<ffffffff815c6031>] SYSC_sendto+0x101/0x190
[<ffffffff815c7111>] ? __sys_recvmsg+0x51/0x90
[<ffffffff815c6b6e>] SyS_sendto+0xe/0x10
[<ffffffff817017f2>] entry_SYSCALL_64_fastpath+0x1a/0xa4
The problem is that the 8021q module propagates the call to
ndo_bridge_getlink() via switchdev ops, but the switch driver doesn't
recognize the netdev, as it's not offloaded.
While we can ignore calls being made to non-bridge ports inside the
driver, a better fix would be to push this check up to the switchdev
layer.
Note that these ndos can be called for non-bridged netdev, but this only
happens in certain PF drivers which don't call the corresponding
switchdev functions anyway.
Fixes: 99f44bb3527b ("mlxsw: spectrum: Enable L3 interfaces on top of bridge devices")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reported-by: Tamir Winetroub <tamirw@mellanox.com>
Tested-by: Tamir Winetroub <tamirw@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
Please queue-up to stable as well. Thanks.
---
net/switchdev/switchdev.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 02beb35..3b95fe9 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -771,6 +771,9 @@ int switchdev_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
u32 mask = BR_LEARNING | BR_LEARNING_SYNC | BR_FLOOD;
int err;
+ if (!netif_is_bridge_port(dev))
+ return -EOPNOTSUPP;
+
err = switchdev_port_attr_get(dev, &attr);
if (err && err != -EOPNOTSUPP)
return err;
@@ -926,6 +929,9 @@ int switchdev_port_bridge_setlink(struct net_device *dev,
struct nlattr *afspec;
int err = 0;
+ if (!netif_is_bridge_port(dev))
+ return -EOPNOTSUPP;
+
protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg),
IFLA_PROTINFO);
if (protinfo) {
@@ -959,6 +965,9 @@ int switchdev_port_bridge_dellink(struct net_device *dev,
{
struct nlattr *afspec;
+ if (!netif_is_bridge_port(dev))
+ return -EOPNOTSUPP;
+
afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg),
IFLA_AF_SPEC);
if (afspec)
--
2.5.5
^ permalink raw reply related
* Re: [patch net 1/6] switchdev: Execute bridge ndos only for bridge ports
From: Jiri Pirko @ 2016-10-18 16:56 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, eladr, yotamg, nogahf, ogerlitz, roopa, nikolay,
linville, andy, f.fainelli, dsa, jhs, vivien.didelot, andrew,
ivecera
In-Reply-To: <1476809423-14624-1-git-send-email-jiri@resnulli.us>
That's it. Only one patch :)
^ permalink raw reply
* [patch net] rtnetlink: Add rtnexthop offload flag to compare mask
From: Jiri Pirko @ 2016-10-18 16:59 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, eladr, yotamg, nogahf, ogerlitz, roopa, nikolay,
linville, andy, f.fainelli, dsa, jhs, vivien.didelot, andrew,
ivecera, nicolas.dichtel
From: Jiri Pirko <jiri@mellanox.com>
The offload flag is a status flag and should not be used by
FIB semantics for comparison.
Fixes: 37ed9493699c ("rtnetlink: add RTNH_F_EXTERNAL flag for fib offload")
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
Please queue-up to stable as well. Thanks.
---
include/uapi/linux/rtnetlink.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 262f037..5a78be5 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -350,7 +350,7 @@ struct rtnexthop {
#define RTNH_F_OFFLOAD 8 /* offloaded route */
#define RTNH_F_LINKDOWN 16 /* carrier-down on nexthop */
-#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN)
+#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD)
/* Macros to handle hexthops */
--
2.5.5
^ permalink raw reply related
* [PATCH v3 net-next 0/7] udp: Flow dissection for tunnels
From: Tom Herbert @ 2016-10-18 17:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Now that we have a means to perform a UDP socket lookup without taking
a reference, it is feasible to have flow dissector crack open UDP
encapsulated packets. Generally, we would expect that the UDP source
port or the flow label in IPv6 would contain enough entropy about
the encapsulated flow. However, there will be cases, such as a static
UDP tunnel with fixed ports, where dissecting the encapsulated packet
is valuable.
The model is here is similar to that implemented for UDP GRO. A
tunnel implementation (e.g. GUE) may set a flow_dissect function
in the udp_sk. In __skb_flow_dissect a case has been added for
UDP to check if there is a socket with flow_dissect set. If there
is the function is called. The (per tunnel implementation)
function can parse the encapsulation headers and return the
next protocol for __skb_flow_dissect to process and it's position
in nhoff.
Since performing a UDP lookup on every packet might be expensive
I added a static key check to bypass the lookup if there are no
sockets with flow_dissect set. I should mention that doing the
lookup wasn't particularly a big hit anyway.
Fou/gue was modified to perform tunnel dissection. This is enabled
on each listener socket via a netlink configuration option.
v2:
- davem suggested that we don't need udp_flow_dissect and that
udp{v6}_encap_needed could be used. Problem is that those are
in respective udp.c and flow_dissector.c is in net/core. Keep
udp_flow_dissect as more generic item.
- Fixed Makefile issue where we were using CONFIG_NET instead of
CONFIG_INET.
- Added limits inf flow dissector from controlling number of nested
encapsulations or EHs that are dissected.
- Added CONFIG_INET around use of inet_offloads in flow_dissector.c.
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.
Tested:
Running 200 streams with TCP_RR.
GRE/GUE variable source port (baseline)
RSS distributes packets, RFS is effective
1211702 tps
147/241/442 50/90/99% latencies
87.95 CPU utilization
GRE/GUE fixed source port
All packets to one CPU, RFS is ineffective
173680 tps
1170/1377/1853 50/90/99% latencies
7.42 CPU utilization
GRE/GUE fixed source port with deep hash enabled
All packets to one CPU, but now RFS is effective
730359 tps
263/325/464 50/90/99% latencies
38.25% CPU utilization (Interrupting CPU is maxed out)
Tom Herbert (7):
ipv6: Fix Makefile conditional to use CONFIG_INET
flow_dissector: Limit processing of next encaps and extensions
udp: Add socket lookup functions with noref
udp: UDP flow dissector
udp: Add UDP flow dissection functions to IPv4 and IPv6
udp: UDP tunnel flow dissection infrastructure
fou: Support flow dissection
drivers/net/usb/cdc_mbim.c | 4 ++
include/linux/netdevice.h | 5 ++
include/linux/udp.h | 7 +++
include/net/flow_dissector.h | 8 +++
include/net/ipv6.h | 15 ++++++
include/net/net_namespace.h | 2 +
include/net/udp.h | 12 +++++
include/net/udp_tunnel.h | 5 ++
include/uapi/linux/fou.h | 1 +
net/Makefile | 2 +-
net/core/flow_dissector.c | 122 ++++++++++++++++++++++++++++++++++++++-----
net/ipv4/fou.c | 68 +++++++++++++++++++++++-
net/ipv4/udp.c | 11 ++++
net/ipv4/udp_offload.c | 39 ++++++++++++++
net/ipv4/udp_tunnel.c | 5 ++
net/ipv6/udp.c | 10 ++++
net/ipv6/udp_offload.c | 40 +++++++++++++-
17 files changed, 341 insertions(+), 15 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH v3 net-next 1/7] ipv6: Fix Makefile conditional to use CONFIG_INET
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>
ipv6 directory was being built based on CONFIG_NET not CONFIG_INET.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
drivers/net/usb/cdc_mbim.c | 4 ++++
include/net/ipv6.h | 15 +++++++++++++++
include/net/net_namespace.h | 2 ++
net/Makefile | 2 +-
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 96a5028..6b38e0c 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -301,6 +301,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
return NULL;
}
+#ifdef CONFIG_INET
/* Some devices are known to send Neigbor Solicitation messages and
* require Neigbor Advertisement replies. The IPv6 core will not
* respond since IFF_NOARP is set, so we must handle them ourselves.
@@ -350,6 +351,7 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
out:
dev_put(netdev);
}
+#endif
static bool is_neigh_solicit(u8 *buf, size_t len)
{
@@ -377,8 +379,10 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_
proto = htons(ETH_P_IP);
break;
case 0x60:
+#ifdef CONFIG_INET
if (is_neigh_solicit(buf, len))
do_neigh_solicit(dev, buf, tci);
+#endif
proto = htons(ETH_P_IPV6);
break;
default:
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 8fed1cd..cbb1ce0 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -936,8 +936,15 @@ void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8 *proto);
+#ifdef CONFIG_INET
int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp,
__be16 *frag_offp);
+#else
+static inline int ipv6_skip_exthdr(const struct sk_buff *skb, int start,
+ u8 *nexthdrp, __be16 *frag_offp) {
+ return -1;
+}
+#endif
bool ipv6_ext_hdr(u8 nexthdr);
@@ -948,8 +955,16 @@ enum {
};
/* find specified header and get offset to it */
+#ifdef CONFIG_INET
int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target,
unsigned short *fragoff, int *fragflg);
+#else
+static inline int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+ int target, unsigned short *fragoff,
+ int *fragflg) {
+ return -EPROTONOSUPPORT;
+}
+#endif
int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type);
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index fc4f757..b4c4a5f 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -352,8 +352,10 @@ static inline void rt_genid_bump_ipv4(struct net *net)
extern void (*__fib6_flush_trees)(struct net *net);
static inline void rt_genid_bump_ipv6(struct net *net)
{
+#ifdef CONFIG_INET
if (__fib6_flush_trees)
__fib6_flush_trees(net);
+#endif
}
#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
diff --git a/net/Makefile b/net/Makefile
index 4cafaa2..82ffb91 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -17,7 +17,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_INET) += ipv4/
obj-$(CONFIG_XFRM) += xfrm/
obj-$(CONFIG_UNIX) += unix/
-obj-$(CONFIG_NET) += ipv6/
+obj-$(CONFIG_INET) += ipv6/
obj-$(CONFIG_PACKET) += packet/
obj-$(CONFIG_NET_KEY) += key/
obj-$(CONFIG_BRIDGE) += bridge/
--
2.9.3
^ permalink raw reply related
* [PATCH v3 net-next 3/7] udp: Add socket lookup functions with noref
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>
Create udp4_lib_lookup_noref and udp6_lib_lookup_noref. These perfrom
a socket lookup on addresses and ports without taking a reference.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/udp.h | 8 ++++++++
net/ipv4/udp.c | 8 ++++++++
net/ipv6/udp.c | 10 ++++++++++
3 files changed, 26 insertions(+)
diff --git a/include/net/udp.h b/include/net/udp.h
index ea53a87..717a972 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -275,6 +275,10 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
struct udp_table *tbl, struct sk_buff *skb);
struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
__be16 sport, __be16 dport);
+struct sock *udp4_lib_lookup_noref(struct net *net,
+ __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport,
+ int dif);
struct sock *udp6_lib_lookup(struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
@@ -286,6 +290,10 @@ struct sock *__udp6_lib_lookup(struct net *net,
struct sk_buff *skb);
struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
__be16 sport, __be16 dport);
+struct sock *udp6_lib_lookup_noref(struct net *net,
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif);
/*
* SNMP statistics for UDP and UDP-Lite
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 7d96dc2..7f84c51 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -595,6 +595,14 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
EXPORT_SYMBOL_GPL(udp4_lib_lookup);
#endif
+struct sock *udp4_lib_lookup_noref(struct net *net, __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport, int dif)
+{
+ return __udp4_lib_lookup(net, saddr, sport, daddr, dport,
+ dif, &udp_table, NULL);
+}
+EXPORT_SYMBOL_GPL(udp4_lib_lookup_noref);
+
static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
__be16 loc_port, __be32 loc_addr,
__be16 rmt_port, __be32 rmt_addr,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 9aa7c1c..6e382d9 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -317,6 +317,16 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
EXPORT_SYMBOL_GPL(udp6_lib_lookup);
#endif
+struct sock *udp6_lib_lookup_noref(struct net *net,
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif)
+{
+ return __udp6_lib_lookup(net, saddr, sport, daddr, dport,
+ dif, &udp_table, NULL);
+}
+EXPORT_SYMBOL_GPL(udp6_lib_lookup_noref);
+
/*
* This should be easy, if there is something there we
* return it, otherwise we block.
--
2.9.3
^ permalink raw reply related
* [PATCH v3 net-next 2/7] flow_dissector: Limit processing of next encaps and extensions
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>
Flow dissector does not limit the number of encapsulated packets or IPv6
header extensions that will be processed. This could easily be
suceptible to DOS attack-- for instance a 1500 byte packet could contain
75 IPIP headers.
This patch places limits on the number of encapsulations and IPv6 extension
headers that are processed in flow dissector
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/core/flow_dissector.c | 37 +++++++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 1a7b80f..919bd02 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -91,6 +91,22 @@ __be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
}
EXPORT_SYMBOL(__skb_flow_get_ports);
+#define MAX_DISSECT_DEPTH 10
+#define MAX_DISSECT_EXT 10
+
+#define __DISSECT_AGAIN(_target, _depth, _limit) do { \
+ (_depth)++; \
+ if ((_depth) > (_limit)) \
+ goto out_good; \
+ else \
+ goto _target; \
+} while (0)
+
+#define DISSECT_AGAIN(target) \
+ __DISSECT_AGAIN(target, depth, MAX_DISSECT_DEPTH)
+#define DISSECT_AGAIN_EXT(target) \
+ __DISSECT_AGAIN(target, ext_cnt, MAX_DISSECT_EXT)
+
/**
* __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
@@ -123,6 +139,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
bool skip_vlan = false;
u8 ip_proto = 0;
bool ret = false;
+ int depth = 0, ext_cnt = 0;
if (!data) {
data = skb->data;
@@ -262,7 +279,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
proto = vlan->h_vlan_encapsulated_proto;
nhoff += sizeof(*vlan);
if (skip_vlan)
- goto again;
+ DISSECT_AGAIN(again);
}
skip_vlan = true;
@@ -285,7 +302,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
}
}
- goto again;
+ DISSECT_AGAIN(again);
}
case htons(ETH_P_PPP_SES): {
struct {
@@ -299,9 +316,9 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
nhoff += PPPOE_SES_HLEN;
switch (proto) {
case htons(PPP_IP):
- goto ip;
+ DISSECT_AGAIN(ip);
case htons(PPP_IPV6):
- goto ipv6;
+ DISSECT_AGAIN(ipv6);
default:
goto out_bad;
}
@@ -472,7 +489,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
goto out_good;
- goto again;
+ DISSECT_AGAIN(again);
}
case NEXTHDR_HOP:
case NEXTHDR_ROUTING:
@@ -490,7 +507,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
ip_proto = opthdr[0];
nhoff += (opthdr[1] + 1) << 3;
- goto ip_proto_again;
+ DISSECT_AGAIN_EXT(ip_proto_again);
}
case NEXTHDR_FRAGMENT: {
struct frag_hdr _fh, *fh;
@@ -512,7 +529,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (!(fh->frag_off & htons(IP6_OFFSET))) {
key_control->flags |= FLOW_DIS_FIRST_FRAG;
if (flags & FLOW_DISSECTOR_F_PARSE_1ST_FRAG)
- goto ip_proto_again;
+ DISSECT_AGAIN_EXT(ip_proto_again);
}
goto out_good;
}
@@ -523,7 +540,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
goto out_good;
- goto ip;
+ DISSECT_AGAIN(ip);
case IPPROTO_IPV6:
proto = htons(ETH_P_IPV6);
@@ -531,10 +548,10 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
goto out_good;
- goto ipv6;
+ DISSECT_AGAIN(ipv6);
case IPPROTO_MPLS:
proto = htons(ETH_P_MPLS_UC);
- goto mpls;
+ DISSECT_AGAIN(mpls);
default:
break;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v3 net-next 4/7] udp: UDP flow dissector
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 for performing per protocol flow dissection and
support flow dissection in UDP payloads (e.g. flow dissection on a
UDP encapsulated tunnel.
The per protocol flow dissector is called by flow_dissect function
in the offload_callbacks of a protocol. The arguments of this function
include the necessary information to do flow dissection as derived
from __skb_flow_dissect which is where the callback is intended to be
called from. There are return codes from the callback in the form
FLOW_DIS_RET_* that indicate the result. FLOW_DIS_RET_IPPROTO
means that the payload should be dissected as an IP proto, the
specific protocol is returned in a pointer argument. Likewise,
FLOW_DIS_RET_PROTO indicate the payload should be processed as
an ethertype which is returned in another argument.
A case for IPPROTO_UDP was added to __skb_flow_dissect. Since
UDP flow dissector involves a relatively expensive socket lookup
there is a static key check first to see if there are any sockets
that have enabled flow dissection. After this check, the offload
ops for UDP for either IPv4 or IPv6 is considered. If the
flow_dissect function is it is called. Upon return the result
is processed (pass, out_bad, process as IP protocol, process
as ethertype). Note that if the result indicates a protocol must
be processed it is expected that nhoff has been updated to the
encapsulated protocol header.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/linux/netdevice.h | 5 +++
include/linux/udp.h | 7 ++++
include/net/flow_dissector.h | 8 +++++
include/net/udp.h | 4 +++
net/core/flow_dissector.c | 85 ++++++++++++++++++++++++++++++++++++++++++--
net/ipv4/udp.c | 3 ++
6 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index bf341b6..c5f4295 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2203,6 +2203,11 @@ 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);
+ int (*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);
};
struct packet_offload {
diff --git a/include/linux/udp.h b/include/linux/udp.h
index d1fd8cd..608ebf4 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -79,6 +79,13 @@ struct udp_sock {
int (*gro_complete)(struct sock *sk,
struct sk_buff *skb,
int nhoff);
+
+ /* Flow dissector function for UDP socket */
+ int (*flow_dissect)(struct sock *sk,
+ const struct sk_buff *skb,
+ void *data, int hlen,
+ int *nhoff, u8 *ip_proto,
+ __be16 *proto);
};
static inline struct udp_sock *udp_sk(const struct sock *sk)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index d953492..9de4904 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -203,4 +203,12 @@ static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissec
return ((char *)target_container) + flow_dissector->offset[key_id];
}
+/* Return codes from per socket flow dissector (e.g. UDP) */
+enum {
+ FLOW_DIS_RET_PASS = 0,
+ FLOW_DIS_RET_BAD,
+ FLOW_DIS_RET_IPPROTO,
+ FLOW_DIS_RET_PROTO,
+};
+
#endif
diff --git a/include/net/udp.h b/include/net/udp.h
index 717a972..8d364e8 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -360,4 +360,8 @@ void udp_encap_enable(void);
#if IS_ENABLED(CONFIG_IPV6)
void udpv6_encap_enable(void);
#endif
+
+void udp_flow_dissect_enable(void);
+void udp_flow_dissect_disable(void);
+
#endif /* _UDP_H */
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 919bd02..06ccfd5 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -8,6 +8,8 @@
#include <net/ipv6.h>
#include <net/gre.h>
#include <net/pptp.h>
+#include <net/protocol.h>
+#include <net/udp.h>
#include <linux/igmp.h>
#include <linux/icmp.h>
#include <linux/sctp.h>
@@ -57,6 +59,20 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
}
EXPORT_SYMBOL(skb_flow_dissector_init);
+static struct static_key udp_flow_dissect __read_mostly;
+
+void udp_flow_dissect_enable(void)
+{
+ static_key_slow_inc(&udp_flow_dissect);
+}
+EXPORT_SYMBOL(udp_flow_dissect_enable);
+
+void udp_flow_dissect_disable(void)
+{
+ static_key_slow_dec(&udp_flow_dissect);
+}
+EXPORT_SYMBOL(udp_flow_dissect_disable);
+
/**
* __skb_flow_get_ports - extract the upper layer ports and return them
* @skb: sk_buff to extract the ports from
@@ -131,7 +147,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
{
struct flow_dissector_key_control *key_control;
struct flow_dissector_key_basic *key_basic;
- struct flow_dissector_key_addrs *key_addrs;
+ struct flow_dissector_key_addrs *key_addrs = NULL;
struct flow_dissector_key_ports *key_ports;
struct flow_dissector_key_tags *key_tags;
struct flow_dissector_key_vlan *key_vlan;
@@ -262,7 +278,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
}
case htons(ETH_P_8021AD):
case htons(ETH_P_8021Q): {
- const struct vlan_hdr *vlan;
+ const struct vlan_hdr *vlan = NULL;
if (skb_vlan_tag_present(skb))
proto = skb->protocol;
@@ -552,6 +568,71 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
case IPPROTO_MPLS:
proto = htons(ETH_P_MPLS_UC);
DISSECT_AGAIN(mpls);
+ case IPPROTO_UDP:
+ {
+ const struct net_offload **offloads;
+ const struct net_offload *ops;
+ int ret;
+
+ if (!static_key_false(&udp_flow_dissect))
+ break;
+
+ if (depth) {
+ /* Only try to parse the UDP encapsulation if no
+ * encapsulation has been encountered yet. With an
+ * encapsulated packet there is a good chance that it is
+ * in a different namespace so the UDP lookup to get
+ * flow dissection may be invalid.
+ */
+ break;
+ }
+
+ if (!key_addrs)
+ break;
+
+ /* See if there is a flow dissector for UDP protocol */
+
+ switch (key_control->addr_type) {
+#ifdef CONFIG_INET
+ case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
+ offloads = inet_offloads;
+ break;
+ case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
+ offloads = inet6_offloads;
+ break;
+#endif
+ default:
+ goto udp_finish;
+ }
+
+ rcu_read_lock();
+
+ ops = rcu_dereference(offloads[IPPROTO_UDP]);
+
+ if (!ops || !ops->callbacks.flow_dissect) {
+ rcu_read_unlock();
+ goto udp_finish;
+ }
+
+ ret = ops->callbacks.flow_dissect(skb, data, hlen, &nhoff,
+ &ip_proto, &proto, key_addrs);
+
+ rcu_read_unlock();
+
+ switch (ret) {
+ case FLOW_DIS_RET_IPPROTO:
+ DISSECT_AGAIN(ip_proto_again);
+ case FLOW_DIS_RET_PROTO:
+ DISSECT_AGAIN(again);
+ case FLOW_DIS_RET_BAD:
+ goto out_bad;
+ case FLOW_DIS_RET_PASS:
+ default:
+ break;
+ }
+udp_finish:
+ break;
+ }
default:
break;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 7f84c51..b4b528e 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1977,6 +1977,9 @@ void udp_destroy_sock(struct sock *sk)
if (encap_destroy)
encap_destroy(sk);
}
+
+ if (up->flow_dissect)
+ udp_flow_dissect_disable();
}
/*
--
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
* [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 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox