aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-11-29 03:16:22 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-29 03:16:22 -0500
commit5656b6ca19c602a7074effae360e5a4dcfdc8170 (patch)
tree13eb8138999a3c6a8e6f92fb98b0cc54b7240c6a /net
parentc1ac403bfa240617da2bce861ea5c3a907a65612 (diff)
parent4814326b59db0cfd18ac652626d955ad3f57fb0f (diff)
Merge branch 'net-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vxy/lksctp-dev
Diffstat (limited to 'net')
-rw-r--r--net/sctp/associola.c27
-rw-r--r--net/sctp/chunk.c15
-rw-r--r--net/sctp/output.c50
-rw-r--r--net/sctp/outqueue.c22
-rw-r--r--net/sctp/protocol.c3
-rw-r--r--net/sctp/sm_make_chunk.c13
-rw-r--r--net/sctp/sm_sideeffect.c5
-rw-r--r--net/sctp/sm_statefuns.c26
-rw-r--r--net/sctp/socket.c335
-rw-r--r--net/sctp/sysctl.c13
-rw-r--r--net/sctp/transport.c45
11 files changed, 163 insertions, 391 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 7eed77a39d0d..df5abbff63e2 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -63,6 +63,12 @@
63static void sctp_assoc_bh_rcv(struct work_struct *work); 63static void sctp_assoc_bh_rcv(struct work_struct *work);
64static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc); 64static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
65 65
66/* Keep track of the new idr low so that we don't re-use association id
67 * numbers too fast. It is protected by they idr spin lock is in the
68 * range of 1 - INT_MAX.
69 */
70static u32 idr_low = 1;
71
66 72
67/* 1st Level Abstractions. */ 73/* 1st Level Abstractions. */
68 74
@@ -167,7 +173,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
167 asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; 173 asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
168 asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; 174 asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
169 asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = 175 asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
170 sp->autoclose * HZ; 176 (unsigned long)sp->autoclose * HZ;
171 177
172 /* Initilizes the timers */ 178 /* Initilizes the timers */
173 for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) 179 for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
@@ -512,7 +518,13 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
512 * to this destination address earlier. The sender MUST set 518 * to this destination address earlier. The sender MUST set
513 * CYCLING_CHANGEOVER to indicate that this switch is a 519 * CYCLING_CHANGEOVER to indicate that this switch is a
514 * double switch to the same destination address. 520 * double switch to the same destination address.
521 *
522 * Really, only bother is we have data queued or outstanding on
523 * the association.
515 */ 524 */
525 if (!asoc->outqueue.outstanding_bytes && !asoc->outqueue.out_qlen)
526 return;
527
516 if (transport->cacc.changeover_active) 528 if (transport->cacc.changeover_active)
517 transport->cacc.cycling_changeover = changeover; 529 transport->cacc.cycling_changeover = changeover;
518 530
@@ -732,6 +744,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
732 744
733 peer->partial_bytes_acked = 0; 745 peer->partial_bytes_acked = 0;
734 peer->flight_size = 0; 746 peer->flight_size = 0;
747 peer->burst_limited = 0;
735 748
736 /* Set the transport's RTO.initial value */ 749 /* Set the transport's RTO.initial value */
737 peer->rto = asoc->rto_initial; 750 peer->rto = asoc->rto_initial;
@@ -1377,8 +1390,9 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
1377 case SCTP_STATE_SHUTDOWN_RECEIVED: 1390 case SCTP_STATE_SHUTDOWN_RECEIVED:
1378 case SCTP_STATE_SHUTDOWN_SENT: 1391 case SCTP_STATE_SHUTDOWN_SENT:
1379 if ((asoc->rwnd > asoc->a_rwnd) && 1392 if ((asoc->rwnd > asoc->a_rwnd) &&
1380 ((asoc->rwnd - asoc->a_rwnd) >= 1393 ((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
1381 min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pathmtu))) 1394 (asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift),
1395 asoc->pathmtu)))
1382 return 1; 1396 return 1;
1383 break; 1397 break;
1384 default: 1398 default:
@@ -1545,7 +1559,12 @@ retry:
1545 1559
1546 spin_lock_bh(&sctp_assocs_id_lock); 1560 spin_lock_bh(&sctp_assocs_id_lock);
1547 error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, 1561 error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
1548 1, &assoc_id); 1562 idr_low, &assoc_id);
1563 if (!error) {
1564 idr_low = assoc_id + 1;
1565 if (idr_low == INT_MAX)
1566 idr_low = 1;
1567 }
1549 spin_unlock_bh(&sctp_assocs_id_lock); 1568 spin_unlock_bh(&sctp_assocs_id_lock);
1550 if (error == -EAGAIN) 1569 if (error == -EAGAIN)
1551 goto retry; 1570 goto retry;
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index acf7c4d128f7..8e4320040f05 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -263,9 +263,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
263 if (0 == i) 263 if (0 == i)
264 frag |= SCTP_DATA_FIRST_FRAG; 264 frag |= SCTP_DATA_FIRST_FRAG;
265 265
266 if ((i == (whole - 1)) && !over) 266 if ((i == (whole - 1)) && !over) {
267 frag |= SCTP_DATA_LAST_FRAG; 267 frag |= SCTP_DATA_LAST_FRAG;
268 268
269 /* The application requests to set the I-bit of the
270 * last DATA chunk of a user message when providing
271 * the user message to the SCTP implementation.
272 */
273 if ((sinfo->sinfo_flags & SCTP_EOF) ||
274 (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
275 frag |= SCTP_DATA_SACK_IMM;
276 }
277
269 chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); 278 chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
270 279
271 if (!chunk) 280 if (!chunk)
@@ -297,6 +306,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
297 else 306 else
298 frag = SCTP_DATA_LAST_FRAG; 307 frag = SCTP_DATA_LAST_FRAG;
299 308
309 if ((sinfo->sinfo_flags & SCTP_EOF) ||
310 (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
311 frag |= SCTP_DATA_SACK_IMM;
312
300 chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); 313 chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
301 314
302 if (!chunk) 315 if (!chunk)
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 5cbda8f1ddfd..7c5589363433 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -429,23 +429,22 @@ int sctp_packet_transmit(struct sctp_packet *packet)
429 list_del_init(&chunk->list); 429 list_del_init(&chunk->list);
430 if (sctp_chunk_is_data(chunk)) { 430 if (sctp_chunk_is_data(chunk)) {
431 431
432 if (!chunk->has_tsn) { 432 if (!chunk->resent) {
433 sctp_chunk_assign_ssn(chunk); 433
434 sctp_chunk_assign_tsn(chunk); 434 /* 6.3.1 C4) When data is in flight and when allowed
435 435 * by rule C5, a new RTT measurement MUST be made each
436 /* 6.3.1 C4) When data is in flight and when allowed 436 * round trip. Furthermore, new RTT measurements
437 * by rule C5, a new RTT measurement MUST be made each 437 * SHOULD be made no more than once per round-trip
438 * round trip. Furthermore, new RTT measurements 438 * for a given destination transport address.
439 * SHOULD be made no more than once per round-trip 439 */
440 * for a given destination transport address.
441 */
442 440
443 if (!tp->rto_pending) { 441 if (!tp->rto_pending) {
444 chunk->rtt_in_progress = 1; 442 chunk->rtt_in_progress = 1;
445 tp->rto_pending = 1; 443 tp->rto_pending = 1;
446 } 444 }
447 } else 445 }
448 chunk->resent = 1; 446
447 chunk->resent = 1;
449 448
450 has_data = 1; 449 has_data = 1;
451 } 450 }
@@ -557,8 +556,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
557 struct timer_list *timer; 556 struct timer_list *timer;
558 unsigned long timeout; 557 unsigned long timeout;
559 558
560 tp->last_time_used = jiffies;
561
562 /* Restart the AUTOCLOSE timer when sending data. */ 559 /* Restart the AUTOCLOSE timer when sending data. */
563 if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) { 560 if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
564 timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; 561 timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
@@ -617,7 +614,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
617 sctp_xmit_t retval = SCTP_XMIT_OK; 614 sctp_xmit_t retval = SCTP_XMIT_OK;
618 size_t datasize, rwnd, inflight, flight_size; 615 size_t datasize, rwnd, inflight, flight_size;
619 struct sctp_transport *transport = packet->transport; 616 struct sctp_transport *transport = packet->transport;
620 __u32 max_burst_bytes;
621 struct sctp_association *asoc = transport->asoc; 617 struct sctp_association *asoc = transport->asoc;
622 struct sctp_outq *q = &asoc->outqueue; 618 struct sctp_outq *q = &asoc->outqueue;
623 619
@@ -650,28 +646,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
650 } 646 }
651 } 647 }
652 648
653 /* sctpimpguide-05 2.14.2
654 * D) When the time comes for the sender to
655 * transmit new DATA chunks, the protocol parameter Max.Burst MUST
656 * first be applied to limit how many new DATA chunks may be sent.
657 * The limit is applied by adjusting cwnd as follows:
658 * if ((flightsize + Max.Burst * MTU) < cwnd)
659 * cwnd = flightsize + Max.Burst * MTU
660 */
661 max_burst_bytes = asoc->max_burst * asoc->pathmtu;
662 if ((flight_size + max_burst_bytes) < transport->cwnd) {
663 transport->cwnd = flight_size + max_burst_bytes;
664 SCTP_DEBUG_PRINTK("%s: cwnd limited by max_burst: "
665 "transport: %p, cwnd: %d, "
666 "ssthresh: %d, flight_size: %d, "
667 "pba: %d\n",
668 __func__, transport,
669 transport->cwnd,
670 transport->ssthresh,
671 transport->flight_size,
672 transport->partial_bytes_acked);
673 }
674
675 /* RFC 2960 6.1 Transmission of DATA Chunks 649 /* RFC 2960 6.1 Transmission of DATA Chunks
676 * 650 *
677 * B) At any given time, the sender MUST NOT transmit new data 651 * B) At any given time, the sender MUST NOT transmit new data
@@ -747,6 +721,8 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
747 /* Has been accepted for transmission. */ 721 /* Has been accepted for transmission. */
748 if (!asoc->peer.prsctp_capable) 722 if (!asoc->peer.prsctp_capable)
749 chunk->msg->can_abandon = 0; 723 chunk->msg->can_abandon = 0;
724 sctp_chunk_assign_tsn(chunk);
725 sctp_chunk_assign_ssn(chunk);
750} 726}
751 727
752static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet, 728static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet,
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index c9f20e28521b..2f2377369e2b 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -931,6 +931,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
931 goto sctp_flush_out; 931 goto sctp_flush_out;
932 } 932 }
933 933
934 /* Apply Max.Burst limitation to the current transport in
935 * case it will be used for new data. We are going to
936 * rest it before we return, but we want to apply the limit
937 * to the currently queued data.
938 */
939 if (transport)
940 sctp_transport_burst_limited(transport);
941
934 /* Finally, transmit new packets. */ 942 /* Finally, transmit new packets. */
935 while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { 943 while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
936 /* RFC 2960 6.5 Every DATA chunk MUST carry a valid 944 /* RFC 2960 6.5 Every DATA chunk MUST carry a valid
@@ -976,6 +984,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
976 packet = &transport->packet; 984 packet = &transport->packet;
977 sctp_packet_config(packet, vtag, 985 sctp_packet_config(packet, vtag,
978 asoc->peer.ecn_capable); 986 asoc->peer.ecn_capable);
987 /* We've switched transports, so apply the
988 * Burst limit to the new transport.
989 */
990 sctp_transport_burst_limited(transport);
979 } 991 }
980 992
981 SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ", 993 SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ",
@@ -1011,6 +1023,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
1011 break; 1023 break;
1012 1024
1013 case SCTP_XMIT_OK: 1025 case SCTP_XMIT_OK:
1026 /* The sender is in the SHUTDOWN-PENDING state,
1027 * The sender MAY set the I-bit in the DATA
1028 * chunk header.
1029 */
1030 if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING)
1031 chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM;
1032
1014 break; 1033 break;
1015 1034
1016 default: 1035 default:
@@ -1063,6 +1082,9 @@ sctp_flush_out:
1063 packet = &t->packet; 1082 packet = &t->packet;
1064 if (!sctp_packet_empty(packet)) 1083 if (!sctp_packet_empty(packet))
1065 error = sctp_packet_transmit(packet); 1084 error = sctp_packet_transmit(packet);
1085
1086 /* Clear the burst limited state, if any */
1087 sctp_transport_burst_reset(t);
1066 } 1088 }
1067 1089
1068 return error; 1090 return error;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 08ef203d36ac..a3c8988758b1 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1258,6 +1258,9 @@ SCTP_STATIC __init int sctp_init(void)
1258 /* Set SCOPE policy to enabled */ 1258 /* Set SCOPE policy to enabled */
1259 sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE; 1259 sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
1260 1260
1261 /* Set the default rwnd update threshold */
1262 sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT;
1263
1261 sctp_sysctl_register(); 1264 sctp_sysctl_register();
1262 1265
1263 INIT_LIST_HEAD(&sctp_address_families); 1266 INIT_LIST_HEAD(&sctp_address_families);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 9d881a61ac02..9e732916b671 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -987,7 +987,10 @@ static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
987 987
988 target = skb_put(chunk->skb, len); 988 target = skb_put(chunk->skb, len);
989 989
990 memcpy(target, data, len); 990 if (data)
991 memcpy(target, data, len);
992 else
993 memset(target, 0, len);
991 994
992 /* Adjust the chunk length field. */ 995 /* Adjust the chunk length field. */
993 chunk->chunk_hdr->length = htons(chunklen + len); 996 chunk->chunk_hdr->length = htons(chunklen + len);
@@ -1129,16 +1132,18 @@ nodata:
1129struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, 1132struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
1130 const struct sctp_chunk *chunk, 1133 const struct sctp_chunk *chunk,
1131 __be16 cause_code, const void *payload, 1134 __be16 cause_code, const void *payload,
1132 size_t paylen) 1135 size_t paylen, size_t reserve_tail)
1133{ 1136{
1134 struct sctp_chunk *retval; 1137 struct sctp_chunk *retval;
1135 1138
1136 retval = sctp_make_op_error_space(asoc, chunk, paylen); 1139 retval = sctp_make_op_error_space(asoc, chunk, paylen + reserve_tail);
1137 if (!retval) 1140 if (!retval)
1138 goto nodata; 1141 goto nodata;
1139 1142
1140 sctp_init_cause(retval, cause_code, paylen); 1143 sctp_init_cause(retval, cause_code, paylen + reserve_tail);
1141 sctp_addto_chunk(retval, paylen, payload); 1144 sctp_addto_chunk(retval, paylen, payload);
1145 if (reserve_tail)
1146 sctp_addto_param(retval, reserve_tail, NULL);
1142 1147
1143nodata: 1148nodata:
1144 return retval; 1149 return retval;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 8674d4919556..8ae67098e094 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -217,8 +217,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
217 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 217 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
218 SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); 218 SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
219 } else { 219 } else {
220 if (asoc->a_rwnd > asoc->rwnd) 220 asoc->a_rwnd = asoc->rwnd;
221 asoc->a_rwnd = asoc->rwnd;
222 sack = sctp_make_sack(asoc); 221 sack = sctp_make_sack(asoc);
223 if (!sack) 222 if (!sack)
224 goto nomem; 223 goto nomem;
@@ -1418,6 +1417,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1418 asoc->init_last_sent_to = t; 1417 asoc->init_last_sent_to = t;
1419 chunk->transport = t; 1418 chunk->transport = t;
1420 t->init_sent_count++; 1419 t->init_sent_count++;
1420 /* Set the new transport as primary */
1421 sctp_assoc_set_primary(asoc, t);
1421 break; 1422 break;
1422 1423
1423 case SCTP_CMD_INIT_RESTART: 1424 case SCTP_CMD_INIT_RESTART:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d4df45022ffa..1ef9de9bbae9 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -996,14 +996,15 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
996 sctp_sf_heartbeat(ep, asoc, type, arg, 996 sctp_sf_heartbeat(ep, asoc, type, arg,
997 commands)) 997 commands))
998 return SCTP_DISPOSITION_NOMEM; 998 return SCTP_DISPOSITION_NOMEM;
999
999 /* Set transport error counter and association error counter 1000 /* Set transport error counter and association error counter
1000 * when sending heartbeat. 1001 * when sending heartbeat.
1001 */ 1002 */
1002 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE,
1003 SCTP_TRANSPORT(transport));
1004 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT, 1003 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT,
1005 SCTP_TRANSPORT(transport)); 1004 SCTP_TRANSPORT(transport));
1006 } 1005 }
1006 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE,
1007 SCTP_TRANSPORT(transport));
1007 sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE, 1008 sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,
1008 SCTP_TRANSPORT(transport)); 1009 SCTP_TRANSPORT(transport));
1009 1010
@@ -1720,7 +1721,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
1720 1721
1721 err = sctp_make_op_error(asoc, chunk, 1722 err = sctp_make_op_error(asoc, chunk,
1722 SCTP_ERROR_COOKIE_IN_SHUTDOWN, 1723 SCTP_ERROR_COOKIE_IN_SHUTDOWN,
1723 NULL, 0); 1724 NULL, 0, 0);
1724 if (err) 1725 if (err)
1725 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 1726 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
1726 SCTP_CHUNK(err)); 1727 SCTP_CHUNK(err));
@@ -2868,6 +2869,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
2868 sctp_cmd_seq_t *commands) 2869 sctp_cmd_seq_t *commands)
2869{ 2870{
2870 struct sctp_chunk *chunk = arg; 2871 struct sctp_chunk *chunk = arg;
2872 sctp_arg_t force = SCTP_NOFORCE();
2871 int error; 2873 int error;
2872 2874
2873 if (!sctp_vtag_verify(chunk, asoc)) { 2875 if (!sctp_vtag_verify(chunk, asoc)) {
@@ -2901,6 +2903,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
2901 BUG(); 2903 BUG();
2902 } 2904 }
2903 2905
2906 if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM)
2907 force = SCTP_FORCE();
2908
2904 if (asoc->autoclose) { 2909 if (asoc->autoclose) {
2905 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 2910 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
2906 SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 2911 SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
@@ -2929,7 +2934,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
2929 * more aggressive than the following algorithms allow. 2934 * more aggressive than the following algorithms allow.
2930 */ 2935 */
2931 if (chunk->end_of_packet) 2936 if (chunk->end_of_packet)
2932 sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE()); 2937 sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);
2933 2938
2934 return SCTP_DISPOSITION_CONSUME; 2939 return SCTP_DISPOSITION_CONSUME;
2935 2940
@@ -2954,7 +2959,7 @@ discard_force:
2954 2959
2955discard_noforce: 2960discard_noforce:
2956 if (chunk->end_of_packet) 2961 if (chunk->end_of_packet)
2957 sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE()); 2962 sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);
2958 2963
2959 return SCTP_DISPOSITION_DISCARD; 2964 return SCTP_DISPOSITION_DISCARD;
2960consume: 2965consume:
@@ -3973,7 +3978,7 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
3973 err_chunk = sctp_make_op_error(asoc, chunk, 3978 err_chunk = sctp_make_op_error(asoc, chunk,
3974 SCTP_ERROR_UNSUP_HMAC, 3979 SCTP_ERROR_UNSUP_HMAC,
3975 &auth_hdr->hmac_id, 3980 &auth_hdr->hmac_id,
3976 sizeof(__u16)); 3981 sizeof(__u16), 0);
3977 if (err_chunk) { 3982 if (err_chunk) {
3978 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3983 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
3979 SCTP_CHUNK(err_chunk)); 3984 SCTP_CHUNK(err_chunk));
@@ -4065,7 +4070,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
4065 hdr = unk_chunk->chunk_hdr; 4070 hdr = unk_chunk->chunk_hdr;
4066 err_chunk = sctp_make_op_error(asoc, unk_chunk, 4071 err_chunk = sctp_make_op_error(asoc, unk_chunk,
4067 SCTP_ERROR_UNKNOWN_CHUNK, hdr, 4072 SCTP_ERROR_UNKNOWN_CHUNK, hdr,
4068 WORD_ROUND(ntohs(hdr->length))); 4073 WORD_ROUND(ntohs(hdr->length)),
4074 0);
4069 if (err_chunk) { 4075 if (err_chunk) {
4070 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 4076 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
4071 SCTP_CHUNK(err_chunk)); 4077 SCTP_CHUNK(err_chunk));
@@ -4084,7 +4090,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
4084 hdr = unk_chunk->chunk_hdr; 4090 hdr = unk_chunk->chunk_hdr;
4085 err_chunk = sctp_make_op_error(asoc, unk_chunk, 4091 err_chunk = sctp_make_op_error(asoc, unk_chunk,
4086 SCTP_ERROR_UNKNOWN_CHUNK, hdr, 4092 SCTP_ERROR_UNKNOWN_CHUNK, hdr,
4087 WORD_ROUND(ntohs(hdr->length))); 4093 WORD_ROUND(ntohs(hdr->length)),
4094 0);
4088 if (err_chunk) { 4095 if (err_chunk) {
4089 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 4096 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
4090 SCTP_CHUNK(err_chunk)); 4097 SCTP_CHUNK(err_chunk));
@@ -6048,7 +6055,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
6048 6055
6049 err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, 6056 err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
6050 &data_hdr->stream, 6057 &data_hdr->stream,
6051 sizeof(data_hdr->stream)); 6058 sizeof(data_hdr->stream),
6059 sizeof(u16));
6052 if (err) 6060 if (err)
6053 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 6061 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
6054 SCTP_CHUNK(err)); 6062 SCTP_CHUNK(err));
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 66b1f02b17ba..71513b3926a5 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2086,6 +2086,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
2086 return -EINVAL; 2086 return -EINVAL;
2087 if (copy_from_user(&sp->autoclose, optval, optlen)) 2087 if (copy_from_user(&sp->autoclose, optval, optlen))
2088 return -EFAULT; 2088 return -EFAULT;
2089 /* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */
2090 if (sp->autoclose > (MAX_SCHEDULE_TIMEOUT / HZ) )
2091 sp->autoclose = MAX_SCHEDULE_TIMEOUT / HZ ;
2089 2092
2090 return 0; 2093 return 0;
2091} 2094}
@@ -2311,11 +2314,10 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
2311 } 2314 }
2312 } 2315 }
2313 2316
2314 /* Note that unless the spp_flag is set to SPP_PMTUD_ENABLE the value 2317 /* Note that a value of zero indicates the current setting should be
2315 * of this field is ignored. Note also that a value of zero 2318 left unchanged.
2316 * indicates the current setting should be left unchanged.
2317 */ 2319 */
2318 if ((params->spp_flags & SPP_PMTUD_ENABLE) && params->spp_pathmaxrxt) { 2320 if (params->spp_pathmaxrxt) {
2319 if (trans) { 2321 if (trans) {
2320 trans->pathmaxrxt = params->spp_pathmaxrxt; 2322 trans->pathmaxrxt = params->spp_pathmaxrxt;
2321 } else if (asoc) { 2323 } else if (asoc) {
@@ -4349,90 +4351,6 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval
4349 return 0; 4351 return 0;
4350} 4352}
4351 4353
4352static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len,
4353 char __user *optval,
4354 int __user *optlen)
4355{
4356 sctp_assoc_t id;
4357 struct sctp_association *asoc;
4358 struct list_head *pos;
4359 int cnt = 0;
4360
4361 if (len < sizeof(sctp_assoc_t))
4362 return -EINVAL;
4363
4364 if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
4365 return -EFAULT;
4366
4367 printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_NUM_OLD "
4368 "socket option deprecated\n");
4369 /* For UDP-style sockets, id specifies the association to query. */
4370 asoc = sctp_id2assoc(sk, id);
4371 if (!asoc)
4372 return -EINVAL;
4373
4374 list_for_each(pos, &asoc->peer.transport_addr_list) {
4375 cnt ++;
4376 }
4377
4378 return cnt;
4379}
4380
4381/*
4382 * Old API for getting list of peer addresses. Does not work for 32-bit
4383 * programs running on a 64-bit kernel
4384 */
4385static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
4386 char __user *optval,
4387 int __user *optlen)
4388{
4389 struct sctp_association *asoc;
4390 int cnt = 0;
4391 struct sctp_getaddrs_old getaddrs;
4392 struct sctp_transport *from;
4393 void __user *to;
4394 union sctp_addr temp;
4395 struct sctp_sock *sp = sctp_sk(sk);
4396 int addrlen;
4397
4398 if (len < sizeof(struct sctp_getaddrs_old))
4399 return -EINVAL;
4400
4401 len = sizeof(struct sctp_getaddrs_old);
4402
4403 if (copy_from_user(&getaddrs, optval, len))
4404 return -EFAULT;
4405
4406 if (getaddrs.addr_num <= 0) return -EINVAL;
4407
4408 printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_OLD "
4409 "socket option deprecated\n");
4410
4411 /* For UDP-style sockets, id specifies the association to query. */
4412 asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
4413 if (!asoc)
4414 return -EINVAL;
4415
4416 to = (void __user *)getaddrs.addrs;
4417 list_for_each_entry(from, &asoc->peer.transport_addr_list,
4418 transports) {
4419 memcpy(&temp, &from->ipaddr, sizeof(temp));
4420 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
4421 addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
4422 if (copy_to_user(to, &temp, addrlen))
4423 return -EFAULT;
4424 to += addrlen ;
4425 cnt ++;
4426 if (cnt >= getaddrs.addr_num) break;
4427 }
4428 getaddrs.addr_num = cnt;
4429 if (put_user(len, optlen))
4430 return -EFAULT;
4431 if (copy_to_user(optval, &getaddrs, len))
4432 return -EFAULT;
4433
4434 return 0;
4435}
4436 4354
4437static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, 4355static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
4438 char __user *optval, int __user *optlen) 4356 char __user *optval, int __user *optlen)
@@ -4485,125 +4403,6 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
4485 return 0; 4403 return 0;
4486} 4404}
4487 4405
4488static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
4489 char __user *optval,
4490 int __user *optlen)
4491{
4492 sctp_assoc_t id;
4493 struct sctp_bind_addr *bp;
4494 struct sctp_association *asoc;
4495 struct sctp_sockaddr_entry *addr;
4496 int cnt = 0;
4497
4498 if (len < sizeof(sctp_assoc_t))
4499 return -EINVAL;
4500
4501 if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
4502 return -EFAULT;
4503
4504 printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_NUM_OLD "
4505 "socket option deprecated\n");
4506
4507 /*
4508 * For UDP-style sockets, id specifies the association to query.
4509 * If the id field is set to the value '0' then the locally bound
4510 * addresses are returned without regard to any particular
4511 * association.
4512 */
4513 if (0 == id) {
4514 bp = &sctp_sk(sk)->ep->base.bind_addr;
4515 } else {
4516 asoc = sctp_id2assoc(sk, id);
4517 if (!asoc)
4518 return -EINVAL;
4519 bp = &asoc->base.bind_addr;
4520 }
4521
4522 /* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
4523 * addresses from the global local address list.
4524 */
4525 if (sctp_list_single_entry(&bp->address_list)) {
4526 addr = list_entry(bp->address_list.next,
4527 struct sctp_sockaddr_entry, list);
4528 if (sctp_is_any(sk, &addr->a)) {
4529 rcu_read_lock();
4530 list_for_each_entry_rcu(addr,
4531 &sctp_local_addr_list, list) {
4532 if (!addr->valid)
4533 continue;
4534
4535 if ((PF_INET == sk->sk_family) &&
4536 (AF_INET6 == addr->a.sa.sa_family))
4537 continue;
4538
4539 if ((PF_INET6 == sk->sk_family) &&
4540 inet_v6_ipv6only(sk) &&
4541 (AF_INET == addr->a.sa.sa_family))
4542 continue;
4543
4544 cnt++;
4545 }
4546 rcu_read_unlock();
4547 } else {
4548 cnt = 1;
4549 }
4550 goto done;
4551 }
4552
4553 /* Protection on the bound address list is not needed,
4554 * since in the socket option context we hold the socket lock,
4555 * so there is no way that the bound address list can change.
4556 */
4557 list_for_each_entry(addr, &bp->address_list, list) {
4558 cnt ++;
4559 }
4560done:
4561 return cnt;
4562}
4563
4564/* Helper function that copies local addresses to user and returns the number
4565 * of addresses copied.
4566 */
4567static int sctp_copy_laddrs_old(struct sock *sk, __u16 port,
4568 int max_addrs, void *to,
4569 int *bytes_copied)
4570{
4571 struct sctp_sockaddr_entry *addr;
4572 union sctp_addr temp;
4573 int cnt = 0;
4574 int addrlen;
4575
4576 rcu_read_lock();
4577 list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
4578 if (!addr->valid)
4579 continue;
4580
4581 if ((PF_INET == sk->sk_family) &&
4582 (AF_INET6 == addr->a.sa.sa_family))
4583 continue;
4584 if ((PF_INET6 == sk->sk_family) &&
4585 inet_v6_ipv6only(sk) &&
4586 (AF_INET == addr->a.sa.sa_family))
4587 continue;
4588 memcpy(&temp, &addr->a, sizeof(temp));
4589 if (!temp.v4.sin_port)
4590 temp.v4.sin_port = htons(port);
4591
4592 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
4593 &temp);
4594 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
4595 memcpy(to, &temp, addrlen);
4596
4597 to += addrlen;
4598 *bytes_copied += addrlen;
4599 cnt ++;
4600 if (cnt >= max_addrs) break;
4601 }
4602 rcu_read_unlock();
4603
4604 return cnt;
4605}
4606
4607static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, 4406static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
4608 size_t space_left, int *bytes_copied) 4407 size_t space_left, int *bytes_copied)
4609{ 4408{
@@ -4647,112 +4446,6 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
4647 return cnt; 4446 return cnt;
4648} 4447}
4649 4448
4650/* Old API for getting list of local addresses. Does not work for 32-bit
4651 * programs running on a 64-bit kernel
4652 */
4653static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4654 char __user *optval, int __user *optlen)
4655{
4656 struct sctp_bind_addr *bp;
4657 struct sctp_association *asoc;
4658 int cnt = 0;
4659 struct sctp_getaddrs_old getaddrs;
4660 struct sctp_sockaddr_entry *addr;
4661 void __user *to;
4662 union sctp_addr temp;
4663 struct sctp_sock *sp = sctp_sk(sk);
4664 int addrlen;
4665 int err = 0;
4666 void *addrs;
4667 void *buf;
4668 int bytes_copied = 0;
4669
4670 if (len < sizeof(struct sctp_getaddrs_old))
4671 return -EINVAL;
4672
4673 len = sizeof(struct sctp_getaddrs_old);
4674 if (copy_from_user(&getaddrs, optval, len))
4675 return -EFAULT;
4676
4677 if (getaddrs.addr_num <= 0 ||
4678 getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr)))
4679 return -EINVAL;
4680
4681 printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_OLD "
4682 "socket option deprecated\n");
4683
4684 /*
4685 * For UDP-style sockets, id specifies the association to query.
4686 * If the id field is set to the value '0' then the locally bound
4687 * addresses are returned without regard to any particular
4688 * association.
4689 */
4690 if (0 == getaddrs.assoc_id) {
4691 bp = &sctp_sk(sk)->ep->base.bind_addr;
4692 } else {
4693 asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
4694 if (!asoc)
4695 return -EINVAL;
4696 bp = &asoc->base.bind_addr;
4697 }
4698
4699 to = getaddrs.addrs;
4700
4701 /* Allocate space for a local instance of packed array to hold all
4702 * the data. We store addresses here first and then put write them
4703 * to the user in one shot.
4704 */
4705 addrs = kmalloc(sizeof(union sctp_addr) * getaddrs.addr_num,
4706 GFP_KERNEL);
4707 if (!addrs)
4708 return -ENOMEM;
4709
4710 /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
4711 * addresses from the global local address list.
4712 */
4713 if (sctp_list_single_entry(&bp->address_list)) {
4714 addr = list_entry(bp->address_list.next,
4715 struct sctp_sockaddr_entry, list);
4716 if (sctp_is_any(sk, &addr->a)) {
4717 cnt = sctp_copy_laddrs_old(sk, bp->port,
4718 getaddrs.addr_num,
4719 addrs, &bytes_copied);
4720 goto copy_getaddrs;
4721 }
4722 }
4723
4724 buf = addrs;
4725 /* Protection on the bound address list is not needed since
4726 * in the socket option context we hold a socket lock and
4727 * thus the bound address list can't change.
4728 */
4729 list_for_each_entry(addr, &bp->address_list, list) {
4730 memcpy(&temp, &addr->a, sizeof(temp));
4731 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
4732 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
4733 memcpy(buf, &temp, addrlen);
4734 buf += addrlen;
4735 bytes_copied += addrlen;
4736 cnt ++;
4737 if (cnt >= getaddrs.addr_num) break;
4738 }
4739
4740copy_getaddrs:
4741 /* copy the entire address list into the user provided space */
4742 if (copy_to_user(to, addrs, bytes_copied)) {
4743 err = -EFAULT;
4744 goto error;
4745 }
4746
4747 /* copy the leading structure back to user */
4748 getaddrs.addr_num = cnt;
4749 if (copy_to_user(optval, &getaddrs, len))
4750 err = -EFAULT;
4751
4752error:
4753 kfree(addrs);
4754 return err;
4755}
4756 4449
4757static int sctp_getsockopt_local_addrs(struct sock *sk, int len, 4450static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4758 char __user *optval, int __user *optlen) 4451 char __user *optval, int __user *optlen)
@@ -5603,22 +5296,6 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
5603 case SCTP_INITMSG: 5296 case SCTP_INITMSG:
5604 retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); 5297 retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
5605 break; 5298 break;
5606 case SCTP_GET_PEER_ADDRS_NUM_OLD:
5607 retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval,
5608 optlen);
5609 break;
5610 case SCTP_GET_LOCAL_ADDRS_NUM_OLD:
5611 retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval,
5612 optlen);
5613 break;
5614 case SCTP_GET_PEER_ADDRS_OLD:
5615 retval = sctp_getsockopt_peer_addrs_old(sk, len, optval,
5616 optlen);
5617 break;
5618 case SCTP_GET_LOCAL_ADDRS_OLD:
5619 retval = sctp_getsockopt_local_addrs_old(sk, len, optval,
5620 optlen);
5621 break;
5622 case SCTP_GET_PEER_ADDRS: 5299 case SCTP_GET_PEER_ADDRS:
5623 retval = sctp_getsockopt_peer_addrs(sk, len, optval, 5300 retval = sctp_getsockopt_peer_addrs(sk, len, optval,
5624 optlen); 5301 optlen);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index ab7151da120f..ae03ded2bf1a 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -52,6 +52,7 @@ static int int_max = INT_MAX;
52static int sack_timer_min = 1; 52static int sack_timer_min = 1;
53static int sack_timer_max = 500; 53static int sack_timer_max = 500;
54static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ 54static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
55static int rwnd_scale_max = 16;
55 56
56extern int sysctl_sctp_mem[3]; 57extern int sysctl_sctp_mem[3];
57extern int sysctl_sctp_rmem[3]; 58extern int sysctl_sctp_rmem[3];
@@ -284,6 +285,18 @@ static ctl_table sctp_table[] = {
284 .extra1 = &zero, 285 .extra1 = &zero,
285 .extra2 = &addr_scope_max, 286 .extra2 = &addr_scope_max,
286 }, 287 },
288 {
289 .ctl_name = CTL_UNNUMBERED,
290 .procname = "rwnd_update_shift",
291 .data = &sctp_rwnd_upd_shift,
292 .maxlen = sizeof(int),
293 .mode = 0644,
294 .proc_handler = &proc_dointvec_minmax,
295 .strategy = &sysctl_intvec,
296 .extra1 = &one,
297 .extra2 = &rwnd_scale_max,
298 },
299
287 { .ctl_name = 0 } 300 { .ctl_name = 0 }
288}; 301};
289 302
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 3b141bb32faf..9a6cb22d129f 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -83,7 +83,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
83 peer->fast_recovery = 0; 83 peer->fast_recovery = 0;
84 84
85 peer->last_time_heard = jiffies; 85 peer->last_time_heard = jiffies;
86 peer->last_time_used = jiffies;
87 peer->last_time_ecne_reduced = jiffies; 86 peer->last_time_ecne_reduced = jiffies;
88 87
89 peer->init_sent_count = 0; 88 peer->init_sent_count = 0;
@@ -565,10 +564,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
565 * to be done every RTO interval, we do it every hearbeat 564 * to be done every RTO interval, we do it every hearbeat
566 * interval. 565 * interval.
567 */ 566 */
568 if (time_after(jiffies, transport->last_time_used + 567 transport->cwnd = max(transport->cwnd/2,
569 transport->rto)) 568 4*transport->asoc->pathmtu);
570 transport->cwnd = max(transport->cwnd/2,
571 4*transport->asoc->pathmtu);
572 break; 569 break;
573 } 570 }
574 571
@@ -579,6 +576,43 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
579 transport->cwnd, transport->ssthresh); 576 transport->cwnd, transport->ssthresh);
580} 577}
581 578
579/* Apply Max.Burst limit to the congestion window:
580 * sctpimpguide-05 2.14.2
581 * D) When the time comes for the sender to
582 * transmit new DATA chunks, the protocol parameter Max.Burst MUST
583 * first be applied to limit how many new DATA chunks may be sent.
584 * The limit is applied by adjusting cwnd as follows:
585 * if ((flightsize+ Max.Burst * MTU) < cwnd)
586 * cwnd = flightsize + Max.Burst * MTU
587 */
588
589void sctp_transport_burst_limited(struct sctp_transport *t)
590{
591 struct sctp_association *asoc = t->asoc;
592 u32 old_cwnd = t->cwnd;
593 u32 max_burst_bytes;
594
595 if (t->burst_limited)
596 return;
597
598 max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu);
599 if (max_burst_bytes < old_cwnd) {
600 t->cwnd = max_burst_bytes;
601 t->burst_limited = old_cwnd;
602 }
603}
604
605/* Restore the old cwnd congestion window, after the burst had it's
606 * desired effect.
607 */
608void sctp_transport_burst_reset(struct sctp_transport *t)
609{
610 if (t->burst_limited) {
611 t->cwnd = t->burst_limited;
612 t->burst_limited = 0;
613 }
614}
615
582/* What is the next timeout value for this transport? */ 616/* What is the next timeout value for this transport? */
583unsigned long sctp_transport_timeout(struct sctp_transport *t) 617unsigned long sctp_transport_timeout(struct sctp_transport *t)
584{ 618{
@@ -601,6 +635,7 @@ void sctp_transport_reset(struct sctp_transport *t)
601 * (see Section 6.2.1) 635 * (see Section 6.2.1)
602 */ 636 */
603 t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); 637 t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
638 t->burst_limited = 0;
604 t->ssthresh = asoc->peer.i.a_rwnd; 639 t->ssthresh = asoc->peer.i.a_rwnd;
605 t->last_rto = t->rto = asoc->rto_initial; 640 t->last_rto = t->rto = asoc->rto_initial;
606 t->rtt = 0; 641 t->rtt = 0;