* This subfunction is used to try to highly optimize the * fast path. We again allow window updates that are * in sequence to remain in the fast-path. We also add * in the __predict's to attempt to help the compiler. * Note that if we return a 0, then we can *not* process * it and the caller should push the packet into the * slow-path. If we return 1, then all is well and * the packet is fu
| 8639 | * the packet is fully processed. |
| 8640 | */ |
| 8641 | static int |
| 8642 | bbr_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so, |
| 8643 | struct tcpcb *tp, struct tcpopt *to, int32_t drop_hdrlen, int32_t tlen, |
| 8644 | uint32_t tiwin, int32_t nxt_pkt, uint8_t iptos) |
| 8645 | { |
| 8646 | int32_t acked; |
| 8647 | uint16_t nsegs; |
| 8648 | uint32_t sack_changed; |
| 8649 | #ifdef TCPDEBUG |
| 8650 | /* |
| 8651 | * The size of tcp_saveipgen must be the size of the max ip header, |
| 8652 | * now IPv6. |
| 8653 | */ |
| 8654 | u_char tcp_saveipgen[IP6_HDR_LEN]; |
| 8655 | struct tcphdr tcp_savetcp; |
| 8656 | short ostate = 0; |
| 8657 | |
| 8658 | #endif |
| 8659 | uint32_t prev_acked = 0; |
| 8660 | struct tcp_bbr *bbr; |
| 8661 | |
| 8662 | if (__predict_false(SEQ_LEQ(th->th_ack, tp->snd_una))) { |
| 8663 | /* Old ack, behind (or duplicate to) the last one rcv'd */ |
| 8664 | return (0); |
| 8665 | } |
| 8666 | if (__predict_false(SEQ_GT(th->th_ack, tp->snd_max))) { |
| 8667 | /* Above what we have sent? */ |
| 8668 | return (0); |
| 8669 | } |
| 8670 | if (__predict_false(tiwin == 0)) { |
| 8671 | /* zero window */ |
| 8672 | return (0); |
| 8673 | } |
| 8674 | if (__predict_false(tp->t_flags & (TF_NEEDSYN | TF_NEEDFIN))) { |
| 8675 | /* We need a SYN or a FIN, unlikely.. */ |
| 8676 | return (0); |
| 8677 | } |
| 8678 | if ((to->to_flags & TOF_TS) && __predict_false(TSTMP_LT(to->to_tsval, tp->ts_recent))) { |
| 8679 | /* Timestamp is behind .. old ack with seq wrap? */ |
| 8680 | return (0); |
| 8681 | } |
| 8682 | if (__predict_false(IN_RECOVERY(tp->t_flags))) { |
| 8683 | /* Still recovering */ |
| 8684 | return (0); |
| 8685 | } |
| 8686 | bbr = (struct tcp_bbr *)tp->t_fb_ptr; |
| 8687 | if (__predict_false(bbr->r_ctl.rc_resend != NULL)) { |
| 8688 | /* We are retransmitting */ |
| 8689 | return (0); |
| 8690 | } |
| 8691 | if (__predict_false(bbr->rc_in_persist != 0)) { |
| 8692 | /* In persist mode */ |
| 8693 | return (0); |
| 8694 | } |
| 8695 | if (bbr->r_ctl.rc_sacked) { |
| 8696 | /* We have sack holes on our scoreboard */ |
| 8697 | return (0); |
| 8698 | } |
no test coverage detected