diff options
author | rrs <rrs@FreeBSD.org> | 2007-04-22 11:06:27 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-04-22 11:06:27 +0000 |
commit | 44fd758bd50a08f1cfd0618700424dd54a93571a (patch) | |
tree | cdfe74b46c1b17927d990e112c62556cf444c46e /sys/netinet/sctputil.c | |
parent | c494d6613ee7a2abda270930371858e0da4262f7 (diff) | |
download | FreeBSD-src-44fd758bd50a08f1cfd0618700424dd54a93571a.zip FreeBSD-src-44fd758bd50a08f1cfd0618700424dd54a93571a.tar.gz |
- Somehow the disable fragment option got lost. We could
set/clear it but would not do it. Now we will.
- Moved to latest socket api for extended sndrcv info struct.
- Moved to support all new levels of fragment interleave.
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r-- | sys/netinet/sctputil.c | 100 |
1 files changed, 80 insertions, 20 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index c94b2d4..9d03b7c 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -3002,7 +3002,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb, /* This always must be called with the read-queue LOCKED in the INP */ void sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, - uint32_t error, int nolock) + uint32_t error, int nolock, uint32_t val) { struct mbuf *m_notify; struct sctp_pdapi_event *pdapi; @@ -3023,6 +3023,8 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, pdapi->pdapi_flags = 0; pdapi->pdapi_length = sizeof(struct sctp_pdapi_event); pdapi->pdapi_indication = error; + pdapi->pdapi_stream = (val >> 16); + pdapi->pdapi_seq = (val & 0x0000ffff); pdapi->pdapi_assoc_id = sctp_get_associd(stcb); SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event); @@ -3265,7 +3267,13 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, sctp_notify_adaptation_layer(stcb, error); break; case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION: - sctp_notify_partial_delivery_indication(stcb, error, 0); + { + uint32_t val; + + val = *((uint32_t *) data); + + sctp_notify_partial_delivery_indication(stcb, error, 0, val); + } break; case SCTP_NOTIFY_STRDATA_ERR: break; @@ -4803,8 +4811,31 @@ restart_nosblocks: /* find a more suitable one then this */ ctl = TAILQ_NEXT(control, next); while (ctl) { - if ((ctl->stcb != control->stcb) && (ctl->length)) { - /* found one */ + if ((ctl->stcb != control->stcb) && (ctl->length) && + (ctl->some_taken || + ((ctl->do_not_ref_stcb == 0) && + (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0))) + ) { + /*- + * If we have a different TCB next, and there is data + * present. If we have already taken some (pdapi), OR we can + * ref the tcb and no delivery as started on this stream, we + * take it. + */ + control = ctl; + goto found_one; + } else if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) && + (ctl->length) && + ((ctl->some_taken) || + ((ctl->do_not_ref_stcb == 0) && + (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0))) + ) { + /*- + * If we have the same tcb, and there is data present, and we + * have the strm interleave feature present. Then if we have + * taken some (pdapi) or we can refer to tht tcb AND we have + * not started a delivery for this stream, we can take it. + */ control = ctl; goto found_one; } @@ -4831,6 +4862,10 @@ found_one: * If we reach here, control has a some data for us to read off. * Note that stcb COULD be NULL. */ + if (control->do_not_ref_stcb == 0) { + control->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started = 1; + } + control->some_taken = 1; if (hold_sblock) { SOCKBUF_UNLOCK(&so->so_rcv); hold_sblock = 0; @@ -4874,21 +4909,22 @@ found_one: struct sctp_extrcvinfo *s_extra; s_extra = (struct sctp_extrcvinfo *)sinfo; - if (nxt) { - s_extra->next_flags = SCTP_NEXT_MSG_AVAIL; + if ((nxt) && + (nxt->length)) { + s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL; if (nxt->sinfo_flags & SCTP_UNORDERED) { - s_extra->next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; + s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; } if (nxt->spec_flags & M_NOTIFICATION) { - s_extra->next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; + s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; } - s_extra->next_asocid = nxt->sinfo_assoc_id; - s_extra->next_length = nxt->length; - s_extra->next_ppid = nxt->sinfo_ppid; - s_extra->next_stream = nxt->sinfo_stream; + s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id; + s_extra->sreinfo_next_length = nxt->length; + s_extra->sreinfo_next_ppid = nxt->sinfo_ppid; + s_extra->sreinfo_next_stream = nxt->sinfo_stream; if (nxt->tail_mbuf != NULL) { if (nxt->end_added) { - s_extra->next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; + s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; } } } else { @@ -4898,11 +4934,12 @@ found_one: * sinfo_ that is on the control's structure * :-D */ - s_extra->next_flags = SCTP_NO_NEXT_MSG; - s_extra->next_asocid = 0; - s_extra->next_length = 0; - s_extra->next_ppid = 0; - s_extra->next_stream = 0; + nxt = NULL; + s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; + s_extra->sreinfo_next_aid = 0; + s_extra->sreinfo_next_length = 0; + s_extra->sreinfo_next_ppid = 0; + s_extra->sreinfo_next_stream = 0; } } /* @@ -5023,6 +5060,8 @@ get_more_data: if ((SCTP_BUF_NEXT(m) == NULL) && (control->end_added)) { out_flags |= MSG_EOR; + if (control->do_not_ref_stcb == 0) + control->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started = 0; } if (control->spec_flags & M_NOTIFICATION) { out_flags |= MSG_NOTIFICATION; @@ -5293,8 +5332,15 @@ wait_some_more: if (control->end_added == 1) { /* he aborted, or is done i.e.did a shutdown */ out_flags |= MSG_EOR; - if (control->pdapi_aborted) + if (control->pdapi_aborted) { + if (control->do_not_ref_stcb == 0) + control->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started = 0; + out_flags |= MSG_TRUNC; + } else { + if (control->do_not_ref_stcb == 0) + control->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started = 0; + } goto done_with_control; } if (so->so_rcv.sb_cc > held_length) { @@ -5343,6 +5389,8 @@ get_more_data2: } if (control->end_added) { out_flags |= MSG_EOR; + if (control->do_not_ref_stcb == 0) + control->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started = 0; } if (control->spec_flags & M_NOTIFICATION) { out_flags |= MSG_NOTIFICATION; @@ -5405,8 +5453,11 @@ get_more_data2: * shutdown */ out_flags |= MSG_EOR; - if (control->pdapi_aborted) + if (control->pdapi_aborted) { out_flags |= MSG_TRUNC; + if (control->do_not_ref_stcb == 0) + control->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started = 0; + } goto done_with_control; } if (so->so_rcv.sb_cc > held_length) { @@ -5535,6 +5586,15 @@ release_unlocked: if (msg_flags) *msg_flags |= out_flags; out: + if (((out_flags & MSG_EOR) == 0) && + ((in_flags & MSG_PEEK) == 0) && + (sinfo) && + (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO))) { + struct sctp_extrcvinfo *s_extra; + + s_extra = (struct sctp_extrcvinfo *)sinfo; + s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; + } if (hold_rlock == 1) { SCTP_INP_READ_UNLOCK(inp); hold_rlock = 0; |