]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'inet_csums_part3'
authorDavid S. Miller <davem@davemloft.net>
Fri, 23 May 2014 20:29:04 +0000 (16:29 -0400)
committerDavid S. Miller <davem@davemloft.net>
Fri, 23 May 2014 20:29:04 +0000 (16:29 -0400)
Tom Herbert says:

====================
net: Checksum offload changes - Part III

I am working on overhauling RX checksum offload. Goals of this effort
are:

- Specify what exactly it means when driver returns CHECKSUM_UNNECESSARY
- Preserve CHECKSUM_COMPLETE through encapsulation layers
- Don't do skb_checksum more than once per packet
- Unify GRO and non-GRO csum verification as much as possible
- Unify the checksum functions (checksum_init)
- Simply code

What is in this third patch set:

- Remove sk_no_check from sunrpc (doesn't seem to have any effect)
- Eliminate no_check from protosw. All protocols are using default of
  zero for this
- Split sk_no_check into sk_no_check_tx and sk_no_check_rx
- Make enabling of UDP6 more restrictive and explicit
- Support zero UDP6 checksums in l2tp

V2: Took out vxlan changes to set zero csums in IPv6, this will
    be in a later patch set.
V3: Fixed bug in restricting UDP6 checksums.

Please review carefully and test if possible, mucking with basic
checksum functions is always a little precarious :-)
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
31 files changed:
drivers/scsi/iscsi_tcp.c
include/linux/udp.h
include/net/protocol.h
include/net/sock.h
include/net/udp.h
include/uapi/linux/l2tp.h
include/uapi/linux/udp.h
net/appletalk/ddp.c
net/core/sock.c
net/dccp/ipv4.c
net/decnet/af_decnet.c
net/ipv4/af_inet.c
net/ipv4/udp.c
net/ipv4/udplite.c
net/ipv6/af_inet6.c
net/ipv6/ping.c
net/ipv6/raw.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udplite.c
net/ipx/af_ipx.c
net/ipx/ipx_route.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/l2tp/l2tp_netlink.c
net/sctp/ipv6.c
net/sctp/protocol.c
net/sctp/socket.c
net/sunrpc/xprtsock.c

index 11854845393bf9cc13688ff3895339997822fa61..a669f2d11c314e380eb2aa90714b91eb0064f781 100644 (file)
@@ -244,7 +244,7 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_conn *conn)
        sk->sk_data_ready   = tcp_sw_conn->old_data_ready;
        sk->sk_state_change = tcp_sw_conn->old_state_change;
        sk->sk_write_space  = tcp_sw_conn->old_write_space;
-       sk->sk_no_check  = 0;
+       sk->sk_no_check_tx = 0;
        write_unlock_bh(&sk->sk_callback_lock);
 }
 
index 42278bbf7a882d90360d141db9c8cc1b1eca1719..247cfdcc4b08bbf377ff5819ebd02683806b0c83 100644 (file)
@@ -47,7 +47,9 @@ struct udp_sock {
 #define udp_portaddr_node      inet.sk.__sk_common.skc_portaddr_node
        int              pending;       /* Any pending frames ? */
        unsigned int     corkflag;      /* Cork is required */
-       __u16            encap_type;    /* Is this an Encapsulation socket? */
+       __u8             encap_type;    /* Is this an Encapsulation socket? */
+       unsigned char    no_check6_tx:1,/* Send zero UDP6 checksums on TX? */
+                        no_check6_rx:1;/* Allow zero UDP6 checksums on RX? */
        /*
         * Following member retains the information to create a UDP header
         * when the socket is uncorked.
@@ -76,6 +78,26 @@ static inline struct udp_sock *udp_sk(const struct sock *sk)
        return (struct udp_sock *)sk;
 }
 
+static inline void udp_set_no_check6_tx(struct sock *sk, bool val)
+{
+       udp_sk(sk)->no_check6_tx = val;
+}
+
+static inline void udp_set_no_check6_rx(struct sock *sk, bool val)
+{
+       udp_sk(sk)->no_check6_rx = val;
+}
+
+static inline bool udp_get_no_check6_tx(struct sock *sk)
+{
+       return udp_sk(sk)->no_check6_tx;
+}
+
+static inline bool udp_get_no_check6_rx(struct sock *sk)
+{
+       return udp_sk(sk)->no_check6_rx;
+}
+
 #define udp_portaddr_for_each_entry(__sk, node, list) \
        hlist_nulls_for_each_entry(__sk, node, list, __sk_common.skc_portaddr_node)
 
index a7e986b081474a51da5011fc19b300d358b0b871..d6fcc1fcdb5b0928a0bd89279e11819a9cc3169d 100644 (file)
@@ -86,7 +86,6 @@ struct inet_protosw {
        struct proto     *prot;
        const struct proto_ops *ops;
   
-       char             no_check;   /* checksum on rcv/xmit/none? */
        unsigned char    flags;      /* See INET_PROTOSW_* below.  */
 };
 #define INET_PROTOSW_REUSE 0x01             /* Are ports automatically reusable? */
