diff options
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
| -rw-r--r-- | net/sctp/sm_sideeffect.c | 105 |
1 files changed, 85 insertions, 20 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index f65fa441952f..778639db125a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
| 414 | */ | 414 | */ |
| 415 | asoc->overall_error_count++; | 415 | asoc->overall_error_count++; |
| 416 | 416 | ||
| 417 | if (transport->active && | 417 | if (transport->state != SCTP_INACTIVE && |
| 418 | (transport->error_count++ >= transport->max_retrans)) { | 418 | (transport->error_count++ >= transport->max_retrans)) { |
| 419 | SCTP_DEBUG_PRINTK("transport_strike: transport " | 419 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", |
| 420 | "IP:%d.%d.%d.%d failed.\n", | 420 | " transport IP: port:%d failed.\n", |
| 421 | NIPQUAD(transport->ipaddr.v4.sin_addr)); | 421 | asoc, |
| 422 | (&transport->ipaddr), | ||
| 423 | transport->ipaddr.v4.sin_port); | ||
| 422 | sctp_assoc_control_transport(asoc, transport, | 424 | sctp_assoc_control_transport(asoc, transport, |
| 423 | SCTP_TRANSPORT_DOWN, | 425 | SCTP_TRANSPORT_DOWN, |
| 424 | SCTP_FAILED_THRESHOLD); | 426 | SCTP_FAILED_THRESHOLD); |
| @@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
| 593 | /* Mark the destination transport address as active if it is not so | 595 | /* Mark the destination transport address as active if it is not so |
| 594 | * marked. | 596 | * marked. |
| 595 | */ | 597 | */ |
| 596 | if (!t->active) | 598 | if (t->state == SCTP_INACTIVE) |
| 597 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | 599 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, |
| 598 | SCTP_HEARTBEAT_SUCCESS); | 600 | SCTP_HEARTBEAT_SUCCESS); |
| 599 | 601 | ||
| @@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
| 665 | 667 | ||
| 666 | asoc->state = state; | 668 | asoc->state = state; |
| 667 | 669 | ||
| 670 | SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n", | ||
| 671 | asoc, sctp_state_tbl[state]); | ||
| 672 | |||
| 668 | if (sctp_style(sk, TCP)) { | 673 | if (sctp_style(sk, TCP)) { |
| 669 | /* Change the sk->sk_state of a TCP-style socket that has | 674 | /* Change the sk->sk_state of a TCP-style socket that has |
| 670 | * sucessfully completed a connect() call. | 675 | * sucessfully completed a connect() call. |
| 671 | */ | 676 | */ |
| 672 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) | 677 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) |
| @@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
| 678 | sk->sk_shutdown |= RCV_SHUTDOWN; | 683 | sk->sk_shutdown |= RCV_SHUTDOWN; |
| 679 | } | 684 | } |
| 680 | 685 | ||
| 686 | if (sctp_state(asoc, COOKIE_WAIT)) { | ||
| 687 | /* Reset init timeouts since they may have been | ||
| 688 | * increased due to timer expirations. | ||
| 689 | */ | ||
| 690 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
| 691 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]; | ||
| 692 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = | ||
| 693 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]; | ||
| 694 | } | ||
| 695 | |||
| 681 | if (sctp_state(asoc, ESTABLISHED) || | 696 | if (sctp_state(asoc, ESTABLISHED) || |
| 682 | sctp_state(asoc, CLOSED) || | 697 | sctp_state(asoc, CLOSED) || |
| 683 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { | 698 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { |
| @@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1120 | * to be executed only during failed attempts of | 1135 | * to be executed only during failed attempts of |
| 1121 | * association establishment. | 1136 | * association establishment. |
| 1122 | */ | 1137 | */ |
| 1123 | if ((asoc->peer.retran_path != | 1138 | if ((asoc->peer.retran_path != |
| 1124 | asoc->peer.primary_path) && | 1139 | asoc->peer.primary_path) && |
| 1125 | (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) { | 1140 | (asoc->init_err_counter > 0)) { |
| 1126 | sctp_add_cmd_sf(commands, | 1141 | sctp_add_cmd_sf(commands, |
| 1127 | SCTP_CMD_FORCE_PRIM_RETRAN, | 1142 | SCTP_CMD_FORCE_PRIM_RETRAN, |
| 1128 | SCTP_NULL()); | 1143 | SCTP_NULL()); |
| 1129 | } | 1144 | } |
| @@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1237 | sctp_association_put(asoc); | 1252 | sctp_association_put(asoc); |
| 1238 | break; | 1253 | break; |
| 1239 | 1254 | ||
| 1255 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: | ||
| 1256 | chunk = cmd->obj.ptr; | ||
| 1257 | t = sctp_assoc_choose_init_transport(asoc); | ||
| 1258 | asoc->init_last_sent_to = t; | ||
| 1259 | chunk->transport = t; | ||
| 1260 | t->init_sent_count++; | ||
| 1261 | break; | ||
| 1262 | |||
| 1240 | case SCTP_CMD_INIT_RESTART: | 1263 | case SCTP_CMD_INIT_RESTART: |
| 1241 | /* Do the needed accounting and updates | 1264 | /* Do the needed accounting and updates |
| 1242 | * associated with restarting an initialization | 1265 | * associated with restarting an initialization |
| 1243 | * timer. | 1266 | * timer. Only multiply the timeout by two if |
| 1267 | * all transports have been tried at the current | ||
| 1268 | * timeout. | ||
| 1269 | */ | ||
| 1270 | t = asoc->init_last_sent_to; | ||
| 1271 | asoc->init_err_counter++; | ||
| 1272 | |||
| 1273 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
| 1274 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; | ||
| 1275 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > | ||
| 1276 | asoc->max_init_timeo) { | ||
| 1277 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
| 1278 | asoc->max_init_timeo; | ||
| 1279 | } | ||
| 1280 | asoc->init_cycle++; | ||
| 1281 | SCTP_DEBUG_PRINTK( | ||
| 1282 | "T1 INIT Timeout adjustment" | ||
| 1283 | " init_err_counter: %d" | ||
| 1284 | " cycle: %d" | ||
| 1285 | " timeout: %d\n", | ||
| 1286 | asoc->init_err_counter, | ||
| 1287 | asoc->init_cycle, | ||
| 1288 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | ||
| 1292 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
| 1293 | break; | ||
| 1294 | |||
| 1295 | case SCTP_CMD_COOKIEECHO_RESTART: | ||
| 1296 | /* Do the needed accounting and updates | ||
| 1297 | * associated with restarting an initialization | ||
| 1298 | * timer. Only multiply the timeout by two if | ||
| 1299 | * all transports have been tried at the current | ||
| 1300 | * timeout. | ||
| 1244 | */ | 1301 | */ |
| 1245 | asoc->counters[SCTP_COUNTER_INIT_ERROR]++; | 1302 | asoc->init_err_counter++; |
| 1246 | asoc->timeouts[cmd->obj.to] *= 2; | 1303 | |
| 1247 | if (asoc->timeouts[cmd->obj.to] > | 1304 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; |
| 1305 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > | ||
| 1248 | asoc->max_init_timeo) { | 1306 | asoc->max_init_timeo) { |
| 1249 | asoc->timeouts[cmd->obj.to] = | 1307 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = |
| 1250 | asoc->max_init_timeo; | 1308 | asoc->max_init_timeo; |
| 1251 | } | 1309 | } |
| 1310 | SCTP_DEBUG_PRINTK( | ||
| 1311 | "T1 COOKIE Timeout adjustment" | ||
| 1312 | " init_err_counter: %d" | ||
| 1313 | " timeout: %d\n", | ||
| 1314 | asoc->init_err_counter, | ||
| 1315 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); | ||
| 1252 | 1316 | ||
| 1253 | /* If we've sent any data bundled with | 1317 | /* If we've sent any data bundled with |
| 1254 | * COOKIE-ECHO we need to resend. | 1318 | * COOKIE-ECHO we need to resend. |
| @@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1261 | 1325 | ||
| 1262 | sctp_add_cmd_sf(commands, | 1326 | sctp_add_cmd_sf(commands, |
| 1263 | SCTP_CMD_TIMER_RESTART, | 1327 | SCTP_CMD_TIMER_RESTART, |
| 1264 | SCTP_TO(cmd->obj.to)); | 1328 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
| 1265 | break; | 1329 | break; |
| 1266 | 1330 | ||
| 1267 | case SCTP_CMD_INIT_FAILED: | 1331 | case SCTP_CMD_INIT_FAILED: |
| @@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1273 | subtype, chunk, cmd->obj.u32); | 1337 | subtype, chunk, cmd->obj.u32); |
| 1274 | break; | 1338 | break; |
| 1275 | 1339 | ||
| 1276 | case SCTP_CMD_COUNTER_INC: | 1340 | case SCTP_CMD_INIT_COUNTER_INC: |
| 1277 | asoc->counters[cmd->obj.counter]++; | 1341 | asoc->init_err_counter++; |
| 1278 | break; | 1342 | break; |
| 1279 | 1343 | ||
| 1280 | case SCTP_CMD_COUNTER_RESET: | 1344 | case SCTP_CMD_INIT_COUNTER_RESET: |
| 1281 | asoc->counters[cmd->obj.counter] = 0; | 1345 | asoc->init_err_counter = 0; |
| 1346 | asoc->init_cycle = 0; | ||
| 1282 | break; | 1347 | break; |
| 1283 | 1348 | ||
| 1284 | case SCTP_CMD_REPORT_DUP: | 1349 | case SCTP_CMD_REPORT_DUP: |
