| 5990 | } |
| 5991 | |
| 5992 | static uint32_t |
| 5993 | rack_update_entry(struct tcpcb *tp, struct tcp_rack *rack, |
| 5994 | struct rack_sendmap *rsm, uint32_t ts, int32_t *lenp) |
| 5995 | { |
| 5996 | /* |
| 5997 | * We (re-)transmitted starting at rsm->r_start for some length |
| 5998 | * (possibly less than r_end. |
| 5999 | */ |
| 6000 | struct rack_sendmap *nrsm, *insret; |
| 6001 | uint32_t c_end; |
| 6002 | int32_t len; |
| 6003 | |
| 6004 | len = *lenp; |
| 6005 | c_end = rsm->r_start + len; |
| 6006 | if (SEQ_GEQ(c_end, rsm->r_end)) { |
| 6007 | /* |
| 6008 | * We retransmitted the whole piece or more than the whole |
| 6009 | * slopping into the next rsm. |
| 6010 | */ |
| 6011 | rack_update_rsm(tp, rack, rsm, ts); |
| 6012 | if (c_end == rsm->r_end) { |
| 6013 | *lenp = 0; |
| 6014 | return (0); |
| 6015 | } else { |
| 6016 | int32_t act_len; |
| 6017 | |
| 6018 | /* Hangs over the end return whats left */ |
| 6019 | act_len = rsm->r_end - rsm->r_start; |
| 6020 | *lenp = (len - act_len); |
| 6021 | return (rsm->r_end); |
| 6022 | } |
| 6023 | /* We don't get out of this block. */ |
| 6024 | } |
| 6025 | /* |
| 6026 | * Here we retransmitted less than the whole thing which means we |
| 6027 | * have to split this into what was transmitted and what was not. |
| 6028 | */ |
| 6029 | nrsm = rack_alloc_full_limit(rack); |
| 6030 | if (nrsm == NULL) { |
| 6031 | /* |
| 6032 | * We can't get memory, so lets not proceed. |
| 6033 | */ |
| 6034 | *lenp = 0; |
| 6035 | return (0); |
| 6036 | } |
| 6037 | /* |
| 6038 | * So here we are going to take the original rsm and make it what we |
| 6039 | * retransmitted. nrsm will be the tail portion we did not |
| 6040 | * retransmit. For example say the chunk was 1, 11 (10 bytes). And |
| 6041 | * we retransmitted 5 bytes i.e. 1, 5. The original piece shrinks to |
| 6042 | * 1, 6 and the new piece will be 6, 11. |
| 6043 | */ |
| 6044 | rack_clone_rsm(rack, nrsm, rsm, c_end); |
| 6045 | nrsm->r_dupack = 0; |
| 6046 | rack_log_retran_reason(rack, nrsm, __LINE__, 0, 2); |
| 6047 | insret = RB_INSERT(rack_rb_tree_head, &rack->r_ctl.rc_mtree, nrsm); |
| 6048 | #ifdef INVARIANTS |
| 6049 | if (insret != NULL) { |
no test coverage detected