index 21569cf456ed54459a537e5a6cf02349a2a8413c..07b7fcd60d808a33f9e6fff208c07fe412da8c7e 100644 (file)
@@ -243,7 +243,8 @@ struct cg_proto;
   *    @sk_sndbuf: size of send buffer in bytes
   *    @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
   *               %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
-  *    @sk_no_check: %SO_NO_CHECK setting, whether or not checkup packets
+  *    @sk_no_check_tx: %SO_NO_CHECK setting, set checksum in TX packets
+  *    @sk_no_check_rx: allow zero checksum in RX packets
   *    @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
   *    @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
   *    @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
@@ -371,7 +372,8 @@ struct sock {
        struct sk_buff_head     sk_write_queue;
        kmemcheck_bitfield_begin(flags);
        unsigned int            sk_shutdown  : 2,
-                               sk_no_check  : 2,
+                               sk_no_check_tx : 1,
+                               sk_no_check_rx : 1,
                                sk_userlocks : 4,
                                sk_protocol  : 8,
                                sk_type      : 16;
index a24f0f3e107f67c71b256cd4fb85d04b2389fb7a..5eb86874bcd68bc5b5d1c0069db35411b0573b85 100644 (file)
@@ -95,15 +95,6 @@ static inline struct udp_hslot *udp_hashslot2(struct udp_table *table,
        return &table->hash2[hash & table->mask];
 }
 
-/* Note: this must match 'valbool' in sock_setsockopt */
-#define UDP_CSUM_NOXMIT                1
-
-/* Used by SunRPC/xprt layer. */
-#define UDP_CSUM_NORCV         2
-
-/* Default, as per the RFC, is to always do csums. */
-#define UDP_CSUM_DEFAULT       0
-
 extern struct proto udp_prot;
 
 extern atomic_long_t udp_memory_allocated;
index 8adb681603273c287f25be055c0258c8a2a73c65..21caa2631c209fdc0f0c7e21591e0507fc3e0b9a 100644 (file)
@@ -124,6 +124,8 @@ enum {
        L2TP_ATTR_STATS,                /* nested */
        L2TP_ATTR_IP6_SADDR,            /* struct in6_addr */
        L2TP_ATTR_IP6_DADDR,            /* struct in6_addr */
+       L2TP_ATTR_UDP_ZERO_CSUM6_TX,    /* u8 */
+       L2TP_ATTR_UDP_ZERO_CSUM6_RX,    /* u8 */
        __L2TP_ATTR_MAX,
 };
 
index e2bcfd75a30d38d37475cef6e0382e1081d5a3b0..16574ea18f0cf62d743287779ffaed6205d120d0 100644 (file)
@@ -29,6 +29,8 @@ struct udphdr {
 /* UDP socket options */
 #define UDP_CORK       1       /* Never send partially complete segments */
 #define UDP_ENCAP      100     /* Set the socket to accept encapsulated packets */
+#define UDP_NO_CHECK6_TX 101   /* Disable sending checksum for UDP6X */
+#define UDP_NO_CHECK6_RX 102   /* Disable accpeting checksum for UDP6 */
 
 /* UDP encapsulation types */
 #define UDP_ENCAP_ESPINUDP_NON_IKE     1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
index 786ee2f83d5fea1dbfd6bb2660544d7f88e1eff2..01a1082e02b3157b3abc84e6b23844ed3a26f2f2 100644 (file)
@@ -1669,7 +1669,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                goto out;
        }
 
-       if (sk->sk_no_check == 1)
+       if (sk->sk_no_check_tx)
                ddp->deh_sum = 0;
        else
                ddp->deh_sum = atalk_checksum(skb, len + sizeof(*ddp));
index 664ee4295b6f6ec38fb4f89d11c52eaa383a15d1..026e01f70274f8a5550af6a7a06fd6846735e4ae 100644 (file)
@@ -784,7 +784,7 @@ set_rcvbuf:
                break;
 
        case SO_NO_CHECK:
-               sk->sk_no_check = valbool;
+               sk->sk_no_check_tx = valbool;
                break;
 
        case SO_PRIORITY:
@@ -1064,7 +1064,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                break;
 
        case SO_NO_CHECK:
-               v.val = sk->sk_no_check;
+               v.val = sk->sk_no_check_tx;
                break;
 
        case SO_PRIORITY:
index 22b5d818b2001b177b765cbb67eb2551e87502ce..6ca645c4b48e8b56a88f7d549b073fb6dc82eeb7 100644 (file)
@@ -1024,7 +1024,6 @@ static struct inet_protosw dccp_v4_protosw = {
        .protocol       = IPPROTO_DCCP,
        .prot           = &dccp_v4_prot,
        .ops            = &inet_dccp_ops,
-       .no_check       = 0,
        .flags          = INET_PROTOSW_ICSK,
 };
 
index 4c04848953bdb4caddeae9debd195ea3d004ee0d..ae011b46c0710fc96204deda6bddb1d912d78f22 100644 (file)
@@ -481,7 +481,7 @@ static struct sock *dn_alloc_sock(struct net *net, struct socket *sock, gfp_t gf
 
        sk->sk_backlog_rcv = dn_nsp_backlog_rcv;
        sk->sk_destruct    = dn_destruct;
-       sk->sk_no_check    = 1;
+       sk->sk_no_check_tx = 1;
        sk->sk_family      = PF_DECnet;
        sk->sk_protocol    = 0;
        sk->sk_allocation  = gfp;
index 279132bcadd92621a3e23e382fe5f03d48dac313..0e9bb08a91e424ca1f5c0351825aaa32d0dc3734 100644 (file)
@@ -254,7 +254,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
        struct inet_sock *inet;
        struct proto *answer_prot;
        unsigned char answer_flags;
-       char answer_no_check;
        int try_loading_module = 0;
        int err;
 
@@ -312,7 +311,6 @@ lookup_protocol:
 
        sock->ops = answer->ops;
        answer_prot = answer->prot;
-       answer_no_check = answer->no_check;
        answer_flags = answer->flags;
        rcu_read_unlock();
 
@@ -324,7 +322,6 @@ lookup_protocol:
                goto out;
 
        err = 0;
-       sk->sk_no_check = answer_no_check;
        if (INET_PROTOSW_REUSE & answer_flags)
                sk->sk_reuse = SK_CAN_REUSE;
 
@@ -1002,7 +999,6 @@ static struct inet_protosw inetsw_array[] =
                .protocol =   IPPROTO_TCP,
                .prot =       &tcp_prot,
                .ops =        &inet_stream_ops,
-               .no_check =   0,
                .flags =      INET_PROTOSW_PERMANENT |
                              INET_PROTOSW_ICSK,
        },
@@ -1012,7 +1008,6 @@ static struct inet_protosw inetsw_array[] =
                .protocol =   IPPROTO_UDP,
                .prot =       &udp_prot,
                .ops =        &inet_dgram_ops,
-               .no_check =   UDP_CSUM_DEFAULT,
                .flags =      INET_PROTOSW_PERMANENT,
        },
 
