Commit 0e0059c1 authored by Sridhar Samudrala's avatar Sridhar Samudrala Committed by Sridhar Samudrala

[SCTP] Window update SACK support.

parent d12add25
...@@ -1360,6 +1360,9 @@ struct SCTP_association { ...@@ -1360,6 +1360,9 @@ struct SCTP_association {
*/ */
__u32 rwnd; __u32 rwnd;
/* This is the last advertised value of rwnd over a SACK chunk. */
__u32 a_rwnd;
/* Number of bytes by which the rwnd has slopped. The rwnd is allowed /* Number of bytes by which the rwnd has slopped. The rwnd is allowed
* to slop over a maximum of the association's frag_point. * to slop over a maximum of the association's frag_point.
*/ */
......
...@@ -186,6 +186,8 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -186,6 +186,8 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
else else
asoc->rwnd = sk->rcvbuf; asoc->rwnd = sk->rcvbuf;
asoc->a_rwnd = 0;
asoc->rwnd_over = 0; asoc->rwnd_over = 0;
/* Use my own max window until I learn something better. */ /* Use my own max window until I learn something better. */
......
...@@ -737,6 +737,9 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands) ...@@ -737,6 +737,9 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands)
if (!sack) if (!sack)
goto nomem; goto nomem;
/* Update the last advertised rwnd value. */
asoc->a_rwnd = asoc->rwnd;
asoc->peer.sack_needed = 0; asoc->peer.sack_needed = 0;
asoc->peer.next_dup_tsn = 0; asoc->peer.next_dup_tsn = 0;
......
...@@ -762,6 +762,8 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb) ...@@ -762,6 +762,8 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
{ {
sctp_association_t *asoc; sctp_association_t *asoc;
sctp_ulpevent_t *event; sctp_ulpevent_t *event;
sctp_chunk_t *sack;
struct timer_list *timer;
/* Current stack structures assume that the rcv buffer is /* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as * per socket. For UDP style sockets this is not true as
...@@ -782,9 +784,39 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb) ...@@ -782,9 +784,39 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
asoc->rwnd += skb->len; asoc->rwnd += skb->len;
} }
SCTP_DEBUG_PRINTK("rwnd increased by %d to (%u, %u)\n", SCTP_DEBUG_PRINTK("rwnd increased by %d to (%u, %u) - %u\n",
skb->len, asoc->rwnd, asoc->rwnd_over); skb->len, asoc->rwnd, asoc->rwnd_over, asoc->a_rwnd);
/* Send a window update SACK if the rwnd has increased by at least the
* minimum of the association's PMTU and half of the receive buffer.
* The algorithm used is similar to the one described in Section 4.2.3.3
* of RFC 1122.
*/
if ((asoc->state == SCTP_STATE_ESTABLISHED) &&
(asoc->rwnd > asoc->a_rwnd) &&
((asoc->rwnd - asoc->a_rwnd) >=
min_t(__u32, (asoc->base.sk->rcvbuf >> 1), asoc->pmtu))) {
SCTP_DEBUG_PRINTK("Sending window update SACK- rwnd: %u "
"a_rwnd: %u\n", asoc->rwnd, asoc->a_rwnd);
sack = sctp_make_sack(asoc);
if (!sack)
goto out;
/* Update the last advertised rwnd value. */
asoc->a_rwnd = asoc->rwnd;
asoc->peer.sack_needed = 0;
asoc->peer.next_dup_tsn = 0;
sctp_push_outqueue(&asoc->outqueue, sack);
/* Stop the SACK timer. */
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
if (timer_pending(timer) && del_timer(timer))
sctp_association_put(asoc);
}
out:
sctp_association_put(asoc); sctp_association_put(asoc);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment