aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 7a0f0b27bf1f..17b89c523f9d 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -439,12 +439,14 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
439 !tp->urg_data || 439 !tp->urg_data ||
440 before(tp->urg_seq, tp->copied_seq) || 440 before(tp->urg_seq, tp->copied_seq) ||
441 !before(tp->urg_seq, tp->rcv_nxt)) { 441 !before(tp->urg_seq, tp->rcv_nxt)) {
442 struct sk_buff *skb;
443
442 answ = tp->rcv_nxt - tp->copied_seq; 444 answ = tp->rcv_nxt - tp->copied_seq;
443 445
444 /* Subtract 1, if FIN is in queue. */ 446 /* Subtract 1, if FIN is in queue. */
445 if (answ && !skb_queue_empty(&sk->sk_receive_queue)) 447 skb = skb_peek_tail(&sk->sk_receive_queue);
446 answ -= 448 if (answ && skb)
447 tcp_hdr((struct sk_buff *)sk->sk_receive_queue.prev)->fin; 449 answ -= tcp_hdr(skb)->fin;
448 } else 450 } else
449 answ = tp->urg_seq - tp->copied_seq; 451 answ = tp->urg_seq - tp->copied_seq;
450 release_sock(sk); 452 release_sock(sk);
@@ -1382,11 +1384,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1382 1384
1383 /* Next get a buffer. */ 1385 /* Next get a buffer. */
1384 1386
1385 skb = skb_peek(&sk->sk_receive_queue); 1387 skb_queue_walk(&sk->sk_receive_queue, skb) {
1386 do {
1387 if (!skb)
1388 break;
1389
1390 /* Now that we have two receive queues this 1388 /* Now that we have two receive queues this
1391 * shouldn't happen. 1389 * shouldn't happen.
1392 */ 1390 */
@@ -1403,8 +1401,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1403 if (tcp_hdr(skb)->fin) 1401 if (tcp_hdr(skb)->fin)
1404 goto found_fin_ok; 1402 goto found_fin_ok;
1405 WARN_ON(!(flags & MSG_PEEK)); 1403 WARN_ON(!(flags & MSG_PEEK));
1406 skb = skb->next; 1404 }
1407 } while (skb != (struct sk_buff *)&sk->sk_receive_queue);
1408 1405
1409 /* Well, if we have backlog, try to process it now yet. */ 1406 /* Well, if we have backlog, try to process it now yet. */
1410 1407
@@ -2518,20 +2515,30 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
2518 unsigned int thlen; 2515 unsigned int thlen;
2519 unsigned int flags; 2516 unsigned int flags;
2520 unsigned int mss = 1; 2517 unsigned int mss = 1;
2518 unsigned int hlen;
2519 unsigned int off;
2521 int flush = 1; 2520 int flush = 1;
2522 int i; 2521 int i;
2523 2522
2524 th = skb_gro_header(skb, sizeof(*th)); 2523 off = skb_gro_offset(skb);
2525 if (unlikely(!th)) 2524 hlen = off + sizeof(*th);
2526 goto out; 2525 th = skb_gro_header_fast(skb, off);
2526 if (skb_gro_header_hard(skb, hlen)) {
2527 th = skb_gro_header_slow(skb, hlen, off);
2528 if (unlikely(!th))
2529 goto out;
2530 }
2527 2531
2528 thlen = th->doff * 4; 2532 thlen = th->doff * 4;
2529 if (thlen < sizeof(*th)) 2533 if (thlen < sizeof(*th))
2530 goto out; 2534 goto out;
2531 2535
2532 th = skb_gro_header(skb, thlen); 2536 hlen = off + thlen;
2533 if (unlikely(!th)) 2537 if (skb_gro_header_hard(skb, hlen)) {
2534 goto out; 2538 th = skb_gro_header_slow(skb, hlen, off);
2539 if (unlikely(!th))
2540 goto out;
2541 }
2535 2542
2536 skb_gro_pull(skb, thlen); 2543 skb_gro_pull(skb, thlen);
2537 2544
@@ -2544,7 +2551,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
2544 2551
2545 th2 = tcp_hdr(p); 2552 th2 = tcp_hdr(p);
2546 2553
2547 if ((th->source ^ th2->source) | (th->dest ^ th2->dest)) { 2554 if (*(u32 *)&th->source ^ *(u32 *)&th2->source) {
2548 NAPI_GRO_CB(p)->same_flow = 0; 2555 NAPI_GRO_CB(p)->same_flow = 0;
2549 continue; 2556 continue;
2550 } 2557 }
@@ -2559,14 +2566,14 @@ found:
2559 flush |= flags & TCP_FLAG_CWR; 2566 flush |= flags & TCP_FLAG_CWR;
2560 flush |= (flags ^ tcp_flag_word(th2)) & 2567 flush |= (flags ^ tcp_flag_word(th2)) &
2561 ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); 2568 ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH);
2562 flush |= (th->ack_seq ^ th2->ack_seq) | (th->window ^ th2->window); 2569 flush |= th->ack_seq ^ th2->ack_seq;
2563 for (i = sizeof(*th); !flush && i < thlen; i += 4) 2570 for (i = sizeof(*th); i < thlen; i += 4)
2564 flush |= *(u32 *)((u8 *)th + i) ^ 2571 flush |= *(u32 *)((u8 *)th + i) ^
2565 *(u32 *)((u8 *)th2 + i); 2572 *(u32 *)((u8 *)th2 + i);
2566 2573
2567 mss = skb_shinfo(p)->gso_size; 2574 mss = skb_shinfo(p)->gso_size;
2568 2575
2569 flush |= (len > mss) | !len; 2576 flush |= (len - 1) >= mss;
2570 flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); 2577 flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq);
2571 2578
2572 if (flush || skb_gro_receive(head, skb)) { 2579 if (flush || skb_gro_receive(head, skb)) {