diff options
| author | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
| commit | bb799d3b980eb803ca2da4a4eefbd9308f8d988a (patch) | |
| tree | 69fbe0cd6d47b23a50f5e1d87bf7489532fae149 /net/sctp | |
| parent | 919fc6e34831d1c2b58bfb5ae261dc3facc9b269 (diff) | |
| parent | 319e2e3f63c348a9b66db4667efa73178e18b17d (diff) | |
Merge tag 'v3.13-rc4' into core/locking
Merge Linux 3.13-rc4, to refresh this rather old tree with the latest fixes.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/sctp')
| -rw-r--r-- | net/sctp/associola.c | 5 | ||||
| -rw-r--r-- | net/sctp/output.c | 6 | ||||
| -rw-r--r-- | net/sctp/outqueue.c | 6 | ||||
| -rw-r--r-- | net/sctp/sm_statefuns.c | 12 | ||||
| -rw-r--r-- | net/sctp/socket.c | 36 | ||||
| -rw-r--r-- | net/sctp/sysctl.c | 76 | ||||
| -rw-r--r-- | net/sctp/transport.c | 2 |
7 files changed, 110 insertions, 33 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 68a27f9796d2..31ed008c8e13 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -154,8 +154,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 154 | 154 | ||
| 155 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; | 155 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; |
| 156 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; | 156 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; |
| 157 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = | 157 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ; |
| 158 | min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ; | ||
| 159 | 158 | ||
| 160 | /* Initializes the timers */ | 159 | /* Initializes the timers */ |
| 161 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) | 160 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) |
| @@ -291,8 +290,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 291 | asoc->peer.ipv6_address = 1; | 290 | asoc->peer.ipv6_address = 1; |
| 292 | INIT_LIST_HEAD(&asoc->asocs); | 291 | INIT_LIST_HEAD(&asoc->asocs); |
| 293 | 292 | ||
| 294 | asoc->autoclose = sp->autoclose; | ||
| 295 | |||
| 296 | asoc->default_stream = sp->default_stream; | 293 | asoc->default_stream = sp->default_stream; |
| 297 | asoc->default_ppid = sp->default_ppid; | 294 | asoc->default_ppid = sp->default_ppid; |
| 298 | asoc->default_flags = sp->default_flags; | 295 | asoc->default_flags = sp->default_flags; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index e650978daf27..0fb140f8f088 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
| @@ -474,10 +474,11 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
| 474 | * for a given destination transport address. | 474 | * for a given destination transport address. |
| 475 | */ | 475 | */ |
| 476 | 476 | ||
| 477 | if (!tp->rto_pending) { | 477 | if (!chunk->resent && !tp->rto_pending) { |
| 478 | chunk->rtt_in_progress = 1; | 478 | chunk->rtt_in_progress = 1; |
| 479 | tp->rto_pending = 1; | 479 | tp->rto_pending = 1; |
| 480 | } | 480 | } |
| 481 | |||
| 481 | has_data = 1; | 482 | has_data = 1; |
| 482 | } | 483 | } |
| 483 | 484 | ||
| @@ -580,7 +581,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
| 580 | unsigned long timeout; | 581 | unsigned long timeout; |
| 581 | 582 | ||
| 582 | /* Restart the AUTOCLOSE timer when sending data. */ | 583 | /* Restart the AUTOCLOSE timer when sending data. */ |
| 583 | if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) { | 584 | if (sctp_state(asoc, ESTABLISHED) && |
| 585 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { | ||
| 584 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; | 586 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; |
| 585 | timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; | 587 | timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; |
| 586 | 588 | ||
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 94df75877869..f51ba985a36e 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
| @@ -446,6 +446,8 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
| 446 | transport->rto_pending = 0; | 446 | transport->rto_pending = 0; |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | chunk->resent = 1; | ||
| 450 | |||
| 449 | /* Move the chunk to the retransmit queue. The chunks | 451 | /* Move the chunk to the retransmit queue. The chunks |
| 450 | * on the retransmit queue are always kept in order. | 452 | * on the retransmit queue are always kept in order. |
| 451 | */ | 453 | */ |
| @@ -1375,6 +1377,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1375 | * instance). | 1377 | * instance). |
| 1376 | */ | 1378 | */ |
| 1377 | if (!tchunk->tsn_gap_acked && | 1379 | if (!tchunk->tsn_gap_acked && |
| 1380 | !tchunk->resent && | ||
| 1378 | tchunk->rtt_in_progress) { | 1381 | tchunk->rtt_in_progress) { |
| 1379 | tchunk->rtt_in_progress = 0; | 1382 | tchunk->rtt_in_progress = 0; |
| 1380 | rtt = jiffies - tchunk->sent_at; | 1383 | rtt = jiffies - tchunk->sent_at; |
| @@ -1391,7 +1394,8 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1391 | */ | 1394 | */ |
| 1392 | if (!tchunk->tsn_gap_acked) { | 1395 | if (!tchunk->tsn_gap_acked) { |
| 1393 | tchunk->tsn_gap_acked = 1; | 1396 | tchunk->tsn_gap_acked = 1; |
| 1394 | *highest_new_tsn_in_sack = tsn; | 1397 | if (TSN_lt(*highest_new_tsn_in_sack, tsn)) |
| 1398 | *highest_new_tsn_in_sack = tsn; | ||
| 1395 | bytes_acked += sctp_data_size(tchunk); | 1399 | bytes_acked += sctp_data_size(tchunk); |
| 1396 | if (!tchunk->transport) | 1400 | if (!tchunk->transport) |
| 1397 | migrate_bytes += sctp_data_size(tchunk); | 1401 | migrate_bytes += sctp_data_size(tchunk); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index dfe3f36ff2aa..a26065be7289 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -820,7 +820,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, | |||
| 820 | SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); | 820 | SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); |
| 821 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 821 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
| 822 | 822 | ||
| 823 | if (new_asoc->autoclose) | 823 | if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
| 824 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 824 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
| 825 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 825 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
| 826 | 826 | ||
| @@ -908,7 +908,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net, | |||
| 908 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); | 908 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); |
| 909 | SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); | 909 | SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); |
| 910 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 910 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
| 911 | if (asoc->autoclose) | 911 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
| 912 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 912 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
| 913 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 913 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
| 914 | 914 | ||
| @@ -2970,7 +2970,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net, | |||
| 2970 | if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) | 2970 | if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) |
| 2971 | force = SCTP_FORCE(); | 2971 | force = SCTP_FORCE(); |
| 2972 | 2972 | ||
| 2973 | if (asoc->autoclose) { | 2973 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { |
| 2974 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 2974 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
| 2975 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 2975 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
| 2976 | } | 2976 | } |
| @@ -3878,7 +3878,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net, | |||
| 3878 | SCTP_CHUNK(chunk)); | 3878 | SCTP_CHUNK(chunk)); |
| 3879 | 3879 | ||
| 3880 | /* Count this as receiving DATA. */ | 3880 | /* Count this as receiving DATA. */ |
| 3881 | if (asoc->autoclose) { | 3881 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { |
| 3882 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 3882 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
| 3883 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 3883 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
| 3884 | } | 3884 | } |
| @@ -5267,7 +5267,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | |||
| 5267 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 5267 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
| 5268 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 5268 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
| 5269 | 5269 | ||
| 5270 | if (asoc->autoclose) | 5270 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
| 5271 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5271 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
| 5272 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 5272 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
| 5273 | 5273 | ||
| @@ -5346,7 +5346,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack( | |||
| 5346 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 5346 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
| 5347 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); | 5347 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); |
| 5348 | 5348 | ||
| 5349 | if (asoc->autoclose) | 5349 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
| 5350 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5350 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
| 5351 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 5351 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
| 5352 | 5352 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 72046b9729a8..42b709c95cf3 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -2196,6 +2196,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
| 2196 | unsigned int optlen) | 2196 | unsigned int optlen) |
| 2197 | { | 2197 | { |
| 2198 | struct sctp_sock *sp = sctp_sk(sk); | 2198 | struct sctp_sock *sp = sctp_sk(sk); |
| 2199 | struct net *net = sock_net(sk); | ||
| 2199 | 2200 | ||
| 2200 | /* Applicable to UDP-style socket only */ | 2201 | /* Applicable to UDP-style socket only */ |
| 2201 | if (sctp_style(sk, TCP)) | 2202 | if (sctp_style(sk, TCP)) |
| @@ -2205,6 +2206,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
| 2205 | if (copy_from_user(&sp->autoclose, optval, optlen)) | 2206 | if (copy_from_user(&sp->autoclose, optval, optlen)) |
| 2206 | return -EFAULT; | 2207 | return -EFAULT; |
| 2207 | 2208 | ||
| 2209 | if (sp->autoclose > net->sctp.max_autoclose) | ||
| 2210 | sp->autoclose = net->sctp.max_autoclose; | ||
| 2211 | |||
| 2208 | return 0; | 2212 | return 0; |
| 2209 | } | 2213 | } |
| 2210 | 2214 | ||
| @@ -2811,6 +2815,8 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne | |||
| 2811 | { | 2815 | { |
| 2812 | struct sctp_rtoinfo rtoinfo; | 2816 | struct sctp_rtoinfo rtoinfo; |
| 2813 | struct sctp_association *asoc; | 2817 | struct sctp_association *asoc; |
| 2818 | unsigned long rto_min, rto_max; | ||
| 2819 | struct sctp_sock *sp = sctp_sk(sk); | ||
| 2814 | 2820 | ||
| 2815 | if (optlen != sizeof (struct sctp_rtoinfo)) | 2821 | if (optlen != sizeof (struct sctp_rtoinfo)) |
| 2816 | return -EINVAL; | 2822 | return -EINVAL; |
| @@ -2824,26 +2830,36 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne | |||
| 2824 | if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) | 2830 | if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) |
| 2825 | return -EINVAL; | 2831 | return -EINVAL; |
| 2826 | 2832 | ||
| 2833 | rto_max = rtoinfo.srto_max; | ||
| 2834 | rto_min = rtoinfo.srto_min; | ||
| 2835 | |||
| 2836 | if (rto_max) | ||
| 2837 | rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max; | ||
| 2838 | else | ||
| 2839 | rto_max = asoc ? asoc->rto_max : sp->rtoinfo.srto_max; | ||
| 2840 | |||
| 2841 | if (rto_min) | ||
| 2842 | rto_min = asoc ? msecs_to_jiffies(rto_min) : rto_min; | ||
| 2843 | else | ||
| 2844 | rto_min = asoc ? asoc->rto_min : sp->rtoinfo.srto_min; | ||
| 2845 | |||
| 2846 | if (rto_min > rto_max) | ||
| 2847 | return -EINVAL; | ||
| 2848 | |||
| 2827 | if (asoc) { | 2849 | if (asoc) { |
| 2828 | if (rtoinfo.srto_initial != 0) | 2850 | if (rtoinfo.srto_initial != 0) |
| 2829 | asoc->rto_initial = | 2851 | asoc->rto_initial = |
| 2830 | msecs_to_jiffies(rtoinfo.srto_initial); | 2852 | msecs_to_jiffies(rtoinfo.srto_initial); |
| 2831 | if (rtoinfo.srto_max != 0) | 2853 | asoc->rto_max = rto_max; |
| 2832 | asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max); | 2854 | asoc->rto_min = rto_min; |
| 2833 | if (rtoinfo.srto_min != 0) | ||
| 2834 | asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min); | ||
| 2835 | } else { | 2855 | } else { |
| 2836 | /* If there is no association or the association-id = 0 | 2856 | /* If there is no association or the association-id = 0 |
| 2837 | * set the values to the endpoint. | 2857 | * set the values to the endpoint. |
| 2838 | */ | 2858 | */ |
| 2839 | struct sctp_sock *sp = sctp_sk(sk); | ||
| 2840 | |||
| 2841 | if (rtoinfo.srto_initial != 0) | 2859 | if (rtoinfo.srto_initial != 0) |
| 2842 | sp->rtoinfo.srto_initial = rtoinfo.srto_initial; | 2860 | sp->rtoinfo.srto_initial = rtoinfo.srto_initial; |
| 2843 | if (rtoinfo.srto_max != 0) | 2861 | sp->rtoinfo.srto_max = rto_max; |
| 2844 | sp->rtoinfo.srto_max = rtoinfo.srto_max; | 2862 | sp->rtoinfo.srto_min = rto_min; |
| 2845 | if (rtoinfo.srto_min != 0) | ||
| 2846 | sp->rtoinfo.srto_min = rtoinfo.srto_min; | ||
| 2847 | } | 2863 | } |
| 2848 | 2864 | ||
| 2849 | return 0; | 2865 | return 0; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 6b36561a1b3b..b0565afb61c7 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
| @@ -56,11 +56,16 @@ extern long sysctl_sctp_mem[3]; | |||
| 56 | extern int sysctl_sctp_rmem[3]; | 56 | extern int sysctl_sctp_rmem[3]; |
| 57 | extern int sysctl_sctp_wmem[3]; | 57 | extern int sysctl_sctp_wmem[3]; |
| 58 | 58 | ||
| 59 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | 59 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, |
| 60 | int write, | 60 | void __user *buffer, size_t *lenp, |
| 61 | loff_t *ppos); | ||
| 62 | static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | ||
| 63 | void __user *buffer, size_t *lenp, | ||
| 64 | loff_t *ppos); | ||
| 65 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | ||
| 61 | void __user *buffer, size_t *lenp, | 66 | void __user *buffer, size_t *lenp, |
| 62 | |||
| 63 | loff_t *ppos); | 67 | loff_t *ppos); |
| 68 | |||
| 64 | static struct ctl_table sctp_table[] = { | 69 | static struct ctl_table sctp_table[] = { |
| 65 | { | 70 | { |
| 66 | .procname = "sctp_mem", | 71 | .procname = "sctp_mem", |
| @@ -102,17 +107,17 @@ static struct ctl_table sctp_net_table[] = { | |||
| 102 | .data = &init_net.sctp.rto_min, | 107 | .data = &init_net.sctp.rto_min, |
| 103 | .maxlen = sizeof(unsigned int), | 108 | .maxlen = sizeof(unsigned int), |
| 104 | .mode = 0644, | 109 | .mode = 0644, |
| 105 | .proc_handler = proc_dointvec_minmax, | 110 | .proc_handler = proc_sctp_do_rto_min, |
| 106 | .extra1 = &one, | 111 | .extra1 = &one, |
| 107 | .extra2 = &timer_max | 112 | .extra2 = &init_net.sctp.rto_max |
| 108 | }, | 113 | }, |
| 109 | { | 114 | { |
| 110 | .procname = "rto_max", | 115 | .procname = "rto_max", |
| 111 | .data = &init_net.sctp.rto_max, | 116 | .data = &init_net.sctp.rto_max, |
| 112 | .maxlen = sizeof(unsigned int), | 117 | .maxlen = sizeof(unsigned int), |
| 113 | .mode = 0644, | 118 | .mode = 0644, |
| 114 | .proc_handler = proc_dointvec_minmax, | 119 | .proc_handler = proc_sctp_do_rto_max, |
| 115 | .extra1 = &one, | 120 | .extra1 = &init_net.sctp.rto_min, |
| 116 | .extra2 = &timer_max | 121 | .extra2 = &timer_max |
| 117 | }, | 122 | }, |
| 118 | { | 123 | { |
| @@ -294,8 +299,7 @@ static struct ctl_table sctp_net_table[] = { | |||
| 294 | { /* sentinel */ } | 299 | { /* sentinel */ } |
| 295 | }; | 300 | }; |
| 296 | 301 | ||
| 297 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | 302 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, |
| 298 | int write, | ||
| 299 | void __user *buffer, size_t *lenp, | 303 | void __user *buffer, size_t *lenp, |
| 300 | loff_t *ppos) | 304 | loff_t *ppos) |
| 301 | { | 305 | { |
| @@ -342,6 +346,60 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | |||
| 342 | return ret; | 346 | return ret; |
| 343 | } | 347 | } |
| 344 | 348 | ||
| 349 | static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | ||
| 350 | void __user *buffer, size_t *lenp, | ||
| 351 | loff_t *ppos) | ||
| 352 | { | ||
| 353 | struct net *net = current->nsproxy->net_ns; | ||
| 354 | int new_value; | ||
| 355 | struct ctl_table tbl; | ||
| 356 | unsigned int min = *(unsigned int *) ctl->extra1; | ||
| 357 | unsigned int max = *(unsigned int *) ctl->extra2; | ||
| 358 | int ret; | ||
| 359 | |||
| 360 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
| 361 | tbl.maxlen = sizeof(unsigned int); | ||
| 362 | |||
| 363 | if (write) | ||
| 364 | tbl.data = &new_value; | ||
| 365 | else | ||
| 366 | tbl.data = &net->sctp.rto_min; | ||
| 367 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
| 368 | if (write) { | ||
| 369 | if (ret || new_value > max || new_value < min) | ||
| 370 | return -EINVAL; | ||
| 371 | net->sctp.rto_min = new_value; | ||
| 372 | } | ||
| 373 | return ret; | ||
| 374 | } | ||
| 375 | |||
| 376 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | ||
| 377 | void __user *buffer, size_t *lenp, | ||
| 378 | loff_t *ppos) | ||
| 379 | { | ||
| 380 | struct net *net = current->nsproxy->net_ns; | ||
| 381 | int new_value; | ||
| 382 | struct ctl_table tbl; | ||
| 383 | unsigned int min = *(unsigned int *) ctl->extra1; | ||
| 384 | unsigned int max = *(unsigned int *) ctl->extra2; | ||
| 385 | int ret; | ||
| 386 | |||
| 387 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
| 388 | tbl.maxlen = sizeof(unsigned int); | ||
| 389 | |||
| 390 | if (write) | ||
| 391 | tbl.data = &new_value; | ||
| 392 | else | ||
| 393 | tbl.data = &net->sctp.rto_max; | ||
| 394 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
| 395 | if (write) { | ||
| 396 | if (ret || new_value > max || new_value < min) | ||
| 397 | return -EINVAL; | ||
| 398 | net->sctp.rto_max = new_value; | ||
| 399 | } | ||
| 400 | return ret; | ||
| 401 | } | ||
| 402 | |||
| 345 | int sctp_sysctl_net_register(struct net *net) | 403 | int sctp_sysctl_net_register(struct net *net) |
| 346 | { | 404 | { |
| 347 | struct ctl_table *table; | 405 | struct ctl_table *table; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index e332efb124cc..efc46ffed1fd 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -573,7 +573,7 @@ void sctp_transport_burst_limited(struct sctp_transport *t) | |||
| 573 | u32 old_cwnd = t->cwnd; | 573 | u32 old_cwnd = t->cwnd; |
| 574 | u32 max_burst_bytes; | 574 | u32 max_burst_bytes; |
| 575 | 575 | ||
| 576 | if (t->burst_limited) | 576 | if (t->burst_limited || asoc->max_burst == 0) |
| 577 | return; | 577 | return; |
| 578 | 578 | ||
| 579 | max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu); | 579 | max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu); |
