|
@@ -126,7 +126,8 @@ int sysctl_tcp_invalid_ratelimit __read_mostly = HZ/2;
|
|
|
#define REXMIT_LOST 1 /* retransmit packets marked lost */
|
|
|
#define REXMIT_NEW 2 /* FRTO-style transmit of unsent/new packets */
|
|
|
|
|
|
-static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb)
|
|
|
+static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb,
|
|
|
+ unsigned int len)
|
|
|
{
|
|
|
static bool __once __read_mostly;
|
|
|
|
|
@@ -137,8 +138,9 @@ static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb)
|
|
|
|
|
|
rcu_read_lock();
|
|
|
dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
|
|
|
- pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n",
|
|
|
- dev ? dev->name : "Unknown driver");
|
|
|
+ if (!dev || len >= dev->mtu)
|
|
|
+ pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n",
|
|
|
+ dev ? dev->name : "Unknown driver");
|
|
|
rcu_read_unlock();
|
|
|
}
|
|
|
}
|
|
@@ -161,8 +163,10 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
|
|
|
if (len >= icsk->icsk_ack.rcv_mss) {
|
|
|
icsk->icsk_ack.rcv_mss = min_t(unsigned int, len,
|
|
|
tcp_sk(sk)->advmss);
|
|
|
- if (unlikely(icsk->icsk_ack.rcv_mss != len))
|
|
|
- tcp_gro_dev_warn(sk, skb);
|
|
|
+ /* Account for possibly-removed options */
|
|
|
+ if (unlikely(len > icsk->icsk_ack.rcv_mss +
|
|
|
+ MAX_TCP_OPTION_SPACE))
|
|
|
+ tcp_gro_dev_warn(sk, skb, len);
|
|
|
} else {
|
|
|
/* Otherwise, we make more careful check taking into account,
|
|
|
* that SACKs block is variable.
|