@@ -1021,7 +1016,6 @@ static struct inet_protosw inetsw_array[] =
                .protocol =   IPPROTO_ICMP,
                .prot =       &ping_prot,
                .ops =        &inet_dgram_ops,
-               .no_check =   UDP_CSUM_DEFAULT,
                .flags =      INET_PROTOSW_REUSE,
        },
 
@@ -1030,7 +1024,6 @@ static struct inet_protosw inetsw_array[] =
               .protocol =   IPPROTO_IP,        /* wild card */
               .prot =       &raw_prot,
               .ops =        &inet_sockraw_ops,
-              .no_check =   UDP_CSUM_DEFAULT,
               .flags =      INET_PROTOSW_REUSE,
        }
 };
index 590532a7bd2d39c582f95d47abba30e45cdbddfe..e07d52b8617a867aefedd3e4bb8dfb4bfd50154b 100644 (file)
@@ -785,7 +785,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4)
        if (is_udplite)                                  /*     UDP-Lite      */
                csum = udplite_csum(skb);
 
-       else if (sk->sk_no_check == UDP_CSUM_NOXMIT) {   /* UDP csum disabled */
+       else if (sk->sk_no_check_tx) {   /* UDP csum disabled */
 
                skb->ip_summed = CHECKSUM_NONE;
                goto send;
@@ -1968,7 +1968,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                       int (*push_pending_frames)(struct sock *))
 {
        struct udp_sock *up = udp_sk(sk);
-       int val;
+       int val, valbool;
        int err = 0;
        int is_udplite = IS_UDPLITE(sk);
 
@@ -1978,6 +1978,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
        if (get_user(val, (int __user *)optval))
                return -EFAULT;
 
+       valbool = val ? 1 : 0;
+
        switch (optname) {
        case UDP_CORK:
                if (val != 0) {
@@ -2007,6 +2009,14 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                }
                break;
 
+       case UDP_NO_CHECK6_TX:
+               up->no_check6_tx = valbool;
+               break;
+
+       case UDP_NO_CHECK6_RX:
+               up->no_check6_rx = valbool;
+               break;
+
        /*
         *      UDP-Lite's partial checksum coverage (RFC 3828).
         */
@@ -2089,6 +2099,14 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
                val = up->encap_type;
                break;
 
+       case UDP_NO_CHECK6_TX:
+               val = up->no_check6_tx;
+               break;
+
+       case UDP_NO_CHECK6_RX:
+               val = up->no_check6_rx;
+               break;
+
        /* The following two cannot be changed on UDP sockets, the return is
         * always 0 (which corresponds to the full checksum coverage of UDP). */
        case UDPLITE_SEND_CSCOV:
index 2c46acd4cc3636e33fb240a963367ec629b482b5..3b3efbda48e13941b35388238508706844c043aa 100644 (file)
@@ -70,7 +70,6 @@ static struct inet_protosw udplite4_protosw = {
        .protocol       =  IPPROTO_UDPLITE,
        .prot           =  &udplite_prot,
        .ops            =  &inet_dgram_ops,
-       .no_check       =  0,           /* must checksum (RFC 3828) */
        .flags          =  INET_PROTOSW_PERMANENT,
 };
 
index dc47cc757b80b6df3fbe99f7d2ead9a335689126..7cb4392690dd614b1672ad51cc57bbe36218e34c 100644 (file)
@@ -106,7 +106,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
        struct inet_protosw *answer;
        struct proto *answer_prot;
        unsigned char answer_flags;
-       char answer_no_check;
        int try_loading_module = 0;
        int err;
 
@@ -162,7 +161,6 @@ lookup_protocol:
 
        sock->ops = answer->ops;
        answer_prot = answer->prot;
-       answer_no_check = answer->no_check;
        answer_flags = answer->flags;
        rcu_read_unlock();
 
@@ -176,7 +174,6 @@ lookup_protocol:
        sock_init_data(sock, sk);
 
        err = 0;
-       sk->sk_no_check = answer_no_check;
        if (INET_PROTOSW_REUSE & answer_flags)
                sk->sk_reuse = SK_CAN_REUSE;
 
index a2a1d80dfe0c0e3cab9ed1eadd51bb3401797b11..5b7a1ed2aba95a837a0063b96cb9803ff8925f0c 100644 (file)
@@ -51,7 +51,6 @@ static struct inet_protosw pingv6_protosw = {
        .protocol =  IPPROTO_ICMPV6,
        .prot =      &pingv6_prot,
        .ops =       &inet6_dgram_ops,
-       .no_check =  UDP_CSUM_DEFAULT,
        .flags =     INET_PROTOSW_REUSE,
 };
 
index dddfb5fa2b7a289f80fcf81d67ff332a678ed398..b2dc60b0c76403d38a6a96c8a1c299977ecb7bad 100644 (file)
@@ -1322,7 +1322,6 @@ static struct inet_protosw rawv6_protosw = {
        .protocol       = IPPROTO_IP,   /* wild card */
        .prot           = &rawv6_prot,
        .ops            = &inet6_sockraw_ops,
-       .no_check       = UDP_CSUM_DEFAULT,
        .flags          = INET_PROTOSW_REUSE,
 };
 
index f07b2abba3592b729248dfce3c06ec34f3741c32..229239ad96b1645de84bfc5b0ad76311e295f82c 100644 (file)
@@ -1992,7 +1992,6 @@ static struct inet_protosw tcpv6_protosw = {
        .protocol       =       IPPROTO_TCP,
        .prot           =       &tcpv6_prot,
        .ops            =       &inet6_stream_ops,
-       .no_check       =       0,
        .flags          =       INET_PROTOSW_PERMANENT |
                                INET_PROTOSW_ICSK,
 };
index 7edf096867c4205342152ea8a5fba6f7ad9a4a66..60325236446a97fbb753ddb0c29ac31accf73ed1 100644 (file)
@@ -794,10 +794,10 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
        dif = inet6_iif(skb);
        sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif);
        while (sk) {
-               /* If zero checksum and sk_no_check is not on for
+               /* If zero checksum and no_check is not on for
                 * the socket then skip it.
                 */
-               if (uh->check || sk->sk_no_check)
+               if (uh->check || udp_sk(sk)->no_check6_rx)
                        stack[count++] = sk;
 
                sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr,
@@ -887,7 +887,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
        if (sk != NULL) {
                int ret;
 
-               if (!uh->check && !sk->sk_no_check) {
+               if (!uh->check && !udp_sk(sk)->no_check6_rx) {
                        sock_put(sk);
                        udp6_csum_zero_error(skb);
                        goto csum_error;
@@ -1037,7 +1037,7 @@ static int udp_v6_push_pending_frames(struct sock *sk)
 
        if (is_udplite)
                csum = udplite_csum_outgoing(sk, skb);
-       else if (sk->sk_no_check == UDP_CSUM_NOXMIT) {   /* UDP csum disabled */
+       else if (up->no_check6_tx) {   /* UDP csum disabled */
                skb->ip_summed = CHECKSUM_NONE;
                goto send;
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
@@ -1507,7 +1507,6 @@ static struct inet_protosw udpv6_protosw = {
        .protocol =  IPPROTO_UDP,
        .prot =      &udpv6_prot,
        .ops =       &inet6_dgram_ops,
-       .no_check =  UDP_CSUM_DEFAULT,
        .flags =     INET_PROTOSW_PERMANENT,
 };
 
index dfcc4be46898281f09038bbd7638edfefa04ea3e..9cf097e206e931c6e3c184f22b8adcabedc4c03a 100644 (file)
@@ -64,7 +64,6 @@ static struct inet_protosw udplite6_protosw = {
        .protocol       = IPPROTO_UDPLITE,
        .prot           = &udplitev6_prot,
        .ops            = &inet6_dgram_ops,
-       .no_check       = 0,
        .flags          = INET_PROTOSW_PERMANENT,
 };
 
index 41e4e93cb3aae37df41ff419ef34be9c2255b5cc..91729b807c7d041ae379e89df335acefe5218635 100644 (file)
@@ -1353,7 +1353,7 @@ static int ipx_create(struct net *net, struct socket *sock, int protocol,
 
        sk_refcnt_debug_inc(sk);
        sock_init_data(sock, sk);
-       sk->sk_no_check = 1;            /* Checksum off by default */
+       sk->sk_no_check_tx = 1;         /* Checksum off by default */
        sock->ops = &ipx_dgram_ops;
        rc = 0;
 out:
index c1f03185c5e115ffe359e39a0bfb17efe8d4c38a..67e7ad3d46b1fb4489a175836351607e7f5ae741 100644 (file)
@@ -236,7 +236,8 @@ int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
        }
 
        /* Apply checksum. Not allowed on 802.3 links. */
-       if (sk->sk_no_check || intrfc->if_dlink_type == htons(IPX_FRAME_8023))
+       if (sk->sk_no_check_tx ||
+           intrfc->if_dlink_type == htons(IPX_FRAME_8023))
                ipx->ipx_checksum = htons(0xFFFF);
        else
                ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
index ed0716a075ba928f5d4c8942eeed9839d3389f3f..379558014b60f40a19964fdbe6c0f8ea9fd3c03e 100644 (file)
@@ -1102,7 +1102,9 @@ static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb,
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct udphdr *uh = udp_hdr(skb);
 
-       if (!skb_dst(skb) || !skb_dst(skb)->dev ||
+       if (udp_get_no_check6_tx(sk))
+               skb->ip_summed = CHECKSUM_NONE;
+       else if (!skb_dst(skb) || !skb_dst(skb)->dev ||
            !(skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) {
                __wsum csum = skb_checksum(skb, 0, udp_len, 0);
                skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1188,7 +1190,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
                        l2tp_xmit_ipv6_csum(sk, skb, udp_len);
                else
 #endif
-               if (sk->sk_no_check == UDP_CSUM_NOXMIT)
+               if (sk->sk_no_check_tx)
                        skb->ip_summed = CHECKSUM_NONE;
                else if ((skb_dst(skb) && skb_dst(skb)->dev) &&
                         (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) {
@@ -1435,6 +1437,11 @@ static int l2tp_tunnel_sock_create(struct net *net,
                                             sizeof(udp6_addr), 0);
                        if (err < 0)
                                goto out;
+
+                       if (cfg->udp6_zero_tx_checksums)
+                               udp_set_no_check6_tx(sock->sk, true);
+                       if (cfg->udp6_zero_rx_checksums)
+                               udp_set_no_check6_rx(sock->sk, true);
                } else
 #endif
                {
@@ -1463,7 +1470,7 @@ static int l2tp_tunnel_sock_create(struct net *net,
                }
 
                if (!cfg->use_udp_checksums)
-                       sock->sk->sk_no_check = UDP_CSUM_NOXMIT;
+                       sock->sk->sk_no_check_tx = 1;
 
                break;
 
index 3f93ccd6ba9768fe171f4e35e79d613226c1dbc7..68aa9ffd4ae4d972cdd57ea742ddf3b78ba497d6 100644 (file)
@@ -162,7 +162,9 @@ struct l2tp_tunnel_cfg {
 #endif
        u16                     local_udp_port;
        u16                     peer_udp_port;
-       unsigned int            use_udp_checksums:1;
+       unsigned int            use_udp_checksums:1,
+                               udp6_zero_tx_checksums:1,
+                               udp6_zero_rx_checksums:1;
 };
 
 struct l2tp_tunnel {
index 3397fe6897c0326d3efb2277a2824f5c2038d3c4..369a9822488c45fc10be28ca00300e9382645a9e 100644 (file)
@@ -606,7 +606,6 @@ static struct inet_protosw l2tp_ip_protosw = {
        .protocol       = IPPROTO_L2TP,
        .prot           = &l2tp_ip_prot,
        .ops            = &l2tp_ip_ops,
-       .no_check       = 0,
 };
 
 static struct net_protocol l2tp_ip_protocol __read_mostly = {
index e472d44a3b91eb74e5614d22c4c7c68811ca4a84..f3f98a156ceed8ebc5843368aa0d1988175e5fc7 100644 (file)
@@ -755,7 +755,6 @@ static struct inet_protosw l2tp_ip6_protosw = {
        .protocol       = IPPROTO_L2TP,
        .prot           = &l2tp_ip6_prot,
        .ops            = &l2tp_ip6_ops,
-       .no_check       = 0,
 };
 
 static struct inet6_protocol l2tp_ip6_protocol __read_mostly = {
index bd7387adea9eff25ce7ffd0683589dcdcc020ad0..0ac907adb2f472c0d49508ca6843363db27129b1 100644 (file)
@@ -161,6 +161,13 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
                        cfg.peer_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_DPORT]);
                if (info->attrs[L2TP_ATTR_UDP_CSUM])
                        cfg.use_udp_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_CSUM]);
+
+#if IS_ENABLED(CONFIG_IPV6)
+               if (info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX])
+                       cfg.udp6_zero_tx_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX]);
+               if (info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX])
+                       cfg.udp6_zero_rx_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX]);
+#endif
        }
 
        if (info->attrs[L2TP_ATTR_DEBUG])
@@ -297,8 +304,7 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
        case L2TP_ENCAPTYPE_UDP:
                if (nla_put_u16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport)) ||
                    nla_put_u16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport)) ||
-                   nla_put_u8(skb, L2TP_ATTR_UDP_CSUM,
-                              (sk->sk_no_check != UDP_CSUM_NOXMIT)))
+                   nla_put_u8(skb, L2TP_ATTR_UDP_CSUM, !sk->sk_no_check_tx))
                        goto nla_put_failure;
                /* NOBREAK */
        case L2TP_ENCAPTYPE_IP:
