diff options
author | David S. Miller <davem@davemloft.net> | 2009-11-29 03:16:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-29 03:16:22 -0500 |
commit | 5656b6ca19c602a7074effae360e5a4dcfdc8170 (patch) | |
tree | 13eb8138999a3c6a8e6f92fb98b0cc54b7240c6a /net | |
parent | c1ac403bfa240617da2bce861ea5c3a907a65612 (diff) | |
parent | 4814326b59db0cfd18ac652626d955ad3f57fb0f (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.c | 27 | ||||
-rw-r--r-- | net/sctp/chunk.c | 15 | ||||
-rw-r--r-- | net/sctp/output.c | 50 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 22 | ||||
-rw-r--r-- | net/sctp/protocol.c | 3 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 13 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 5 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 26 | ||||
-rw-r--r-- | net/sctp/socket.c | 335 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 13 | ||||
-rw-r--r-- | net/sctp/transport.c | 45 |
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 @@ | |||
63 | static void sctp_assoc_bh_rcv(struct work_struct *work); | 63 | static void sctp_assoc_bh_rcv(struct work_struct *work); |
64 | static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc); | 64 | static 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 | */ | ||
70 | static 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 | ||
752 | static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet, | 728 | static 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: | |||
1129 | struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, | 1132 | struct 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 | ||
1143 | nodata: | 1148 | nodata: |
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 | ||
2955 | discard_noforce: | 2960 | discard_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; |
2960 | consume: | 2965 | consume: |
@@ -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 | ||
4352 | static 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 | */ | ||
4385 | static 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 | ||
4437 | static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | 4355 | static 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 | ||
4488 | static 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 | } | ||
4560 | done: | ||
4561 | return cnt; | ||
4562 | } | ||
4563 | |||
4564 | /* Helper function that copies local addresses to user and returns the number | ||
4565 | * of addresses copied. | ||
4566 | */ | ||
4567 | static 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 | |||
4607 | static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, | 4406 | static 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 | */ | ||
4653 | static 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 | |||
4740 | copy_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 | |||
4752 | error: | ||
4753 | kfree(addrs); | ||
4754 | return err; | ||
4755 | } | ||
4756 | 4449 | ||
4757 | static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | 4450 | static 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; | |||
52 | static int sack_timer_min = 1; | 52 | static int sack_timer_min = 1; |
53 | static int sack_timer_max = 500; | 53 | static int sack_timer_max = 500; |
54 | static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ | 54 | static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ |
55 | static int rwnd_scale_max = 16; | ||
55 | 56 | ||
56 | extern int sysctl_sctp_mem[3]; | 57 | extern int sysctl_sctp_mem[3]; |
57 | extern int sysctl_sctp_rmem[3]; | 58 | extern 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 | |||
589 | void 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 | */ | ||
608 | void 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? */ |
583 | unsigned long sctp_transport_timeout(struct sctp_transport *t) | 617 | unsigned 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; |