git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git]
/
net
/
sctp
/
outqueue.c
diff --git
a/net/sctp/outqueue.c
b/net/sctp/outqueue.c
index
1b2d4ad
..
e5faa35
100644
(file)
--- a/
net/sctp/outqueue.c
+++ b/
net/sctp/outqueue.c
@@
-75,7
+75,7
@@
static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);
static inline void sctp_outq_head_data(struct sctp_outq *q,
struct sctp_chunk *ch)
{
static inline void sctp_outq_head_data(struct sctp_outq *q,
struct sctp_chunk *ch)
{
-
__skb_queue_head(&q->out, (struct sk_buff *)ch
);
+
list_add(&ch->list, &q->out_chunk_list
);
q->out_qlen += ch->skb->len;
return;
}
q->out_qlen += ch->skb->len;
return;
}
@@
-83,17
+83,22
@@
static inline void sctp_outq_head_data(struct sctp_outq *q,
/* Take data from the front of the queue. */
static inline struct sctp_chunk *sctp_outq_dequeue_data(struct sctp_outq *q)
{
/* Take data from the front of the queue. */
static inline struct sctp_chunk *sctp_outq_dequeue_data(struct sctp_outq *q)
{
- struct sctp_chunk *ch;
- ch = (struct sctp_chunk *)__skb_dequeue(&q->out);
- if (ch)
+ struct sctp_chunk *ch = NULL;
+
+ if (!list_empty(&q->out_chunk_list)) {
+ struct list_head *entry = q->out_chunk_list.next;
+
+ ch = list_entry(entry, struct sctp_chunk, list);
+ list_del_init(entry);
q->out_qlen -= ch->skb->len;
q->out_qlen -= ch->skb->len;
+ }
return ch;
}
/* Add data chunk to the end of the queue. */
static inline void sctp_outq_tail_data(struct sctp_outq *q,
struct sctp_chunk *ch)
{
return ch;
}
/* Add data chunk to the end of the queue. */
static inline void sctp_outq_tail_data(struct sctp_outq *q,
struct sctp_chunk *ch)
{
-
__skb_queue_tail(&q->out, (struct sk_buff *)ch
);
+
list_add_tail(&ch->list, &q->out_chunk_list
);
q->out_qlen += ch->skb->len;
return;
}
q->out_qlen += ch->skb->len;
return;
}
@@
-197,8
+202,8
@@
static inline int sctp_cacc_skip(struct sctp_transport *primary,
void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
{
q->asoc = asoc;
void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
{
q->asoc = asoc;
-
skb_queue_head_init(&q->ou
t);
-
skb_queue_head_init(&q->control
);
+
INIT_LIST_HEAD(&q->out_chunk_lis
t);
+
INIT_LIST_HEAD(&q->control_chunk_list
);
INIT_LIST_HEAD(&q->retransmit);
INIT_LIST_HEAD(&q->sacked);
INIT_LIST_HEAD(&q->abandoned);
INIT_LIST_HEAD(&q->retransmit);
INIT_LIST_HEAD(&q->sacked);
INIT_LIST_HEAD(&q->abandoned);
@@
-217,7
+222,7
@@
void sctp_outq_teardown(struct sctp_outq *q)
{
struct sctp_transport *transport;
struct list_head *lchunk, *pos, *temp;
{
struct sctp_transport *transport;
struct list_head *lchunk, *pos, *temp;
- struct sctp_chunk *chunk;
+ struct sctp_chunk *chunk
, *tmp
;
/* Throw away unacknowledged chunks. */
list_for_each(pos, &q->asoc->peer.transport_addr_list) {
/* Throw away unacknowledged chunks. */
list_for_each(pos, &q->asoc->peer.transport_addr_list) {
@@
-269,8
+274,10
@@
void sctp_outq_teardown(struct sctp_outq *q)
q->error = 0;
/* Throw away any leftover control chunks. */
q->error = 0;
/* Throw away any leftover control chunks. */
- while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control)) != NULL)
+ list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
+ list_del_init(&chunk->list);
sctp_chunk_free(chunk);
sctp_chunk_free(chunk);
+ }
}
/* Free the outqueue structure and any related pending chunks. */
}
/* Free the outqueue structure and any related pending chunks. */
@@
-333,7
+340,7
@@
int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
break;
};
} else {
break;
};
} else {
-
__skb_queue_tail(&q->control, (struct sk_buff *) chunk
);
+
list_add_tail(&chunk->list, &q->control_chunk_list
);
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
}
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
}
@@
-399,7
+406,7
@@
void sctp_retransmit_mark(struct sctp_outq *q,
* chunks that are not yet acked should be added to the
* retransmit queue.
*/
* chunks that are not yet acked should be added to the
* retransmit queue.
*/
- if ((fast_retransmit &&
chunk->fast_retransmit
) ||
+ if ((fast_retransmit &&
(chunk->fast_retransmit > 0)
) ||
(!fast_retransmit && !chunk->tsn_gap_acked)) {
/* RFC 2960 6.2.1 Processing a Received SACK
*
(!fast_retransmit && !chunk->tsn_gap_acked)) {
/* RFC 2960 6.2.1 Processing a Received SACK
*
@@
-596,7
+603,8
@@
static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
/* Mark the chunk as ineligible for fast retransmit
* after it is retransmitted.
*/
/* Mark the chunk as ineligible for fast retransmit
* after it is retransmitted.
*/
- chunk->fast_retransmit = 0;
+ if (chunk->fast_retransmit > 0)
+ chunk->fast_retransmit = -1;
*start_timer = 1;
q->empty = 0;
*start_timer = 1;
q->empty = 0;
@@
-614,7
+622,8
@@
static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
list_for_each(lchunk1, lqueue) {
chunk1 = list_entry(lchunk1, struct sctp_chunk,
transmitted_list);
list_for_each(lchunk1, lqueue) {
chunk1 = list_entry(lchunk1, struct sctp_chunk,
transmitted_list);
- chunk1->fast_retransmit = 0;
+ if (chunk1->fast_retransmit > 0)
+ chunk1->fast_retransmit = -1;
}
}
}
}
}
}
@@
-650,10
+659,9
@@
int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
__u16 sport = asoc->base.bind_addr.port;
__u16 dport = asoc->peer.port;
__u32 vtag = asoc->peer.i.init_tag;
__u16 sport = asoc->base.bind_addr.port;
__u16 dport = asoc->peer.port;
__u32 vtag = asoc->peer.i.init_tag;
- struct sk_buff_head *queue;
struct sctp_transport *transport = NULL;
struct sctp_transport *new_transport;
struct sctp_transport *transport = NULL;
struct sctp_transport *new_transport;
- struct sctp_chunk *chunk;
+ struct sctp_chunk *chunk
, *tmp
;
sctp_xmit_t status;
int error = 0;
int start_timer = 0;
sctp_xmit_t status;
int error = 0;
int start_timer = 0;
@@
-675,16
+683,17
@@
int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
* ...
*/
* ...
*/
- queue = &q->control;
- while ((chunk = (struct sctp_chunk *)skb_dequeue(queue)) != NULL) {
+ list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
+ list_del_init(&chunk->list);
+
/* Pick the right transport to use. */
new_transport = chunk->transport;
if (!new_transport) {
new_transport = asoc->peer.active_path;
/* Pick the right transport to use. */
new_transport = chunk->transport;
if (!new_transport) {
new_transport = asoc->peer.active_path;
- } else if (
!new_transport->active
) {
- /* If the chunk is Heartbeat or Heartbeat Ack,
- * send it to chunk->transport, even if it's
+ } else if (
new_transport->state == SCTP_INACTIVE
) {
+ /* If the chunk is Heartbeat or Heartbeat Ack,
+ * send it to chunk->transport, even if it's
* inactive.
*
* 3.3.6 Heartbeat Acknowledgement:
* inactive.
*
* 3.3.6 Heartbeat Acknowledgement:
@@
-814,8
+823,6
@@
int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
/* Finally, transmit new packets. */
start_timer = 0;
/* Finally, transmit new packets. */
start_timer = 0;
- queue = &q->out;
-
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
* stream identifier.
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
* stream identifier.
@@
-840,7
+847,8
@@
int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
* Otherwise, we want to use the active path.
*/
new_transport = chunk->transport;
* Otherwise, we want to use the active path.
*/
new_transport = chunk->transport;
- if (!new_transport || !new_transport->active)
+ if (!new_transport ||
+ new_transport->state == SCTP_INACTIVE)
new_transport = asoc->peer.active_path;
/* Change packets if necessary. */
new_transport = asoc->peer.active_path;
/* Change packets if necessary. */
@@
-1148,8
+1156,9
@@
int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
/* See if all chunks are acked.
* Make sure the empty queue handler will get run later.
*/
/* See if all chunks are acked.
* Make sure the empty queue handler will get run later.
*/
- q->empty = skb_queue_empty(&q->out) && skb_queue_empty(&q->control) &&
- list_empty(&q->retransmit);
+ q->empty = (list_empty(&q->out_chunk_list) &&
+ list_empty(&q->control_chunk_list) &&
+ list_empty(&q->retransmit));
if (!q->empty)
goto finish;
if (!q->empty)
goto finish;
@@
-1253,6
+1262,7
@@
static void sctp_check_transmitted(struct sctp_outq *q,
if (!tchunk->tsn_gap_acked &&
!tchunk->resent &&
tchunk->rtt_in_progress) {
if (!tchunk->tsn_gap_acked &&
!tchunk->resent &&
tchunk->rtt_in_progress) {
+ tchunk->rtt_in_progress = 0;
rtt = jiffies - tchunk->sent_at;
sctp_transport_update_rto(transport,
rtt);
rtt = jiffies - tchunk->sent_at;
sctp_transport_update_rto(transport,
rtt);
@@
-1454,7
+1464,7
@@
static void sctp_check_transmitted(struct sctp_outq *q,
/* Mark the destination transport address as
* active if it is not so marked.
*/
/* Mark the destination transport address as
* active if it is not so marked.
*/
- if (
!transport->active
) {
+ if (
transport->state == SCTP_INACTIVE
) {
sctp_assoc_control_transport(
transport->asoc,
transport,
sctp_assoc_control_transport(
transport->asoc,
transport,
@@
-1555,11
+1565,11
@@
static void sctp_mark_missing(struct sctp_outq *q,
/*
* M4) If any DATA chunk is found to have a
* 'TSN.Missing.Report'
/*
* M4) If any DATA chunk is found to have a
* 'TSN.Missing.Report'
- * value larger than or equal to
4
, mark that chunk for
+ * value larger than or equal to
3
, mark that chunk for
* retransmission and start the fast retransmit procedure.
*/
* retransmission and start the fast retransmit procedure.
*/
- if (chunk->tsn_missing_report >=
4
) {
+ if (chunk->tsn_missing_report >=
3
) {
chunk->fast_retransmit = 1;
do_fast_retransmit = 1;
}
chunk->fast_retransmit = 1;
do_fast_retransmit = 1;
}
@@
-1678,9
+1688,9
@@
static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
if (TSN_lte(tsn, ctsn)) {
list_del_init(lchunk);
if (!chunk->tsn_gap_acked) {
if (TSN_lte(tsn, ctsn)) {
list_del_init(lchunk);
if (!chunk->tsn_gap_acked) {
- chunk->transport->flight_size -=
-
sctp_data_size(chunk);
- q->outstanding_bytes -= sctp_data_size(chunk);
+
chunk->transport->flight_size -=
+ sctp_data_size(chunk);
+
q->outstanding_bytes -= sctp_data_size(chunk);
}
sctp_chunk_free(chunk);
} else {
}
sctp_chunk_free(chunk);
} else {
@@
-1728,7
+1738,7
@@
static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
nskips, &ftsn_skip_arr[0]);
if (ftsn_chunk) {
nskips, &ftsn_skip_arr[0]);
if (ftsn_chunk) {
-
__skb_queue_tail(&q->control, (struct sk_buff *)ftsn_chunk
);
+
list_add_tail(&ftsn_chunk->list, &q->control_chunk_list
);
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
}
}
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
}
}