index 4dc5d9e083115983595edcdf10641e78d1fdfb41..1999592ba88c9f3d574428e1ce076c10f724c13a 100644 (file)
@@ -943,7 +943,6 @@ static struct inet_protosw sctpv6_seqpacket_protosw = {
        .protocol      = IPPROTO_SCTP,
        .prot          = &sctpv6_prot,
        .ops           = &inet6_seqpacket_ops,
-       .no_check      = 0,
        .flags         = SCTP_PROTOSW_FLAG
 };
 static struct inet_protosw sctpv6_stream_protosw = {
@@ -951,7 +950,6 @@ static struct inet_protosw sctpv6_stream_protosw = {
        .protocol      = IPPROTO_SCTP,
        .prot          = &sctpv6_prot,
        .ops           = &inet6_seqpacket_ops,
-       .no_check      = 0,
        .flags         = SCTP_PROTOSW_FLAG,
 };
 
index af5afca4b85a2df42c998474fbae14c057509c13..6789d785e698325afc7c8cfd65d1b69c2e50047a 100644 (file)
@@ -1017,7 +1017,6 @@ static struct inet_protosw sctp_seqpacket_protosw = {
        .protocol   = IPPROTO_SCTP,
        .prot       = &sctp_prot,
        .ops        = &inet_seqpacket_ops,
-       .no_check   = 0,
        .flags      = SCTP_PROTOSW_FLAG
 };
 static struct inet_protosw sctp_stream_protosw = {
@@ -1025,7 +1024,6 @@ static struct inet_protosw sctp_stream_protosw = {
        .protocol   = IPPROTO_SCTP,
        .prot       = &sctp_prot,
        .ops        = &inet_seqpacket_ops,
-       .no_check   = 0,
        .flags      = SCTP_PROTOSW_FLAG
 };
 
index 2af76eaba8f784e4d7b4276c8c2ef46b1ef30925..429899689408caec64cf5c36b4eb0b00369f8e48 100644 (file)
@@ -6946,7 +6946,8 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newsk->sk_type = sk->sk_type;
        newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
        newsk->sk_flags = sk->sk_flags;
-       newsk->sk_no_check = sk->sk_no_check;
+       newsk->sk_no_check_tx = sk->sk_no_check_tx;
+       newsk->sk_no_check_rx = sk->sk_no_check_rx;
        newsk->sk_reuse = sk->sk_reuse;
 
        newsk->sk_shutdown = sk->sk_shutdown;
index 25a3dcf15cae97ff54f315412848c269acef3b01..1dec6043e4de7f208f2d1df23ae658868c004f5a 100644 (file)
@@ -866,8 +866,6 @@ static void xs_reset_transport(struct sock_xprt *transport)
        xs_restore_old_callbacks(transport, sk);
        write_unlock_bh(&sk->sk_callback_lock);
 
-       sk->sk_no_check = 0;
-
        trace_rpc_socket_close(&transport->xprt, sock);
        sock_release(sock);
 }
@@ -2046,7 +2044,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_udp_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_no_check = UDP_CSUM_NORCV;
                sk->sk_allocation = GFP_ATOMIC;
 
                xprt_set_connected(xprt);