Browse Source

qmi_rmnet: Dissect the ACKs rather than relying on helpers

Some drivers may not set the transport header when queueing packets
to the network stack. Network stack will end up setting the
transport offset to 0 in this case.

When these packets arrive in rmnet and have to be checked for
TCP ACKs, usage of standard helpers for tcp header is not possible
as it relies on the transport header offset to be set.

CRs-Fixed: 2965067
Change-Id: I50d53b7762fd75d1b17ccc6765abe65568aaa4e0
Signed-off-by: Subash Abhinov Kasiviswanathan <[email protected]>
Subash Abhinov Kasiviswanathan 4 years ago
parent
commit
0ad2e0e18b
1 changed files with 19 additions and 20 deletions
  1. 19 20
      core/qmi_rmnet.c

+ 19 - 20
core/qmi_rmnet.c

@@ -1008,28 +1008,27 @@ EXPORT_SYMBOL(qmi_rmnet_burst_fc_check);
 
 static bool _qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
 {
-	switch (skb->protocol) {
-	/* TCPv4 ACKs */
-	case htons(ETH_P_IP):
-		if ((ip_hdr(skb)->protocol == IPPROTO_TCP) &&
-		    (ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2) ==
-		      tcp_hdr(skb)->doff << 2) &&
-		    ((tcp_flag_word(tcp_hdr(skb)) &
-		      cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
-			return true;
-		break;
-
-	/* TCPv6 ACKs */
-	case htons(ETH_P_IPV6):
-		if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) &&
-		    (ntohs(ipv6_hdr(skb)->payload_len) ==
-		      (tcp_hdr(skb)->doff) << 2) &&
-		    ((tcp_flag_word(tcp_hdr(skb)) &
-		      cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
-			return true;
-		break;
+	struct tcphdr *th;
+	int ip_hdr_len;
+	int ip_payload_len;
+
+	if (skb->protocol == htons(ETH_P_IP) &&
+	    ip_hdr(skb)->protocol == IPPROTO_TCP) {
+		ip_hdr_len = ip_hdr(skb)->ihl << 2;
+		ip_payload_len = ntohs(ip_hdr(skb)->tot_len) - ip_hdr_len;
+	} else if (skb->protocol == htons(ETH_P_IPV6) &&
+		   ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) {
+		ip_hdr_len = sizeof(struct ipv6hdr);
+		ip_payload_len = ntohs(ipv6_hdr(skb)->payload_len);
+	} else {
+		return false;
 	}
 
+	th = (struct tcphdr *)(skb->data + ip_hdr_len);
+	if ((ip_payload_len == th->doff << 2) &&
+	    ((tcp_flag_word(th) & cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
+		return true;
+
 	return false;
 }