ip6_gre: Make o_seqno start from 0 in native mode
authorPeilin Ye <peilin.ye@bytedance.com>
Thu, 21 Apr 2022 22:08:38 +0000 (15:08 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 May 2022 07:14:36 +0000 (09:14 +0200)
[ Upstream commit fde98ae91f79cab4e020f40c35ed23cbdc59661c ]

For IP6GRE and IP6GRETAP devices, currently o_seqno starts from 1 in
native mode.  According to RFC 2890 2.2., "The first datagram is sent
with a sequence number of 0."  Fix it.

It is worth mentioning that o_seqno already starts from 0 in collect_md
mode, see the "if (tunnel->parms.collect_md)" clause in __gre6_xmit(),
where tunnel->o_seqno is passed to gre_build_header() before getting
incremented.

Fixes: c12b395a4664 ("gre: Support GRE over IPv6")
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Acked-by: William Tu <u9012063@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv6/ip6_gre.c

index 869c333..4ccbee5 100644 (file)
@@ -724,6 +724,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
 {
        struct ip6_tnl *tunnel = netdev_priv(dev);
        __be16 protocol;
+       __be16 flags;
 
        if (dev->type == ARPHRD_ETHER)
                IPCB(skb)->flags = 0;
@@ -739,7 +740,6 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
        if (tunnel->parms.collect_md) {
                struct ip_tunnel_info *tun_info;
                const struct ip_tunnel_key *key;
-               __be16 flags;
                int tun_hlen;
 
                tun_info = skb_tunnel_info_txcheck(skb);
@@ -770,15 +770,14 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
                                                      : 0);
 
        } else {
-               if (tunnel->parms.o_flags & TUNNEL_SEQ)
-                       tunnel->o_seqno++;
-
                if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen))
                        return -ENOMEM;
 
-               gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags,
+               flags = tunnel->parms.o_flags;
+
+               gre_build_header(skb, tunnel->tun_hlen, flags,
                                 protocol, tunnel->parms.o_key,
-                                htonl(tunnel->o_seqno));
+                                (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
        }
 
        return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu,