[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CANn89iJjwuN6hv7CuvR3n5efwo4MjV+Xe2byK7wy4k0AXkJkzg@mail.gmail.com>
Date: Thu, 3 Feb 2022 17:14:44 -0800
From: Eric Dumazet <edumazet@...gle.com>
To: Alexander Duyck <alexander.duyck@...il.com>
Cc: Eric Dumazet <eric.dumazet@...il.com>,
"David S . Miller" <davem@...emloft.net>,
Jakub Kicinski <kuba@...nel.org>,
netdev <netdev@...r.kernel.org>, Coco Li <lixiaoyan@...gle.com>
Subject: Re: [PATCH net-next 05/15] ipv6/gso: remove temporary HBH/jumbo header
On Thu, Feb 3, 2022 at 4:27 PM Eric Dumazet <edumazet@...gle.com> wrote:
>
> On Thu, Feb 3, 2022 at 4:05 PM Alexander Duyck
> <alexander.duyck@...il.com> wrote:
> >
>
> > I get that. What I was getting at was that we might be able to process
> > it in ipv6_gso_segment before we hand it off to either TCP or UDP gso
> > handlers to segment.
> >
> > The general idea being we keep the IPv6 specific bits in the IPv6
> > specific code instead of having the skb_segment function now have to
> > understand IPv6 packets. So what we would end up doing is having to do
> > an skb_cow to replace the skb->head if any clones might be holding on
> > it, and then just chop off the HBH jumbo header before we start the
> > segmenting.
> >
> > The risk would be that we waste cycles removing the HBH header for a
> > frame that is going to fail, but I am not sure how likely a scenario
> > that is or if we need to optimize for that.
>
> I guess I can try this for the next version, thanks.
I came up with:
ommit 147f17169ccc6c2c38ea802e5728528ed54f492d
Author: Eric Dumazet <edumazet@...gle.com>
Date: Sat Nov 20 16:49:35 2021 -0800
ipv6/gso: remove temporary HBH/jumbo header
ipv6 tcp and gro stacks will soon be able to build big TCP packets,
with an added temporary Hop By Hop header.
If GSO is involved for these large packets, we need to remove
the temporary HBH header before segmentation happens.
v2: perform HBH removal from ipv6_gso_segment() instead of
skb_segment() (Alexander feedback)
Signed-off-by: Eric Dumazet <edumazet@...gle.com>
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index ea2a4351b654f8bc96503aae2b9adcd478e1f8b2..a850c18dae0dfedccb9d956bf1ec9fa6b0368c6b
100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -464,6 +464,38 @@ bool ipv6_opt_accepted(const struct sock *sk,
const struct sk_buff *skb,
struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
struct ipv6_txoptions *opt);
+/* This helper is specialized for BIG TCP needs.
+ * It assumes the hop_jumbo_hdr will immediately follow the IPV6 header.
+ * It assumes headers are already in skb->head, thus the sk argument
is only read.
+ */
+static inline bool ipv6_has_hopopt_jumbo(const struct sk_buff *skb)
+{
+ const struct hop_jumbo_hdr *jhdr;
+ const struct ipv6hdr *nhdr;
+
+ if (likely(skb->len <= GRO_MAX_SIZE))
+ return false;
+
+ if (skb->protocol != htons(ETH_P_IPV6))
+ return false;
+
+ if (skb_network_offset(skb) +
+ sizeof(struct ipv6hdr) +
+ sizeof(struct hop_jumbo_hdr) > skb_headlen(skb))
+ return false;
+
+ nhdr = ipv6_hdr(skb);
+
+ if (nhdr->nexthdr != NEXTHDR_HOP)
+ return false;
+
+ jhdr = (const struct hop_jumbo_hdr *) (nhdr + 1);
+ if (jhdr->tlv_type != IPV6_TLV_JUMBO || jhdr->hdrlen != 0 ||
+ jhdr->nexthdr != IPPROTO_TCP)
+ return false;
+ return true;
+}
+
static inline bool ipv6_accept_ra(struct inet6_dev *idev)
{
/* If forwarding is enabled, RA are not accepted unless the special
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index d37a79a8554e92a1dcaa6fd023cafe2114841ece..7f65097c8f30fa19a8c9c265eb4f027e91848021
100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -87,6 +87,27 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
bool gso_partial;
skb_reset_network_header(skb);
+ if (ipv6_has_hopopt_jumbo(skb)) {
+ const int hophdr_len = sizeof(struct hop_jumbo_hdr);
+ int err;
+
+ err = skb_cow_head(skb, 0);
+ if (err < 0)
+ return ERR_PTR(err);
+
+ /* remove the HBH header.
+ * Layout: [Ethernet header][IPv6 header][HBH][TCP header]
+ */
+ memmove(skb->data + hophdr_len,
+ skb->data,
+ ETH_HLEN + sizeof(struct ipv6hdr));
+ skb->data += hophdr_len;
+ skb->len -= hophdr_len;
+ skb->network_header += hophdr_len;
+ skb->mac_header += hophdr_len;
+ ipv6h = (struct ipv6hdr *)skb->data;
+ ipv6h->nexthdr = IPPROTO_TCP;
+ }
nhoff = skb_network_header(skb) - skb_mac_header(skb);
if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
goto out;
Powered by blists - more mailing lists