|
@@ -19,6 +19,7 @@
|
|
#include <linux/rtnetlink.h>
|
|
#include <linux/rtnetlink.h>
|
|
#include <uapi/linux/rtnetlink.h>
|
|
#include <uapi/linux/rtnetlink.h>
|
|
#include <net/pkt_sched.h>
|
|
#include <net/pkt_sched.h>
|
|
|
|
+#include <net/tcp.h>
|
|
#include <linux/module.h>
|
|
#include <linux/module.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/ip.h>
|
|
@@ -873,16 +874,14 @@ void qmi_rmnet_burst_fc_check(struct net_device *dev,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(qmi_rmnet_burst_fc_check);
|
|
EXPORT_SYMBOL(qmi_rmnet_burst_fc_check);
|
|
|
|
|
|
-static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
|
|
|
|
|
|
+static bool _qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
|
|
{
|
|
{
|
|
- unsigned int len = skb->len;
|
|
|
|
-
|
|
|
|
switch (skb->protocol) {
|
|
switch (skb->protocol) {
|
|
/* TCPv4 ACKs */
|
|
/* TCPv4 ACKs */
|
|
case htons(ETH_P_IP):
|
|
case htons(ETH_P_IP):
|
|
if ((ip_hdr(skb)->protocol == IPPROTO_TCP) &&
|
|
if ((ip_hdr(skb)->protocol == IPPROTO_TCP) &&
|
|
- (ip_hdr(skb)->ihl == 5) &&
|
|
|
|
- (len == 40 || len == 52) &&
|
|
|
|
|
|
+ (ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2) ==
|
|
|
|
+ tcp_hdr(skb)->doff << 2) &&
|
|
((tcp_flag_word(tcp_hdr(skb)) &
|
|
((tcp_flag_word(tcp_hdr(skb)) &
|
|
cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
|
|
cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
|
|
return true;
|
|
return true;
|
|
@@ -891,7 +890,8 @@ static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
|
|
/* TCPv6 ACKs */
|
|
/* TCPv6 ACKs */
|
|
case htons(ETH_P_IPV6):
|
|
case htons(ETH_P_IPV6):
|
|
if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) &&
|
|
if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) &&
|
|
- (len == 60 || len == 72) &&
|
|
|
|
|
|
+ (ntohs(ipv6_hdr(skb)->payload_len) ==
|
|
|
|
+ (tcp_hdr(skb)->doff) << 2) &&
|
|
((tcp_flag_word(tcp_hdr(skb)) &
|
|
((tcp_flag_word(tcp_hdr(skb)) &
|
|
cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
|
|
cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
|
|
return true;
|
|
return true;
|
|
@@ -901,6 +901,19 @@ static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
|
|
|
|
+{
|
|
|
|
+ /* Locally generated TCP acks */
|
|
|
|
+ if (skb_is_tcp_pure_ack(skb))
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ /* Forwarded */
|
|
|
|
+ if (unlikely(_qmi_rmnet_is_tcp_ack(skb)))
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
static int qmi_rmnet_get_queue_sa(struct qos_info *qos, struct sk_buff *skb)
|
|
static int qmi_rmnet_get_queue_sa(struct qos_info *qos, struct sk_buff *skb)
|
|
{
|
|
{
|
|
struct rmnet_flow_map *itm;
|
|
struct rmnet_flow_map *itm;
|