|
@@ -1672,6 +1672,7 @@ process:
|
|
|
|
|
|
if (sk->sk_state == TCP_NEW_SYN_RECV) {
|
|
|
struct request_sock *req = inet_reqsk(sk);
|
|
|
+ bool req_stolen = false;
|
|
|
struct sock *nsk;
|
|
|
|
|
|
sk = req->rsk_listener;
|
|
@@ -1694,10 +1695,20 @@ process:
|
|
|
th = (const struct tcphdr *)skb->data;
|
|
|
iph = ip_hdr(skb);
|
|
|
tcp_v4_fill_cb(skb, iph, th);
|
|
|
- nsk = tcp_check_req(sk, skb, req, false);
|
|
|
+ nsk = tcp_check_req(sk, skb, req, false, &req_stolen);
|
|
|
}
|
|
|
if (!nsk) {
|
|
|
reqsk_put(req);
|
|
|
+ if (req_stolen) {
|
|
|
+ /* Another cpu got exclusive access to req
|
|
|
+ * and created a full blown socket.
|
|
|
+ * Try to feed this packet to this socket
|
|
|
+ * instead of discarding it.
|
|
|
+ */
|
|
|
+ tcp_v4_restore_cb(skb);
|
|
|
+ sock_put(sk);
|
|
|
+ goto lookup;
|
|
|
+ }
|
|
|
goto discard_and_relse;
|
|
|
}
|
|
|
if (nsk == sk) {
|