diff options
author | rrs <rrs@FreeBSD.org> | 2007-01-15 15:12:10 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-01-15 15:12:10 +0000 |
commit | 094d70fac7c91a2d4fa26601007f25c9d46b058e (patch) | |
tree | 7e51ed488736cee7b8b3fdcc5a1fa638803647b8 /sys/netinet/sctp_output.c | |
parent | af870dbd2eb2b7c401adbdae5995f68a5ff112a3 (diff) | |
download | FreeBSD-src-094d70fac7c91a2d4fa26601007f25c9d46b058e.zip FreeBSD-src-094d70fac7c91a2d4fa26601007f25c9d46b058e.tar.gz |
- Macroizes the V6ONLY flag check.
- Added a short time wait (not used yet) constant
- Corrected the type of the crc32c table (it was
unsigned long and really is a uint32_t
- Got rid of the user of MHeaders until they
are truely needed by lower layers.
- Fixed an initialization problem in the readq structure
(ordering was off).
- Found yet another collision bug when the random number
generator returns two numbers on one side (during a collision)
that are the same. Also added some tracking of cookies
that will go away when we know that we have the last collision
bug gone.
- Fixed an init bug for book_size_scale, that was causing
Early FR code to run when it should not.
- Fixed a flight size tracking bug that was associated with
Early FR but due to above bug also effected all FR's
- Fixed it so Max Burst also will apply to Fast Retransmit.
- Fixed a bug in the temporary logging code that allowed a
static log array overflow
- hashinit_flags is now used.
- Two last mcopym's were converted to the macro sctp_m_copym that
has always been used by all other places
- macro sctp_m_copym was converted to upper case.
- We now validate sinfo_flags on input (we did not before).
- Fixed a bug that prevented a user from sending data and immediately
shuting down with one send operation.
- Moved to use hashdestroy instead of free() in our macros.
- Fixed an init problem in our timed_wait vtag where we
did not fully initialize our time-wait blocks.
- Timer stops were re-positioned.
- A pcb cleanup method was added, however this probably will
not be used in BSD.. unless we make module loadable protocols
- I think this fixes the mysterious timer bug.. it was a
ordering of locks problem in the way we did timers. It
now conforms to the timeout(9) manual (except for the
_drain part, we had to do this a different way due
to locks).
- Fixed error return code so we get either CONNREUSED or CONNRESET
depending on where one is in progression
- Purged an unused clone macro.
- Fixed a read erro code issue where we were NOT getting the proper
error when the connection was reset.
- Purged an unused clone macro.
- Fixed a read erro code issue where we were NOT getting the proper
error when the connection was reset.
Approved by: gnn
Diffstat (limited to 'sys/netinet/sctp_output.c')
-rw-r--r-- | sys/netinet/sctp_output.c | 100 |
1 files changed, 71 insertions, 29 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 261b66e..a6c129d 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -2041,7 +2041,6 @@ try_again: } - static struct mbuf * sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset, struct mbuf *initack, int initack_offset, struct sctp_state_cookie *stc_in) @@ -2061,12 +2060,12 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset, if (mret == NULL) { return (NULL); } - copy_init = sctp_m_copym(init, init_offset, M_COPYALL, M_DONTWAIT); + copy_init = SCTP_M_COPYM(init, init_offset, M_COPYALL, M_DONTWAIT); if (copy_init == NULL) { sctp_m_freem(mret); return (NULL); } - copy_initack = sctp_m_copym(initack, initack_offset, M_COPYALL, + copy_initack = SCTP_M_COPYM(initack, initack_offset, M_COPYALL, M_DONTWAIT); if (copy_initack == NULL) { sctp_m_freem(mret); @@ -3390,9 +3389,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, in_inp = (struct inpcb *)inp; stc.ipv6_addr_legal = 1; /* Now look at the binding flag to see if V4 will be legal */ - if ( - (in_inp->inp_flags & IN6P_IPV6_V6ONLY) - == 0) { + if (SCTP_IPV6_V6ONLY(in_inp) == 0) { stc.ipv4_addr_legal = 1; } else { /* V4 addresses are NOT legal on the association */ @@ -3616,16 +3613,20 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, initackm_out->msg.init.initiate_tag = htonl(asoc->my_vtag); initackm_out->msg.init.initial_tsn = htonl(asoc->init_seq_number); } else { + uint32_t vtag; + if (asoc) { atomic_add_int(&asoc->refcnt, 1); SCTP_TCB_UNLOCK(stcb); - initackm_out->msg.init.initiate_tag = htonl(sctp_select_a_tag(inp)); + vtag = sctp_select_a_tag(inp); + initackm_out->msg.init.initiate_tag = htonl(vtag); /* get a TSN to use too */ initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep)); SCTP_TCB_LOCK(stcb); atomic_add_int(&asoc->refcnt, -1); } else { - initackm_out->msg.init.initiate_tag = htonl(sctp_select_a_tag(inp)); + vtag = sctp_select_a_tag(inp); + initackm_out->msg.init.initiate_tag = htonl(vtag); /* get a TSN to use too */ initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep)); } @@ -4321,7 +4322,7 @@ error_out: return (outchain); } else { /* copy the old fashion way */ - appendchain = m_copy(clonechain, 0, M_COPYALL); + appendchain = SCTP_M_COPYM(clonechain, 0, M_COPYALL, M_DONTWAIT); } } if (appendchain == NULL) { @@ -4399,7 +4400,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, return; } if ((ca->m) && ca->sndlen) { - m = m_copym(ca->m, 0, M_COPYALL, M_DONTWAIT); + m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_DONTWAIT); if (m == NULL) { /* can't copy so we are done */ ca->cnt_failed++; @@ -5030,7 +5031,7 @@ out_gu: } else { struct mbuf *m; - chk->data = m_copym(sp->data, 0, to_move, M_DONTWAIT); + chk->data = SCTP_M_COPYM(sp->data, 0, to_move, M_DONTWAIT); chk->last_mbuf = NULL; if (chk->data == NULL) { sp->some_taken = some_taken; @@ -5104,6 +5105,7 @@ out_gu: sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk)); chk->book_size = chk->send_size = (to_move + sizeof(struct sctp_data_chunk)); + chk->book_size_scale = 0; chk->sent = SCTP_DATAGRAM_UNSENT; /* @@ -6208,7 +6210,7 @@ sctp_send_cookie_echo(struct mbuf *m, if ((pad = (plen % 4))) { plen += 4 - pad; } - cookie = sctp_m_copym(m, at, plen, M_DONTWAIT); + cookie = SCTP_M_COPYM(m, at, plen, M_DONTWAIT); if (cookie == NULL) { /* No memory */ return (-2); @@ -6269,7 +6271,7 @@ sctp_send_heartbeat_ack(struct sctp_tcb *stcb, /* must have a net pointer */ return; - outchain = sctp_m_copym(m, offset, chk_length, M_DONTWAIT); + outchain = SCTP_M_COPYM(m, offset, chk_length, M_DONTWAIT); if (outchain == NULL) { /* gak out of memory */ return; @@ -6499,8 +6501,7 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb, uint32_t retrans) return (-1); } /* copy the asconf_ack */ - /* We no longer have pak headers here so m_copy is it */ - m_ack = m_copy(stcb->asoc.last_asconf_ack_sent, 0, M_COPYALL); + m_ack = SCTP_M_COPYM(stcb->asoc.last_asconf_ack_sent, 0, M_COPYALL, M_DONTWAIT); if (m_ack == NULL) { /* couldn't copy it */ @@ -6566,7 +6567,7 @@ static int sctp_chunk_retransmission(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_association *asoc, - int *cnt_out, struct timeval *now, int *now_filled) + int *cnt_out, struct timeval *now, int *now_filled, int *fr_done) { /* * send out one MTU of retransmission. If fast_retransmit is @@ -6769,6 +6770,7 @@ one_chunk_around: * Mark the destination net to have FR recovery * limits put on it. */ + *fr_done = 1; net->fast_retran_ip = 1; } @@ -6947,22 +6949,22 @@ one_chunk_around: if (asoc->sent_queue_retran_cnt < 0) { asoc->sent_queue_retran_cnt = 0; } -#ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_UP, - data_list[i]->whoTo->flight_size, - data_list[i]->book_size, - (uintptr_t) stcb, - data_list[i]->rec.data.TSN_seq); -#endif - net->flight_size += data_list[i]->book_size; - asoc->total_flight += data_list[i]->book_size; if (data_list[i]->book_size_scale) { /* * need to double the book size on * this one */ data_list[i]->book_size_scale = 0; + /* + * Since we double the booksize, we + * must also double the output queue + * size, since this get shrunk when + * we free by this amount. + */ + atomic_add_int(&((asoc)->total_output_queue_size), data_list[i]->book_size); data_list[i]->book_size *= 2; + + } else { sctp_ucount_incr(asoc->total_flight_count); #ifdef SCTP_LOG_RWND @@ -6973,6 +6975,15 @@ one_chunk_around: (uint32_t) (data_list[i]->send_size + sctp_peer_chunk_oh)); } +#ifdef SCTP_FLIGHT_LOGGING + sctp_misc_ints(SCTP_FLIGHT_LOG_UP, + data_list[i]->whoTo->flight_size, + data_list[i]->book_size, + (uintptr_t) stcb, + data_list[i]->rec.data.TSN_seq); +#endif + net->flight_size += data_list[i]->book_size; + asoc->total_flight += data_list[i]->book_size; if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { /* SWS sender side engages */ asoc->peers_rwnd = 0; @@ -7074,6 +7085,7 @@ sctp_chunk_output(struct sctp_inpcb *inp, int nagle_on = 0; int frag_point = sctp_get_frag_point(stcb, &stcb->asoc); int un_sent = 0; + int fr_done, tot_frs = 0; asoc = &stcb->asoc; if (from_where == SCTP_OUTPUT_FROM_USR_SEND) { @@ -7118,7 +7130,11 @@ sctp_chunk_output(struct sctp_inpcb *inp, return (0); } else if (from_where != SCTP_OUTPUT_FROM_HB_TMR) { /* if its not from a HB then do it */ - ret = sctp_chunk_retransmission(inp, stcb, asoc, &num_out, &now, &now_filled); + fr_done = 0; + ret = sctp_chunk_retransmission(inp, stcb, asoc, &num_out, &now, &now_filled, &fr_done); + if (fr_done) { + tot_frs++; + } } else { /* * its from any other place, we don't allow retran @@ -7161,7 +7177,12 @@ sctp_chunk_output(struct sctp_inpcb *inp, &now, &now_filled, frag_point); return (ret); } + if (tot_frs > asoc->max_burst) { + /* Hit FR burst limit */ + return (0); + } if ((num_out == 0) && (ret == 0)) { + /* No more retrans to send */ break; } @@ -8300,6 +8321,7 @@ jump_out: } chk->book_size = SCTP_SIZE32((chk->send_size + sizeof(struct sctp_pktdrop_chunk) + sizeof(struct sctphdr) + SCTP_MED_OVERHEAD)); + chk->book_size_scale = 0; if (chk->book_size > small_one) { drp->ch.chunk_flags = SCTP_PACKET_TRUNCATED; drp->trunc_len = htons(chk->send_size); @@ -8443,6 +8465,7 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk, /* now fix the chunk length */ ch->chunk_length = htons(len + old_len); chk->book_size = len + old_len; + chk->book_size_scale = 0; chk->send_size = SCTP_SIZE32(chk->book_size); SCTP_BUF_LEN(chk->data) = chk->send_size; return; @@ -8486,6 +8509,7 @@ sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk, /* now fix the chunk length */ ch->chunk_length = htons(len + old_len); chk->book_size = len + old_len; + chk->book_size_scale = 0; chk->send_size = SCTP_SIZE32(chk->book_size); SCTP_BUF_LEN(chk->data) = chk->send_size; return; @@ -8517,6 +8541,7 @@ sctp_add_stream_reset_tsn(struct sctp_tmit_chunk *chk, ch->chunk_length = htons(len + old_len); chk->send_size = len + old_len; chk->book_size = SCTP_SIZE32(chk->send_size); + chk->book_size_scale = 0; SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); return; } @@ -8546,6 +8571,7 @@ sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk, /* now fix the chunk length */ ch->chunk_length = htons(len + old_len); chk->book_size = len + old_len; + chk->book_size_scale = 0; chk->send_size = SCTP_SIZE32(chk->book_size); SCTP_BUF_LEN(chk->data) = chk->send_size; return; @@ -8582,6 +8608,7 @@ sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk, ch->chunk_length = htons(len + old_len); chk->book_size = len + old_len; chk->send_size = SCTP_SIZE32(chk->book_size); + chk->book_size_scale = 0; SCTP_BUF_LEN(chk->data) = chk->send_size; return; } @@ -8625,6 +8652,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, chk->asoc = &stcb->asoc; chk->book_size = sizeof(struct sctp_chunkhdr); chk->send_size = SCTP_SIZE32(chk->book_size); + chk->book_size_scale = 0; chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (chk->data == NULL) { @@ -9278,6 +9306,11 @@ sctp_lower_sosend(struct socket *so, goto out_unlocked; } if ((use_rcvinfo) && srcv) { + if (INVALID_SINFO_FLAG(srcv->sinfo_flags) || PR_SCTP_INVALID_POLICY(srcv->sinfo_flags)) { + error = EINVAL; + splx(s); + goto out_unlocked; + } if (srcv->sinfo_flags) SCTP_STAT_INCR(sctps_sends_with_flags); @@ -9383,8 +9416,13 @@ sctp_lower_sosend(struct socket *so, * process */ if ((use_rcvinfo) && (srcv) && - (srcv->sinfo_flags & SCTP_ABORT)) { - /* User asks to abort a non-existant asoc */ + ((srcv->sinfo_flags & SCTP_ABORT) || + ((srcv->sinfo_flags & SCTP_EOF) && + (uio->uio_resid == 0)))) { + /* + * User asks to abort a non-existant assoc, + * or EOF a non-existant assoc with no data + */ error = ENOENT; splx(s); goto out_unlocked; @@ -10230,7 +10268,11 @@ skip_out_eof: queue_only = 0; } else { sctp_send_initiate(inp, stcb); - stcb->asoc.state = SCTP_STATE_COOKIE_WAIT; + if (stcb->asoc.state & SCTP_STATE_SHUTDOWN_PENDING) + stcb->asoc.state = SCTP_STATE_COOKIE_WAIT | + SCTP_STATE_SHUTDOWN_PENDING; + else + stcb->asoc.state = SCTP_STATE_COOKIE_WAIT; queue_only_for_init = 0; queue_only = 1; } |