tcp: Fix conditions to determine checksum offload
authorTom Herbert <tom@herbertland.com>
Mon, 14 Dec 2015 19:19:45 +0000 (11:19 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Dec 2015 21:50:20 +0000 (16:50 -0500)
In tcp_send_sendpage and tcp_sendmsg we check the route capabilities to
determine if checksum offload can be performed. This check currently
does not take the IP protocol into account for devices that advertise
only one of NETIF_F_IPV6_CSUM or NETIF_F_IP_CSUM. This patch adds a
function to check capabilities for checksum offload with a socket
called sk_check_csum_caps. This function checks for specific IPv4 or
IPv6 offload support based on the family of the socket.

Signed-off-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sock.h
net/ipv4/tcp.c

index 0ca22b014de1a0a31e539a89e35fa5cc14875384..ab0269f4b2cc2ea6597d43dd663c860579d02ca2 100644 (file)
@@ -1791,6 +1791,15 @@ static inline void sk_nocaps_add(struct sock *sk, netdev_features_t flags)
        sk->sk_route_caps &= ~flags;
 }
 
+static inline bool sk_check_csum_caps(struct sock *sk)
+{
+       return (sk->sk_route_caps & NETIF_F_HW_CSUM) ||
+              (sk->sk_family == PF_INET &&
+               (sk->sk_route_caps & NETIF_F_IP_CSUM)) ||
+              (sk->sk_family == PF_INET6 &&
+               (sk->sk_route_caps & NETIF_F_IPV6_CSUM));
+}
+
 static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb,
                                           struct iov_iter *from, char *to,
                                           int copy, int offset)
index cf7ef7be79f0de3618dd1156b1217cd515153c53..92b3e61b847d683d8c74eb64062828491a026b8a 100644 (file)
@@ -1018,7 +1018,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset,
        ssize_t res;
 
        if (!(sk->sk_route_caps & NETIF_F_SG) ||
-           !(sk->sk_route_caps & NETIF_F_CSUM_MASK))
+           !sk_check_csum_caps(sk))
                return sock_no_sendpage(sk->sk_socket, page, offset, size,
                                        flags);
 
@@ -1175,7 +1175,7 @@ new_segment:
                        /*
                         * Check whether we can use HW checksum.
                         */
-                       if (sk->sk_route_caps & NETIF_F_CSUM_MASK)
+                       if (sk_check_csum_caps(sk))
                                skb->ip_summed = CHECKSUM_PARTIAL;
 
                        skb_entail(sk, skb);