* After a timeout, the SACK list may be rebuilt. This SACK information * should be used to avoid retransmitting SACKed data. This function * traverses the SACK list to see if snd_nxt should be moved forward. */
| 872 | * traverses the SACK list to see if snd_nxt should be moved forward. |
| 873 | */ |
| 874 | void |
| 875 | tcp_sack_adjust(struct tcpcb *tp) |
| 876 | { |
| 877 | struct sackhole *p, *cur = TAILQ_FIRST(&tp->snd_holes); |
| 878 | |
| 879 | INP_WLOCK_ASSERT(tp->t_inpcb); |
| 880 | if (cur == NULL) |
| 881 | return; /* No holes */ |
| 882 | if (SEQ_GEQ(tp->snd_nxt, tp->snd_fack)) |
| 883 | return; /* We're already beyond any SACKed blocks */ |
| 884 | /*- |
| 885 | * Two cases for which we want to advance snd_nxt: |
| 886 | * i) snd_nxt lies between end of one hole and beginning of another |
| 887 | * ii) snd_nxt lies between end of last hole and snd_fack |
| 888 | */ |
| 889 | while ((p = TAILQ_NEXT(cur, scblink)) != NULL) { |
| 890 | if (SEQ_LT(tp->snd_nxt, cur->end)) |
| 891 | return; |
| 892 | if (SEQ_GEQ(tp->snd_nxt, p->start)) |
| 893 | cur = p; |
| 894 | else { |
| 895 | tp->snd_nxt = p->start; |
| 896 | return; |
| 897 | } |
| 898 | } |
| 899 | if (SEQ_LT(tp->snd_nxt, cur->end)) |
| 900 | return; |
| 901 | tp->snd_nxt = tp->snd_fack; |
| 902 | } |