Merge branches 'acpi-scan', 'acpi-pnp' and 'acpi-sleep'
[linux-2.6-microblaze.git] / net / ipv4 / tcp_ipv4.c
index 592c739..58207c7 100644 (file)
@@ -575,7 +575,7 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
        case TCP_SYN_SENT:
        case TCP_SYN_RECV:
                /* Only in fast or simultaneous open. If a fast open socket is
-                * is already accepted it is treated as a connected one below.
+                * already accepted it is treated as a connected one below.
                 */
                if (fastopen && !fastopen->sk)
                        break;
@@ -965,26 +965,38 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
                              struct flowi *fl,
                              struct request_sock *req,
                              struct tcp_fastopen_cookie *foc,
-                             enum tcp_synack_type synack_type)
+                             enum tcp_synack_type synack_type,
+                             struct sk_buff *syn_skb)
 {
        const struct inet_request_sock *ireq = inet_rsk(req);
        struct flowi4 fl4;
        int err = -1;
        struct sk_buff *skb;
+       u8 tos;
 
        /* First, grab a route. */
        if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
                return -1;
 
-       skb = tcp_make_synack(sk, dst, req, foc, synack_type);
+       skb = tcp_make_synack(sk, dst, req, foc, synack_type, syn_skb);
 
        if (skb) {
                __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
 
+               tos = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
+                               (tcp_rsk(req)->syn_tos & ~INET_ECN_MASK) |
+                               (inet_sk(sk)->tos & INET_ECN_MASK) :
+                               inet_sk(sk)->tos;
+
+               if (!INET_ECN_is_capable(tos) &&
+                   tcp_bpf_ca_needs_ecn((struct sock *)req))
+                       tos |= INET_ECN_ECT_0;
+
                rcu_read_lock();
                err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
                                            ireq->ir_rmt_addr,
-                                           rcu_dereference(ireq->ireq_opt));
+                                           rcu_dereference(ireq->ireq_opt),
+                                           tos);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@ -1433,9 +1445,15 @@ static void tcp_v4_init_req(struct request_sock *req,
 }
 
 static struct dst_entry *tcp_v4_route_req(const struct sock *sk,
+                                         struct sk_buff *skb,
                                          struct flowi *fl,
-                                         const struct request_sock *req)
+                                         struct request_sock *req)
 {
+       tcp_v4_init_req(req, sk, skb);
+
+       if (security_inet_conn_request(sk, skb, req))
+               return NULL;
+
        return inet_csk_route_req(sk, &fl->u.ip4, req);
 }
 
@@ -1455,7 +1473,6 @@ const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
        .req_md5_lookup =       tcp_v4_md5_lookup,
        .calc_md5_hash  =       tcp_v4_md5_hash_skb,
 #endif
-       .init_req       =       tcp_v4_init_req,
 #ifdef CONFIG_SYN_COOKIES
        .cookie_init_seq =      cookie_v4_init_sequence,
 #endif
@@ -1492,6 +1509,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
                                  bool *own_req)
 {
        struct inet_request_sock *ireq;
+       bool found_dup_sk = false;
        struct inet_sock *newinet;
        struct tcp_sock *newtp;
        struct sock *newsk;
@@ -1529,6 +1547,12 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
                inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
        newinet->inet_id = prandom_u32();
 
+       /* Set ToS of the new socket based upon the value of incoming SYN.
+        * ECT bits are set later in tcp_init_transfer().
+        */
+       if (sock_net(sk)->ipv4.sysctl_tcp_reflect_tos)
+               newinet->tos = tcp_rsk(req)->syn_tos & ~INET_ECN_MASK;
+
        if (!dst) {
                dst = inet_csk_route_child_sock(sk, newsk, req);
                if (!dst)
@@ -1565,12 +1589,22 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 
        if (__inet_inherit_port(sk, newsk) < 0)
                goto put_and_exit;
-       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
+       *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash),
+                                      &found_dup_sk);
        if (likely(*own_req)) {
                tcp_move_syn(newtp, req);
                ireq->ireq_opt = NULL;
        } else {
-               newinet->inet_opt = NULL;
+               if (!req_unhash && found_dup_sk) {
+                       /* This code path should only be executed in the
+                        * syncookie case only
+                        */
+                       bh_unlock_sock(newsk);
+                       sock_put(newsk);
+                       newsk = NULL;
+               } else {
+                       newinet->inet_opt = NULL;
+               }
        }
        return newsk;
 
@@ -2730,6 +2764,20 @@ void tcp4_proc_exit(void)
 }
 #endif /* CONFIG_PROC_FS */
 
+/* @wake is one when sk_stream_write_space() calls us.
+ * This sends EPOLLOUT only if notsent_bytes is half the limit.
+ * This mimics the strategy used in sock_def_write_space().
+ */
+bool tcp_stream_memory_free(const struct sock *sk, int wake)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       u32 notsent_bytes = READ_ONCE(tp->write_seq) -
+                           READ_ONCE(tp->snd_nxt);
+
+       return (notsent_bytes << wake) < tcp_notsent_lowat(tp);
+}
+EXPORT_SYMBOL(tcp_stream_memory_free);
+
 struct proto tcp_prot = {
        .name                   = "TCP",
        .owner                  = THIS_MODULE,