void RUDPRecvBuffer::on_timer(uint64_t now_timer, uint32_t rtc) { if(check_loss(now_timer, rtc)) { recv_new_packet_ = false; } uint32_t rtc_threshold = core_min(20, rtc / 2); if(last_ack_ts_ + rtc_threshold <= now_timer && recv_new_packet_) { net_channel_->send_ack(first_seq_); set_send_last_ack_ts(now_timer); } //判断是否可以读 if(!recv_data_.empty() && net_channel_ != NULL) net_channel_->on_read(); }
STATIC int test_mod(test_pars_t *tp, pdu_t *pdu, iscsi_pdu_kind_t kind, int rxtx, int err) { mod_desc_t *mod; uint32_t mpoff, off; int i, rc = 0, s; tp->pdu_count[kind][rxtx]++; tp->pdu_count[ANY_PDU][rxtx]++; do { if ((mod = TAILQ_FIRST(&tp->mods)) == NULL) { return check_loss(tp, rxtx); } if (mod->pars.which_pdu != ANY_PDU && mod->pars.which_pdu != kind) { return check_loss(tp, rxtx); } mpoff = mod->pars.pdu_offset; switch (mod->pars.which_offset) { case ABSOLUTE_ANY: off = tp->pdu_count[ANY_PDU][CNT_TX] + tp->pdu_count[ANY_PDU][CNT_RX]; break; case RELATIVE_ANY: off = (tp->pdu_count[ANY_PDU][CNT_TX] + tp->pdu_count[ANY_PDU][CNT_RX]) - (tp->pdu_last[ANY_PDU][CNT_TX] + tp->pdu_last[ANY_PDU][CNT_RX]); break; case ABSOLUTE_PDUKIND: off = tp->pdu_count[kind][rxtx]; break; case RELATIVE_PDUKIND: off = tp->pdu_count[kind][rxtx] - tp->pdu_last[kind][rxtx]; break; case ABSOLUTE_TX: if (rxtx != CNT_TX) return check_loss(tp, rxtx); off = tp->pdu_count[ANY_PDU][CNT_TX]; break; case RELATIVE_TX: if (rxtx != CNT_TX) return check_loss(tp, rxtx); off = tp->pdu_count[ANY_PDU][CNT_TX] - tp->pdu_last[ANY_PDU][CNT_TX]; break; case ABSOLUTE_RX: if (rxtx != CNT_RX) return check_loss(tp, rxtx); off = tp->pdu_count[ANY_PDU][CNT_RX]; break; case RELATIVE_RX: if (rxtx != CNT_RX) return check_loss(tp, rxtx); off = tp->pdu_count[ANY_PDU][CNT_RX] - tp->pdu_last[ANY_PDU][CNT_RX]; break; default: /* bad offset - skip this entry */ mpoff = off = 0; break; } DEB(1, ("test_mod: kind=%d, rxtx=%d, pdukind=%d, mpoff=%d, " "whichoff=%d, off=%d\n", kind, rxtx, mod->pars.which_pdu, mpoff, mod->pars.which_offset, off)); if (!off || (mpoff != 0 && mpoff < off)) { /* This might happen in some cases. Just discard the modification. */ s = splbio(); TAILQ_REMOVE(&tp->mods, mod, link); splx(s); update_options(tp, mod); if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) { mod->pars.status = ISCSI_STATUS_TEST_MODIFICATION_SKIPPED; wakeup(mod); } free(mod, M_TEMP); } } while (mpoff && mpoff < off); if (mpoff > off) return check_loss(tp, rxtx); DEB(1, ("test_mod: opt=%x, pdu_ptr=%x, num_mods=%d\n", mod->pars.options, (int) mod->pdu_ptr, mod->pars.num_pdu_mods)); if (mod->pdu_ptr) test_get(pdu, mod, err); if (mod->pars.options & ISCSITEST_OPT_DISCARD_PDU) rc = 1; else if (check_loss(tp, rxtx)) rc = 1; else if (mod->pars.num_pdu_mods) { if (!(mod->pars.options & ISCSITEST_OPT_MOD_PERMANENT)) { /* * Note: if the PDU is later resent, the unmodified one will be * used as resend_pdu restores the original io vector. */ pdu->mod_pdu = pdu->pdu; pdu->io_vec[0].iov_base = &pdu->mod_pdu; } for (i = 0; i < mod->pars.num_pdu_mods; i++) { mod_pdu(pdu, &mod->mods[i]); } } if (rxtx == CNT_TX) { if (mod->pars.options & ISCSITEST_OPT_NO_RESPONSE_PDU) { ccb_t *ccb = pdu->owner; DEB(1, ("test_mod: No response expected, completing CCB %x\n", (int)ccb)); if (ccb != NULL && (ccb->disp == CCBDISP_WAIT || ccb->disp == CCBDISP_SCSIPI)) { /* simulate timeout */ wake_ccb(ccb, ISCSI_STATUS_TIMEOUT); } } if ((mod->pars.options & ISCSITEST_SFLAG_UPDATE_FIELDS) && mod->pars.num_pdu_mods) { connection_t *conn = pdu->connection; if (conn->HeaderDigest && !(mod->pars.options & ISCSITEST_SFLAG_NO_HEADER_DIGEST)) pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE); if (pdu->uio.uio_iovcnt > 1 && conn->DataDigest && !(mod->pars.options & ISCSITEST_SFLAG_NO_DATA_DIGEST)) pdu->data_digest = gen_digest_2( pdu->io_vec[1].iov_base, pdu->io_vec[1].iov_len, pdu->io_vec[2].iov_base, pdu->io_vec[2].iov_len); } } s = splbio(); TAILQ_REMOVE(&tp->mods, mod, link); update_options(tp, mod); /* we've modified a PDU - copy current count into last count */ memcpy(tp->pdu_last, tp->pdu_count, sizeof(tp->pdu_last)); splx(s); if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) { wakeup(mod); } if (mod->pars.options & ISCSITEST_KILL_CONNECTION) { kill_connection(tp->connection, ISCSI_STATUS_TEST_CONNECTION_CLOSED, NO_LOGOUT, TRUE); } free(mod, M_TEMP); return rc; }