diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fdd88c3803a6..0003d409fec5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2478,6 +2478,9 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, | |||
2478 | int newly_acked_sacked = prior_unsacked - | 2478 | int newly_acked_sacked = prior_unsacked - |
2479 | (tp->packets_out - tp->sacked_out); | 2479 | (tp->packets_out - tp->sacked_out); |
2480 | 2480 | ||
2481 | if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) | ||
2482 | return; | ||
2483 | |||
2481 | tp->prr_delivered += newly_acked_sacked; | 2484 | tp->prr_delivered += newly_acked_sacked; |
2482 | if (delta < 0) { | 2485 | if (delta < 0) { |
2483 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + | 2486 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + |
@@ -4481,19 +4484,34 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int | |||
4481 | int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | 4484 | int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) |
4482 | { | 4485 | { |
4483 | struct sk_buff *skb; | 4486 | struct sk_buff *skb; |
4487 | int err = -ENOMEM; | ||
4488 | int data_len = 0; | ||
4484 | bool fragstolen; | 4489 | bool fragstolen; |
4485 | 4490 | ||
4486 | if (size == 0) | 4491 | if (size == 0) |
4487 | return 0; | 4492 | return 0; |
4488 | 4493 | ||
4489 | skb = alloc_skb(size, sk->sk_allocation); | 4494 | if (size > PAGE_SIZE) { |
4495 | int npages = min_t(size_t, size >> PAGE_SHIFT, MAX_SKB_FRAGS); | ||
4496 | |||
4497 | data_len = npages << PAGE_SHIFT; | ||
4498 | size = data_len + (size & ~PAGE_MASK); | ||
4499 | } | ||
4500 | skb = alloc_skb_with_frags(size - data_len, data_len, | ||
4501 | PAGE_ALLOC_COSTLY_ORDER, | ||
4502 | &err, sk->sk_allocation); | ||
4490 | if (!skb) | 4503 | if (!skb) |
4491 | goto err; | 4504 | goto err; |
4492 | 4505 | ||
4506 | skb_put(skb, size - data_len); | ||
4507 | skb->data_len = data_len; | ||
4508 | skb->len = size; | ||
4509 | |||
4493 | if (tcp_try_rmem_schedule(sk, skb, skb->truesize)) | 4510 | if (tcp_try_rmem_schedule(sk, skb, skb->truesize)) |
4494 | goto err_free; | 4511 | goto err_free; |
4495 | 4512 | ||
4496 | if (memcpy_from_msg(skb_put(skb, size), msg, size)) | 4513 | err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size); |
4514 | if (err) | ||
4497 | goto err_free; | 4515 | goto err_free; |
4498 | 4516 | ||
4499 | TCP_SKB_CB(skb)->seq = tcp_sk(sk)->rcv_nxt; | 4517 | TCP_SKB_CB(skb)->seq = tcp_sk(sk)->rcv_nxt; |
@@ -4509,7 +4527,8 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | |||
4509 | err_free: | 4527 | err_free: |
4510 | kfree_skb(skb); | 4528 | kfree_skb(skb); |
4511 | err: | 4529 | err: |
4512 | return -ENOMEM; | 4530 | return err; |
4531 | |||
4513 | } | 4532 | } |
4514 | 4533 | ||
4515 | static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) | 4534 | static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) |
@@ -5667,6 +5686,7 @@ discard: | |||
5667 | } | 5686 | } |
5668 | 5687 | ||
5669 | tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; | 5688 | tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; |
5689 | tp->copied_seq = tp->rcv_nxt; | ||
5670 | tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; | 5690 | tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; |
5671 | 5691 | ||
5672 | /* RFC1323: The window in SYN & SYN/ACK segments is | 5692 | /* RFC1323: The window in SYN & SYN/ACK segments is |
@@ -6187,7 +6207,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, | |||
6187 | tcp_openreq_init(req, &tmp_opt, skb, sk); | 6207 | tcp_openreq_init(req, &tmp_opt, skb, sk); |
6188 | 6208 | ||
6189 | /* Note: tcp_v6_init_req() might override ir_iif for link locals */ | 6209 | /* Note: tcp_v6_init_req() might override ir_iif for link locals */ |
6190 | inet_rsk(req)->ir_iif = sk->sk_bound_dev_if; | 6210 | inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb); |
6191 | 6211 | ||
6192 | af_ops->init_req(req, sk, skb); | 6212 | af_ops->init_req(req, sk, skb); |
6193 | 6213 | ||