Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 26523
b: refs/heads/master
c: 7c3ceb4
h: refs/heads/master
i:
  26521: a0a0dc8
  26519: 0ba7d1f
v: v3
  • Loading branch information
Neil Horman authored and David S. Miller committed May 6, 2006
1 parent d6fe05d commit c2180e1
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 91ef5d2d6e934762db9c3e0d9e5b2862e40ea429
refs/heads/master: 7c3ceb4fb9667f34f1599a062efecf4cdc4a4ce5
1 change: 1 addition & 0 deletions trunk/include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@ struct sctp_chunk {
__u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */
__s8 fast_retransmit; /* Is this chunk fast retransmitted? */
__u8 tsn_missing_report; /* Data chunk missing counter. */
__u8 data_accepted; /* At least 1 chunk in this packet accepted */
};

void sctp_chunk_hold(struct sctp_chunk *);
Expand Down
1 change: 1 addition & 0 deletions trunk/net/sctp/inqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
/* This is the first chunk in the packet. */
chunk->singleton = 1;
ch = (sctp_chunkhdr_t *) chunk->skb->data;
chunk->data_accepted = 0;
}

chunk->chunk_hdr = ch;
Expand Down
46 changes: 36 additions & 10 deletions trunk/net/sctp/sm_statefuns.c
Original file line number Diff line number Diff line change
Expand Up @@ -5151,7 +5151,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
int tmp;
__u32 tsn;
int account_value;
struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
struct sock *sk = asoc->base.sk;
int rcvbuf_over = 0;

data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
Expand All @@ -5162,10 +5164,16 @@ static int sctp_eat_data(const struct sctp_association *asoc,
/* ASSERT: Now skb->data is really the user data. */

/*
* if we are established, and we have used up our receive
* buffer memory, drop the frame
*/
if (asoc->state == SCTP_STATE_ESTABLISHED) {
* If we are established, and we have used up our receive buffer
* memory, think about droping the frame.
* Note that we have an opportunity to improve performance here.
* If we accept one chunk from an skbuff, we have to keep all the
* memory of that skbuff around until the chunk is read into user
* space. Therefore, once we accept 1 chunk we may as well accept all
* remaining chunks in the skbuff. The data_accepted flag helps us do
* that.
*/
if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) {
/*
* If the receive buffer policy is 1, then each
* association can allocate up to sk_rcvbuf bytes
Expand All @@ -5176,9 +5184,25 @@ static int sctp_eat_data(const struct sctp_association *asoc,
account_value = atomic_read(&asoc->rmem_alloc);
else
account_value = atomic_read(&sk->sk_rmem_alloc);

if (account_value > sk->sk_rcvbuf)
return SCTP_IERROR_IGNORE_TSN;
if (account_value > sk->sk_rcvbuf) {
/*
* We need to make forward progress, even when we are
* under memory pressure, so we always allow the
* next tsn after the ctsn ack point to be accepted.
* This lets us avoid deadlocks in which we have to
* drop frames that would otherwise let us drain the
* receive queue.
*/
if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn)
return SCTP_IERROR_IGNORE_TSN;

/*
* We're going to accept the frame but we should renege
* to make space for it. This will send us down that
* path later in this function.
*/
rcvbuf_over = 1;
}
}

/* Process ECN based congestion.
Expand Down Expand Up @@ -5226,6 +5250,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
datalen -= sizeof(sctp_data_chunk_t);

deliver = SCTP_CMD_CHUNK_ULP;
chunk->data_accepted = 1;

/* Think about partial delivery. */
if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
Expand All @@ -5242,16 +5267,17 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* large spill over.
*/
if (!asoc->rwnd || asoc->rwnd_over ||
(datalen > asoc->rwnd + asoc->frag_point)) {
(datalen > asoc->rwnd + asoc->frag_point) ||
rcvbuf_over) {

/* If this is the next TSN, consider reneging to make
* room. Note: Playing nice with a confused sender. A
* malicious sender can still eat up all our buffer
* space and in the future we may want to detect and
* do more drastic reneging.
*/
if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
(sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
if (sctp_tsnmap_has_gap(map) &&
(sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
deliver = SCTP_CMD_RENEGE;
} else {
Expand Down

0 comments on commit c2180e1

Please sign in to comment.