* Re: [RFC PATCH linux-next] ovs: internal_set_rx_headroom() can be static
From: David Miller @ 2016-03-18 21:50 UTC (permalink / raw)
To: fengguang.wu-ral2JQCrhuEAvxtiuMwx3w
Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, kbuild-all-JC7UmRfGjtg,
pabeni-H+wXaHxf7aLQT0dZR+AlfA
In-Reply-To: <20160318165450.GA16372@cairo>
From: kbuild test robot <fengguang.wu@intel.com>
Date: Sat, 19 Mar 2016 00:54:50 +0800
> Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
Looks good, applied, thanks.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev
^ permalink raw reply
* Re: [PATCH] sctp: align MTU to a word
From: Eric Dumazet @ 2016-03-18 22:09 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: netdev, Neil Horman, Vlad Yasevich, linux-sctp
In-Reply-To: <1458337159-22792-1-git-send-email-marcelo.leitner@gmail.com>
On Fri, 2016-03-18 at 18:39 -0300, Marcelo Ricardo Leitner wrote:
> - transport->pathmtu = dst_mtu(transport->dst);
> + transport->pathmtu = dst_mtu(transport->dst) & ~3;
Well, surely a helper doing this would be better than spreading & ~3 all
over the places ;)
^ permalink raw reply
* Re: [PATCH] ipv6: Fix the pmtu path for connected UDP socket
From: Cong Wang @ 2016-03-18 22:09 UTC (permalink / raw)
To: Wei Wang
Cc: Wei Wang, Martin KaFai Lau, Eric Dumazet, David Miller,
Eric Dumazet, Linux Kernel Network Developers
In-Reply-To: <CAC15z3hhXxTQ+_Y6DaZcd-XVfCdDO9ZcQD6doNNKt-wHjTXAQw@mail.gmail.com>
On Fri, Mar 18, 2016 at 2:26 PM, Wei Wang <tracywwnj@gmail.com> wrote:
> I don't think ip6_sk_update_pmtu() is a good place to put it as all it
> does is to call ip6_update_pmtu(). And ip6_update_pmtu() does the
> route lookup and call __ip6_rt_update_pmtu.
> We can put it in ip6_update_pmtu(). But that still means we need to
> pass sk to ip6_update_pmtu() and I don't think it makes any difference
> compared to the current fix.
>
Well, your patch touches all the callers of ip6_update_pmtu() , if you just
fix ip6_sk_update_pmtu() as I suggested, you only need to change one
function, ideally. And the ipv4 code is there, although I am not sure, it
looks like we can just mimic the logic here:
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index ed44663..b88c2ff 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1417,8 +1417,28 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu);
void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
{
- ip6_update_pmtu(skb, sock_net(sk), mtu,
- sk->sk_bound_dev_if, sk->sk_mark);
+ const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
+ struct net *net = sock_net(sk);
+ struct dst_entry *dst;
+ struct flowi6 fl6;
+
+ bh_lock_sock(sk);
+
+ memset(&fl6, 0, sizeof(fl6));
+ fl6.flowi6_oif = sk->sk_bound_dev_if;
+ fl6.flowi6_mark = sk->sk_mark ? : IP6_REPLY_MARK(net, skb->mark);
+ fl6.daddr = iph->daddr;
+ fl6.saddr = iph->saddr;
+ fl6.flowlabel = ip6_flowinfo(iph);
+
+ dst = ip6_route_output(net, NULL, &fl6);
+ if (!dst->error)
+ __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu));
+
+ sk_dst_set(sk, &rt->dst);
+ bh_unlock_sock(sk);
+
+ dst_release(dst);
}
Please don't judge me on the code, it could still miss a lot of things,
but it can show my idea...
^ permalink raw reply related
* Re: [PATCH] openvswitch: reduce padding in struct sw_flow_key
From: Jesse Gross @ 2016-03-18 22:22 UTC (permalink / raw)
To: Arnd Bergmann
Cc: ovs dev, Linux Kernel Network Developers,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jiri Benc, Joe Stringer,
Justin Pettit, David S. Miller
In-Reply-To: <1458308084-268272-1-git-send-email-arnd-r2nGTMty4D4@public.gmane.org>
On Fri, Mar 18, 2016 at 6:34 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> This means it's still too large really, we just don't warn about it any more,
> and will get the warning again once another member is added. My patch is a
> band-aid at best, but more work is needed here. One problem is that
> ovs_flow_cmd_new and ovs_flow_cmd_set have two copies of struct sw_flow_key on
> the stack, one of them nested within sw_flow_mask. If we could reduce that to
> a single instance, the stack usage would be cut in half here.
I think it should be possible to reduce those two functions to only
use a single instance of the structure.
For new flows, we're already allocating the key structure on the heap,
it seems like we could just translate the key into that rather than to
intermediate location on the stack. And when setting flows, I'm not
sure that we really need the mask at all - we don't do anything with
it other than check it against the actions but we really should be
using the original mask for that rather than the new one.
It seems like it would be preferable to go down that route rather than
this patch, since as you say, this patch is really only suppressing
the warning and doesn't have a significant impact on the actual stack
consumption. Plus, the ordering of the flow layout affects how much
data needs to be compared during packet lookup, so this change will
likely be bad for forwarding performance.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev
^ permalink raw reply
* Re: [PATCH] netdev: Move octeon/octeon_mgmt driver to cavium directory.
From: David Miller @ 2016-03-18 22:25 UTC (permalink / raw)
To: ddaney.cavm; +Cc: netdev, linux-kernel, linux-mips, david.daney
In-Reply-To: <1458003428-27632-1-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <ddaney.cavm@gmail.com>
Date: Mon, 14 Mar 2016 17:57:08 -0700
> From: David Daney <david.daney@cavium.com>
>
> No code changes. Since OCTEON is a Cavium product, move the driver to
> the vendor directory to unclutter things a bit.
>
> Signed-off-by: David Daney <david.daney@cavium.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-next repost] openvswitch: allow output of MPLS packets on tunnel vports
From: David Miller @ 2016-03-18 22:27 UTC (permalink / raw)
To: simon.horman; +Cc: pshelar, jesse, netdev, dev
In-Reply-To: <1458010835-18555-1-git-send-email-simon.horman@netronome.com>
From: Simon Horman <simon.horman@netronome.com>
Date: Tue, 15 Mar 2016 12:00:35 +0900
> Currently output of MPLS packets on tunnel vports is not allowed by Open
> vSwitch. This is because historically encapsulation was done in such a way
> that the inner_protocol field of the skb needed to hold the inner protocol
> for both MPLS and tunnel encapsulation in order for GSO segmentation to be
> performed correctly.
>
> Since b2acd1dc3949 ("openvswitch: Use regular GRE net_device instead of
> vport") Open vSwitch makes use of lwt to output to tunnel netdevs which
> perform encapsulation. As no drivers expose support for MPLS offloads this
> means that GSO packets are segmented in software by validate_xmit_skb(),
> which is called from __dev_queue_xmit(), before tunnel encapsulation occurs.
> This means that the inner protocol of MPLS is no longer needed by the time
> encapsulation occurs and the contention on the inner_protocol field of the
> skb no longer occurs.
>
> Thus it is now safe to output MPLS to tunnel vports.
>
> Signed-off-by: Simon Horman <simon.horman@netronome.com>
Applied, thanks.
^ permalink raw reply
* Re: [patch 1/2 net-next] mediatek: checking for IS_ERR() instead of NULL
From: David Miller @ 2016-03-18 22:31 UTC (permalink / raw)
To: dan.carpenter
Cc: nbd, blogic, matthias.bgg, netdev, linux-mediatek,
kernel-janitors
In-Reply-To: <20160315071849.GH13560@mwanda>
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Tue, 15 Mar 2016 10:18:49 +0300
> of_phy_connect() returns NULL on error, it never returns error pointers.
>
> Fixes: 656e705243fd ('net-next: mediatek: add support for MT7623 ethernet')
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Applied.
^ permalink raw reply
* Re: [patch 2/2 net-next] mediatek: unlock on error in mtk_tx_map()
From: David Miller @ 2016-03-18 22:31 UTC (permalink / raw)
To: dan.carpenter
Cc: nbd, blogic, matthias.bgg, netdev, linux-mediatek,
kernel-janitors
In-Reply-To: <20160315071904.GI13560@mwanda>
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Tue, 15 Mar 2016 10:19:04 +0300
> There was a missing unlock on the error path.
>
> Fixes: 656e705243fd ('net-next: mediatek: add support for MT7623 ethernet')
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Applied.
^ permalink raw reply
* Re: [PATCH 1/1] net: stmmac: Don't search for phys if mdio node is defined.
From: David Miller @ 2016-03-18 22:31 UTC (permalink / raw)
To: preid; +Cc: peppe.cavallaro, netdev
In-Reply-To: <1458027273-127737-2-git-send-email-preid@electromag.com.au>
From: Phil Reid <preid@electromag.com.au>
Date: Tue, 15 Mar 2016 15:34:33 +0800
> If a dt mdio entry has been added least assume that we wont
> search for phys attached. The DT and of_mdiobus_register already do
> this. This stops DSA phys being found and phys created for them, as
> this is handled by the DSA driver.
>
> Signed-off-by: Phil Reid <preid@electromag.com.au>
Applied.
^ permalink raw reply
* Re: [PATCH] af_unix: closed SOCK_SEQPACKET socketpair must get SIGPIPE
From: David Miller @ 2016-03-18 22:32 UTC (permalink / raw)
To: glider; +Cc: edumazet, rweikusat, linux-kernel, netdev
In-Reply-To: <1458032624-139688-1-git-send-email-glider@google.com>
From: Alexander Potapenko <glider@google.com>
Date: Tue, 15 Mar 2016 10:03:44 +0100
> According to IEEE Std 1003.1, 2013, sending data to a SOCK_SEQPACKET
> socketpair with MSG_NOSIGNAL flag set must result in a SIGPIPE if the
> socket is no longer connected.
>
> I used the following program to check the kernel behavior:
...
> Signed-off-by: Alexander Potapenko <glider@google.com>
In the final analysis I don't think we can do this.
Properly working programs will start to mysteriously receive
signals in this situation and fail.
I'm sorry but I think we're stuck with this behavior.
^ permalink raw reply
* Re: [PATCH] sctp: align MTU to a word
From: Marcelo Ricardo Leitner @ 2016-03-18 22:33 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, Neil Horman, Vlad Yasevich, linux-sctp
In-Reply-To: <1458338974.31963.15.camel@edumazet-glaptop3.roam.corp.google.com>
On Fri, Mar 18, 2016 at 03:09:34PM -0700, Eric Dumazet wrote:
> On Fri, 2016-03-18 at 18:39 -0300, Marcelo Ricardo Leitner wrote:
>
> > - transport->pathmtu = dst_mtu(transport->dst);
> > + transport->pathmtu = dst_mtu(transport->dst) & ~3;
>
>
> Well, surely a helper doing this would be better than spreading & ~3 all
> over the places ;)
Heh.. agreed
for this and the other patch too, will post a v2
Thanks
^ permalink raw reply
* Re: [PATCH] net: consolidate lock/unlock into unlock_wait
From: Joe Perches @ 2016-03-18 22:35 UTC (permalink / raw)
To: David Miller, hofrat; +Cc: netdev, linux-kernel
In-Reply-To: <20160318.173702.788700055531273267.davem@davemloft.net>
On Fri, 2016-03-18 at 17:37 -0400, David Miller wrote:
> From: Nicholas Mc Guire <hofrat@osadl.org>
> > The spin_lock()/spin_unlock() is synchronizing on the adapter->work_lock
> > as the comment also suggests, which is equivalent to spin_unlock_wait()
> > but the later should be more efficient.
[]
> There really is no justification for this change.
> This is an optimization in a slow-path of the driver.
> The device is a rarely used older piece of hardware.
It really might be nice to take some of the ancient
hardware drivers in drivers/net and move them into
some separate subdirectory like:
drivers/net/ancient
or
drivers/net/antiques
or
drivers/net/archaic
etc...
so there's some clear designation that these crufty
old drivers don't need to be touched anymore except
for maybe when kernel wide changes occur.
^ permalink raw reply
* Re: [v6, 2/5] soc: fsl: add GUTS driver for QorIQ platforms
From: Scott Wood @ 2016-03-18 22:54 UTC (permalink / raw)
To: Yangbo Lu, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-clk@vger.kernel.org, linux-i2c@vger.kernel.org,
iommu@lists.linux-foundation.org, netdev@vger.kernel.org,
linux-mmc@vger.kernel.org
Cc: Rob Herring, Russell King, Jochen Friedrich, Joerg Roedel,
Claudiu Manoil, ulf.hansson@linaro.org, Bhupesh Sharma,
Zhao Qiang, Kumar Gala, Santosh Shilimkar, Yang-Leo Li,
Xiaobo Xie
In-Reply-To: <1457518131-11339-3-git-send-email-yangbo.lu@nxp.com>
On 03/09/2016 04:18 AM, Yangbo Lu wrote:
> +#ifdef CONFIG_FSL_GUTS
> +u32 fsl_guts_get_svr(void);
> +int fsl_guts_init(void);
> +#endif
Don't ifdef prototypes (when not providing a stub alternative).
-Scott
^ permalink raw reply
* Re: [PATCH] sctp: keep fragmentation point aligned to word size
From: Marcelo Ricardo Leitner @ 2016-03-18 23:11 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, Vlad Yasevich, linux-sctp
In-Reply-To: <1458337159-22792-2-git-send-email-marcelo.leitner@gmail.com>
On Fri, Mar 18, 2016 at 06:39:17PM -0300, Marcelo Ricardo Leitner wrote:
> If the user supply a different fragmentation point or if there is a
> network header that cause it to not be aligned, force it to be aligned.
>
> Fragmentation point at a value that is not aligned is not optimal. It
> causes extra padding to be used and has just no pros.
>
> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> ---
> include/net/sctp/sctp.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 835aa2ed987092634a4242314e9eabb51d1e4e35..f27d38113c7926783a9bf2863e14e963ed0ad5d6 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -426,7 +426,7 @@ static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> if (asoc->user_frag)
> frag = min_t(int, frag, asoc->user_frag);
>
> - frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN);
> + frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN) & ~3;
Will submit a v2 with a helper for this & ~3 thing
^ permalink raw reply
* Re: [PATCH net 1/1] qlge: Fix receive packets drop.
From: David Miller @ 2016-03-18 23:22 UTC (permalink / raw)
To: manish.chopra; +Cc: netdev, Dept-GELinuxNICDev, harish.patil
In-Reply-To: <1458040425-12937-1-git-send-email-manish.chopra@qlogic.com>
From: Manish Chopra <manish.chopra@qlogic.com>
Date: Tue, 15 Mar 2016 07:13:45 -0400
> When running small packets [length < 256 bytes] traffic, packets were
> being dropped due to invalid data in those packets which were
> delivered by the driver upto the stack. Using pci_dma_sync_single_for_cpu
> ensures copying latest and updated data into skb from the receive buffer.
>
> Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
> Signed-off-by: Manish Chopra <manish.chopra@qlogic.com>
Applied and queued up for -stable.
^ permalink raw reply
* Re: [PATCH net] ravb: fix result value overwrite
From: David Miller @ 2016-03-18 23:22 UTC (permalink / raw)
To: ykaneko0929
Cc: netdev, sergei.shtylyov, horms, magnus.damm, linux-renesas-soc
In-Reply-To: <1458057136-23253-1-git-send-email-ykaneko0929@gmail.com>
From: Yoshihiro Kaneko <ykaneko0929@gmail.com>
Date: Wed, 16 Mar 2016 00:52:16 +0900
> The result value is overwritten by a return value of
> ravb_ptp_interrupt().
>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH net] bnx2x: Prevent false warning for lack of FC NPIV
From: David Miller @ 2016-03-18 23:23 UTC (permalink / raw)
To: Yuval.Mintz; +Cc: netdev, Ariel.Elior, linux-scsi, andrew.patterson
In-Reply-To: <1458064324-16487-1-git-send-email-Yuval.Mintz@qlogic.com>
From: Yuval Mintz <Yuval.Mintz@qlogic.com>
Date: Tue, 15 Mar 2016 19:52:04 +0200
> Not all adapters have FC-NPIV configured. If bnx2fc is used with such an
> adapter, driver would read irrelevant data from the the nvram and log
> "FC-NPIV table with bad length..." In system logs.
>
> Simply accept that reading '0' as the feature offset in nvram indicates
> the feature isn't there and return.
>
> Reported-by: Andrew Patterson <andrew.patterson@hpe.com>
> Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Applied.
^ permalink raw reply
* [RFC PATCH 0/9] RFC6864 compliant GRO and GSO partial offload
From: Alexander Duyck @ 2016-03-18 23:24 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
This patch series addresses two things.
First it enables what I am calling RFC6864 compliant GRO. Basically what
I am doing is allowing one of two patterns for incoming frames. Either the
IP ID will increment, or if the DF bit is set it can either increment or
stay the same value. This allows us to perform GRO if the IP ID is forced
to stay at a static value as may occur if we are replicating an IP header
instead of actually having it offloaded.
The last 3 patches introduce what I am calling GSO partial. The best way
to describe it is that it is a GSO offload in which the portion pointed to
by csum_start must be handled by the hardware, and the region before that
can be optionally handled. So for example with i40e the only pieces it was
missing from the full offload was the checksum so this is computed in
software and the hardware will update inner and outer IP headers. In the
example for ixgbe the hardware will only update the outer IP header. The
outer UDP or GRE header and inner IP header are unmodified.
The bits remaining to be worked out are what to do about drivers that
wouldn't be able to handle updating the outer IP header. So for example
should I require the driver to have to update the outer IP header or handle
it in software. The one concern here is that if the outer IP header does
not have the DF bit set and does not update the IP ID field we run the risk
of causing all sorts of problems if the packet is fragmented in flight.
---
Alexander Duyck (9):
ipv4/GRO: Allow multiple frames to use the same IP ID
gre: Enforce IP ID verification on outer headers
geneve: Enforce IP ID verification on outer headers
vxlan: Enforce IP ID verification on outer headers
gue: Enforce IP ID verification on outer headers
ethtool: Add support for toggling any of the GSO offloads
GSO: Support partial segmentation offload
i40e/i40evf: Add support for GSO partial with UDP_TUNNEL_CSUM and GRE_CSUM
ixgbe/ixgbevf: Add support for GSO partial
drivers/net/ethernet/intel/i40e/i40e_main.c | 8 ++
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 14 +++-
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 14 +++-
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 8 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 72 +++++++++++++-------
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 77 ++++++++++++++-------
drivers/net/geneve.c | 14 ++++
drivers/net/vxlan.c | 14 ++++
include/linux/netdev_features.h | 7 ++
include/linux/netdevice.h | 7 ++
include/linux/skbuff.h | 7 ++
net/core/dev.c | 31 ++++++++
net/core/ethtool.c | 4 +
net/core/skbuff.c | 21 +++++-
net/ipv4/af_inet.c | 20 ++++-
net/ipv4/fou.c | 14 ++++
net/ipv4/gre_offload.c | 37 +++++++++-
net/ipv4/tcp_offload.c | 25 ++++++-
net/ipv4/udp_offload.c | 20 ++++-
net/ipv6/ip6_offload.c | 9 ++
20 files changed, 344 insertions(+), 79 deletions(-)
^ permalink raw reply
* [RFC PATCH 1/9] ipv4/GRO: Allow multiple frames to use the same IP ID
From: Alexander Duyck @ 2016-03-18 23:24 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
In-Reply-To: <20160318230945.14955.63211.stgit@localhost.localdomain>
In RFC 6864 it is stated that we can essentially ignore the IPv4 ID field
if we have not and will not use fragmentation. Such a frame is defined
as having the DF flag set to 1, and the MF and frag_offset as 0. Currently
for GRO we were requiring that the inner header always have an increasing
IPv4 ID, but we are ignoring the outer value.
This patch is a first step in trying to reverse some of that. Specifically
what this patch does is allow us to coalesce frames that have a static IPv4
ID value. So for example if we had a series of frames where the DF flag
was set we would allow the same IPv4 ID value to be used for all the frames
belonging to that flow. This would become the standard behavior for TCP so
it would support either a fixed IPv4 ID value, or one in which the value
increments.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
include/linux/netdevice.h | 5 ++++-
net/ipv4/af_inet.c | 8 ++++++--
net/ipv4/tcp_offload.c | 15 ++++++++++++++-
3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index be693b34662f..31474d9d8a96 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2113,7 +2113,10 @@ struct napi_gro_cb {
/* Used in foo-over-udp, set in udp[46]_gro_receive */
u8 is_ipv6:1;
- /* 7 bit hole */
+ /* Flag indicating if IP ID can be ignored on receive */
+ u8 rfc6864:1;
+
+ /* 6 bit hole */
/* used to support CHECKSUM_COMPLETE for tunneling protocols */
__wsum csum;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 0cc923f83e10..5e3885672907 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1320,6 +1320,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
id = ntohl(*(__be32 *)&iph->id);
flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));
+
+ NAPI_GRO_CB(skb)->rfc6864 = !!(id & IP_DF);
id >>= 16;
for (p = *head; p; p = p->next) {
@@ -1352,8 +1354,10 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
* This is because some GSO/TSO implementations do not
* correctly increment the IP ID for the outer hdrs.
*/
- NAPI_GRO_CB(p)->flush_id =
- ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id);
+ NAPI_GRO_CB(p)->flush_id = (u16)(id - ntohs(iph2->id));
+ if (!NAPI_GRO_CB(p)->rfc6864 || !NAPI_GRO_CB(skb)->rfc6864)
+ NAPI_GRO_CB(p)->flush_id ^= NAPI_GRO_CB(p)->count;
+
NAPI_GRO_CB(p)->flush |= flush;
}
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 773083b7f1e9..1a2e9957c177 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -237,7 +237,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
found:
/* Include the IP ID check below from the inner most IP hdr */
- flush = NAPI_GRO_CB(p)->flush | NAPI_GRO_CB(p)->flush_id;
+ flush = NAPI_GRO_CB(p)->flush;
flush |= (__force int)(flags & TCP_FLAG_CWR);
flush |= (__force int)((flags ^ tcp_flag_word(th2)) &
~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH));
@@ -246,6 +246,19 @@ found:
flush |= *(u32 *)((u8 *)th + i) ^
*(u32 *)((u8 *)th2 + i);
+ /* Some devices may make use of RFC6864 to skip the need to
+ * increment the IP ID on inner headers of tunneled frames. This
+ * allows them to make use of TSO by not updating the headers from
+ * the outer L4 to inner L3. We should be able to identify any such
+ * frames on the second frame received and then after that we expect
+ * the same ID on all remaining frames in the flow.
+ */
+ if ((NAPI_GRO_CB(p)->flush_id == 1) && NAPI_GRO_CB(p)->rfc6864 &&
+ (NAPI_GRO_CB(p)->count == 1))
+ NAPI_GRO_CB(p)->rfc6864 = 0;
+ else
+ flush |= NAPI_GRO_CB(p)->flush_id;
+
mss = skb_shinfo(p)->gso_size;
flush |= (len - 1) >= mss;
^ permalink raw reply related
* [RFC PATCH 2/9] gre: Enforce IP ID verification on outer headers
From: Alexander Duyck @ 2016-03-18 23:24 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
In-Reply-To: <20160318230945.14955.63211.stgit@localhost.localdomain>
This change enforces the IP ID verification on outer headers. As a result
if the DF flag is not set on the outer header we will force the flow to be
flushed in the event that the IP ID is out of sequence with the existing
flow.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
net/ipv4/gre_offload.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 540866dbd27d..7ea14ced9222 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -203,6 +203,20 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
continue;
}
}
+
+ /* Include the IP ID check from the outer IP hdr */
+ if (!NAPI_GRO_CB(p)->flush_id)
+ continue;
+
+ /* If flush_id is non-zero and rfc6864 is enabled for
+ * the new frame the only possibility is that we are
+ * incrementing so we can xor by count to cancel out
+ * the one acceptable value.
+ */
+ NAPI_GRO_CB(p)->flush |= NAPI_GRO_CB(skb)->rfc6864 ?
+ NAPI_GRO_CB(p)->flush_id ^
+ NAPI_GRO_CB(p)->count :
+ NAPI_GRO_CB(p)->flush_id;
}
skb_gro_pull(skb, grehlen);
^ permalink raw reply related
* [RFC PATCH 3/9] geneve: Enforce IP ID verification on outer headers
From: Alexander Duyck @ 2016-03-18 23:24 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
In-Reply-To: <20160318230945.14955.63211.stgit@localhost.localdomain>
This change enforces the IP ID verification on outer headers. As a result
if the DF flag is not set on the outer header we will force the flow to be
flushed in the event that the IP ID is out of sequence with the existing
flow.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
drivers/net/geneve.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 192631a345df..2dac5496c965 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -473,6 +473,20 @@ static struct sk_buff **geneve_gro_receive(struct sk_buff **head,
NAPI_GRO_CB(p)->same_flow = 0;
continue;
}
+
+ /* Include the IP ID check from the outer IP hdr */
+ if (!NAPI_GRO_CB(p)->flush_id)
+ continue;
+
+ /* If flush_id is non-zero and rfc6864 is enabled for
+ * the new frame the only possibility is that we are
+ * incrementing so we can xor by count to cancel out
+ * the one acceptable value.
+ */
+ NAPI_GRO_CB(p)->flush |= NAPI_GRO_CB(skb)->rfc6864 ?
+ NAPI_GRO_CB(p)->flush_id ^
+ NAPI_GRO_CB(p)->count :
+ NAPI_GRO_CB(p)->flush_id;
}
type = gh->proto_type;
^ permalink raw reply related
* [RFC PATCH 4/9] vxlan: Enforce IP ID verification on outer headers
From: Alexander Duyck @ 2016-03-18 23:25 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
In-Reply-To: <20160318230945.14955.63211.stgit@localhost.localdomain>
This change enforces the IP ID verification on outer headers. As a result
if the DF flag is not set on the outer header we will force the flow to be
flushed in the event that the IP ID is out of sequence with the existing
flow.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
drivers/net/vxlan.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 800106a7246c..d6838a30e772 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -601,6 +601,20 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head,
NAPI_GRO_CB(p)->same_flow = 0;
continue;
}
+
+ /* Include the IP ID check from the outer IP hdr */
+ if (!NAPI_GRO_CB(p)->flush_id)
+ continue;
+
+ /* If flush_id is non-zero and rfc6864 is enabled for
+ * the new frame the only possibility is that we are
+ * incrementing so we can xor by count to cancel out
+ * the one acceptable value.
+ */
+ NAPI_GRO_CB(p)->flush |= NAPI_GRO_CB(skb)->rfc6864 ?
+ NAPI_GRO_CB(p)->flush_id ^
+ NAPI_GRO_CB(p)->count :
+ NAPI_GRO_CB(p)->flush_id;
}
pp = eth_gro_receive(head, skb);
^ permalink raw reply related
* [RFC PATCH 5/9] gue: Enforce IP ID verification on outer headers
From: Alexander Duyck @ 2016-03-18 23:25 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
In-Reply-To: <20160318230945.14955.63211.stgit@localhost.localdomain>
This change enforces the IP ID verification on outer headers. As a result
if the DF flag is not set on the outer header we will force the flow to be
flushed in the event that the IP ID is out of sequence with the existing
flow.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
net/ipv4/fou.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 780484243e14..2be35e4f6d88 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -341,6 +341,20 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
NAPI_GRO_CB(p)->same_flow = 0;
continue;
}
+
+ /* Include the IP ID check from the outer IP hdr */
+ if (!NAPI_GRO_CB(p)->flush_id)
+ continue;
+
+ /* If flush_id is non-zero and rfc6864 is enabled for
+ * the new frame the only possibility is that we are
+ * incrementing so we can xor by count to cancel out
+ * the one acceptable value.
+ */
+ NAPI_GRO_CB(p)->flush |= NAPI_GRO_CB(skb)->rfc6864 ?
+ NAPI_GRO_CB(p)->flush_id ^
+ NAPI_GRO_CB(p)->count :
+ NAPI_GRO_CB(p)->flush_id;
}
rcu_read_lock();
^ permalink raw reply related
* [RFC PATCH 6/9] ethtool: Add support for toggling any of the GSO offloads
From: Alexander Duyck @ 2016-03-18 23:25 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
In-Reply-To: <20160318230945.14955.63211.stgit@localhost.localdomain>
The strings were missing for several of the GSO offloads that are
available. This patch provides the missing strings so that we can toggle
or query any of them via the ethtool command.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
net/core/ethtool.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 2966cd0d7c93..b3c39d531469 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -82,9 +82,12 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation",
[NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
[NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
+ [NETIF_F_GSO_GRE_CSUM_BIT] = "tx-gre-csum-segmentation",
[NETIF_F_GSO_IPIP_BIT] = "tx-ipip-segmentation",
[NETIF_F_GSO_SIT_BIT] = "tx-sit-segmentation",
[NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
+ [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
+ [NETIF_F_GSO_TUNNEL_REMCSUM_BIT] = "tx-remcsum-segmentation",
[NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
[NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp",
^ permalink raw reply related
* [RFC PATCH 7/9] GSO: Support partial segmentation offload
From: Alexander Duyck @ 2016-03-18 23:25 UTC (permalink / raw)
To: ecree, netdev, davem, alexander.duyck, tom
In-Reply-To: <20160318230945.14955.63211.stgit@localhost.localdomain>
This patch adds support for something I am referring to as GSO partial.
The basic idea is that we can support a broader range of devices for
segmentation if we use fixed outer headers and have the hardware only
really deal with segmenting the inner header. The idea behind the naming
is due to the fact that everything before csum_start will be fixed headers,
and everything after will be the region that is handled by hardware.
With the current implementation it allows us to add support for the
following GSO types with an inner TSO or TSO6 offload:
NETIF_F_GSO_GRE
NETIF_F_GSO_GRE_CSUM
NETIF_F_UDP_TUNNEL
NETIF_F_UDP_TUNNEL_CSUM
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
include/linux/netdev_features.h | 7 ++++++-
include/linux/netdevice.h | 2 ++
include/linux/skbuff.h | 7 ++++++-
net/core/dev.c | 31 ++++++++++++++++++++++++++++++-
net/core/ethtool.c | 1 +
net/core/skbuff.c | 21 ++++++++++++++++++++-
net/ipv4/af_inet.c | 12 ++++++++++--
net/ipv4/gre_offload.c | 23 +++++++++++++++++++----
net/ipv4/tcp_offload.c | 10 ++++++++--
net/ipv4/udp_offload.c | 20 ++++++++++++++++----
net/ipv6/ip6_offload.c | 9 ++++++++-
11 files changed, 126 insertions(+), 17 deletions(-)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index a734bf43d190..8df3c5553af0 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -48,8 +48,12 @@ enum {
NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
+ NETIF_F_GSO_PARTIAL_BIT, /* ... Only segment inner-most L4
+ * in hardware and all other
+ * headers in software.
+ */
/**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
- NETIF_F_GSO_TUNNEL_REMCSUM_BIT,
+ NETIF_F_GSO_PARTIAL_BIT,
NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
NETIF_F_SCTP_CRC_BIT, /* SCTP checksum offload */
@@ -121,6 +125,7 @@ enum {
#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
#define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM)
+#define NETIF_F_GSO_PARTIAL __NETIF_F(GSO_PARTIAL)
#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)
#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 31474d9d8a96..427d748ad8f9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1647,6 +1647,7 @@ struct net_device {
netdev_features_t vlan_features;
netdev_features_t hw_enc_features;
netdev_features_t mpls_features;
+ netdev_features_t gso_partial_features;
int ifindex;
int group;
@@ -4014,6 +4015,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
+ BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT));
return (features & feature) == feature;
}
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 15d0df943466..c291a282f8b6 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -482,6 +482,8 @@ enum {
SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
SKB_GSO_TUNNEL_REMCSUM = 1 << 12,
+
+ SKB_GSO_PARTIAL = 1 << 13,
};
#if BITS_PER_LONG > 32
@@ -3584,7 +3586,10 @@ static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
* Keeps track of level of encapsulation of network headers.
*/
struct skb_gso_cb {
- int mac_offset;
+ union {
+ int mac_offset;
+ int data_offset;
+ };
int encap_level;
__wsum csum;
__u16 csum_start;
diff --git a/net/core/dev.c b/net/core/dev.c
index edb7179bc051..666cf427898b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2711,6 +2711,19 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
return ERR_PTR(err);
}
+ /* Only report GSO partial support if it will enable us to
+ * support segmentation on this frame without needing additional
+ * work.
+ */
+ if (features & NETIF_F_GSO_PARTIAL) {
+ netdev_features_t partial_features;
+ struct net_device *dev = skb->dev;
+
+ partial_features = dev->features & dev->gso_partial_features;
+ if (!skb_gso_ok(skb, features | partial_features))
+ features &= ~NETIF_F_GSO_PARTIAL;
+ }
+
BUILD_BUG_ON(SKB_SGO_CB_OFFSET +
sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb));
@@ -2841,6 +2854,14 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
if (skb->encapsulation)
features &= dev->hw_enc_features;
+ /* Support for GSO partial features requires software intervention
+ * before we can actually process the packets so we need to strip
+ * support for any partial features now and we can pull them back
+ * in after we have partially segmented the frame.
+ */
+ if (skb_is_gso(skb) && !(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL))
+ features &= ~dev->gso_partial_features;
+
if (skb_vlan_tagged(skb))
features = netdev_intersect_features(features,
dev->vlan_features |
@@ -6702,6 +6723,14 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
}
}
+ /* GSO partial features require GSO partial be set */
+ if ((features & dev->gso_partial_features) &&
+ !(features & NETIF_F_GSO_PARTIAL)) {
+ netdev_dbg(dev,
+ "Dropping partially supported GSO features since no GSO partial.\n");
+ features &= ~dev->gso_partial_features;
+ }
+
#ifdef CONFIG_NET_RX_BUSY_POLL
if (dev->netdev_ops->ndo_busy_poll)
features |= NETIF_F_BUSY_POLL;
@@ -6982,7 +7011,7 @@ int register_netdevice(struct net_device *dev)
/* Make NETIF_F_SG inheritable to tunnel devices.
*/
- dev->hw_enc_features |= NETIF_F_SG;
+ dev->hw_enc_features |= NETIF_F_SG | NETIF_F_GSO_PARTIAL;
/* Make NETIF_F_SG inheritable to MPLS.
*/
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index b3c39d531469..d1b278c6c29f 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -88,6 +88,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
[NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
[NETIF_F_GSO_TUNNEL_REMCSUM_BIT] = "tx-remcsum-segmentation",
+ [NETIF_F_GSO_PARTIAL_BIT] = "tx-gso-partial",
[NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
[NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp",
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f044f970f1a6..bdcba77e164c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3076,8 +3076,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
struct sk_buff *frag_skb = head_skb;
unsigned int offset = doffset;
unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
+ unsigned int partial_segs = 0;
unsigned int headroom;
- unsigned int len;
+ unsigned int len = head_skb->len;
__be16 proto;
bool csum;
int sg = !!(features & NETIF_F_SG);
@@ -3094,6 +3095,15 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
csum = !!can_checksum_protocol(features, proto);
+ /* GSO partial only requires that we trim off any excess that
+ * doesn't fit into an MSS sized block, so take care of that
+ * now.
+ */
+ if (features & NETIF_F_GSO_PARTIAL) {
+ partial_segs = len / mss;
+ mss *= partial_segs;
+ }
+
headroom = skb_headroom(head_skb);
pos = skb_headlen(head_skb);
@@ -3281,6 +3291,15 @@ perform_csum_check:
*/
segs->prev = tail;
+ /* Update GSO info on first skb in partial sequence. */
+ if (partial_segs) {
+ skb_shinfo(segs)->gso_size = mss / partial_segs;
+ skb_shinfo(segs)->gso_segs = partial_segs;
+ skb_shinfo(segs)->gso_type = skb_shinfo(head_skb)->gso_type |
+ SKB_GSO_PARTIAL;
+ SKB_GSO_CB(segs)->data_offset = skb_headroom(segs) + doffset;
+ }
+
/* Following permits correct backpressure, for protocols
* using skb_set_owner_w().
* Idea is to tranfert ownership from head_skb to last segment.
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 5e3885672907..d091f91fa25d 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1199,7 +1199,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
unsigned int offset = 0;
bool udpfrag, encap;
struct iphdr *iph;
- int proto;
+ int proto, tot_len;
int nhoff;
int ihl;
int id;
@@ -1269,10 +1269,18 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
if (skb->next)
iph->frag_off |= htons(IP_MF);
offset += skb->len - nhoff - ihl;
+ tot_len = skb->len - nhoff;
+ } else if (skb_is_gso(skb)) {
+ iph->id = htons(id);
+ id += skb_shinfo(skb)->gso_segs;
+ tot_len = skb_shinfo(skb)->gso_size +
+ SKB_GSO_CB(skb)->data_offset +
+ skb->head - (unsigned char *)iph;
} else {
iph->id = htons(id++);
+ tot_len = skb->len - nhoff;
}
- iph->tot_len = htons(skb->len - nhoff);
+ iph->tot_len = htons(tot_len);
ip_send_check(iph);
if (encap)
skb_reset_inner_headers(skb);
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 7ea14ced9222..dea0390d65bb 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -85,7 +85,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
skb = segs;
do {
struct gre_base_hdr *greh;
- __be32 *pcsum;
+ __sum16 *pcsum;
/* Set up inner headers if we are offloading inner checksum */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -105,10 +105,25 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
continue;
greh = (struct gre_base_hdr *)skb_transport_header(skb);
- pcsum = (__be32 *)(greh + 1);
+ pcsum = (__sum16 *)(greh + 1);
+
+ if (skb_is_gso(skb)) {
+ unsigned int partial_adj;
+
+ /* Adjust checksum to account for the fact that
+ * the partial checksum is based on actual size
+ * whereas headers should be based on MSS size.
+ */
+ partial_adj = skb->len + skb_headroom(skb) -
+ SKB_GSO_CB(skb)->data_offset -
+ skb_shinfo(skb)->gso_size;
+ *pcsum = ~csum_fold((__force __wsum)htonl(partial_adj));
+ } else {
+ *pcsum = 0;
+ }
- *pcsum = 0;
- *(__sum16 *)pcsum = gso_make_checksum(skb, 0);
+ *(pcsum + 1) = 0;
+ *pcsum = gso_make_checksum(skb, 0);
} while ((skb = skb->next));
out:
return segs;
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 1a2e9957c177..4e9b8f011473 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -107,6 +107,12 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
goto out;
}
+ /* GSO partial only requires splitting the frame into an MSS
+ * multiple and possibly a remainder. So update the mss now.
+ */
+ if (features & NETIF_F_GSO_PARTIAL)
+ mss = skb->len - (skb->len % mss);
+
copy_destructor = gso_skb->destructor == tcp_wfree;
ooo_okay = gso_skb->ooo_okay;
/* All segments but the first should have ooo_okay cleared */
@@ -131,7 +137,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
newcheck = ~csum_fold((__force __wsum)((__force u32)th->check +
(__force u32)delta));
- do {
+ while (skb->next) {
th->fin = th->psh = 0;
th->check = newcheck;
@@ -151,7 +157,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
th->seq = htonl(seq);
th->cwr = 0;
- } while (skb->next);
+ }
/* Following permits TCP Small Queues to work well with GSO :
* The callback to TCP stack will be called at the time last frag
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 8a3405a80260..5fcb93269afb 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -100,7 +100,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
udp_offset = outer_hlen - tnl_hlen;
skb = segs;
do {
- __be16 len;
+ unsigned int len;
if (remcsum)
skb->ip_summed = CHECKSUM_NONE;
@@ -118,14 +118,26 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
skb_reset_mac_header(skb);
skb_set_network_header(skb, mac_len);
skb_set_transport_header(skb, udp_offset);
- len = htons(skb->len - udp_offset);
+ len = skb->len - udp_offset;
uh = udp_hdr(skb);
- uh->len = len;
+
+ /* If we are only performing partial GSO the inner header
+ * will be using a length value equal to only one MSS sized
+ * segment instead of the entire frame.
+ */
+ if (skb_is_gso(skb)) {
+ uh->len = htons(skb_shinfo(skb)->gso_size +
+ SKB_GSO_CB(skb)->data_offset +
+ skb->head - (unsigned char *)uh);
+ } else {
+ uh->len = htons(len);
+ }
if (!need_csum)
continue;
- uh->check = ~csum_fold(csum_add(partial, (__force __wsum)len));
+ uh->check = ~csum_fold(csum_add(partial,
+ (__force __wsum)htonl(len)));
if (skb->encapsulation || !offload_csum) {
uh->check = gso_make_checksum(skb, ~uh->check);
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index eeca943f12dc..d467053c226a 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -63,6 +63,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
int proto;
struct frag_hdr *fptr;
unsigned int unfrag_ip6hlen;
+ unsigned int payload_len;
u8 *prevhdr;
int offset = 0;
bool encap, udpfrag;
@@ -117,7 +118,13 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
for (skb = segs; skb; skb = skb->next) {
ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff);
- ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h));
+ if (skb_is_gso(skb))
+ payload_len = skb_shinfo(skb)->gso_size +
+ SKB_GSO_CB(skb)->data_offset +
+ skb->head - (unsigned char *)(ipv6h + 1);
+ else
+ payload_len = skb->len - nhoff - sizeof(*ipv6h);
+ ipv6h->payload_len = htons(payload_len);
skb->network_header = (u8 *)ipv6h - skb->head;
if (udpfrag) {
^ 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