diff options
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
-rw-r--r-- | net/sctp/sm_sideeffect.c | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index efa516b47e81..eb1f42f45fdd 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/types.h> | 51 | #include <linux/types.h> |
52 | #include <linux/socket.h> | 52 | #include <linux/socket.h> |
53 | #include <linux/ip.h> | 53 | #include <linux/ip.h> |
54 | #include <linux/gfp.h> | ||
54 | #include <net/sock.h> | 55 | #include <net/sock.h> |
55 | #include <net/sctp/sctp.h> | 56 | #include <net/sctp/sctp.h> |
56 | #include <net/sctp/sm.h> | 57 | #include <net/sctp/sm.h> |
@@ -217,8 +218,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
217 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 218 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
218 | SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); | 219 | SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); |
219 | } else { | 220 | } else { |
220 | if (asoc->a_rwnd > asoc->rwnd) | 221 | asoc->a_rwnd = asoc->rwnd; |
221 | asoc->a_rwnd = asoc->rwnd; | ||
222 | sack = sctp_make_sack(asoc); | 222 | sack = sctp_make_sack(asoc); |
223 | if (!sack) | 223 | if (!sack) |
224 | goto nomem; | 224 | goto nomem; |
@@ -397,6 +397,41 @@ out_unlock: | |||
397 | sctp_transport_put(transport); | 397 | sctp_transport_put(transport); |
398 | } | 398 | } |
399 | 399 | ||
400 | /* Handle the timeout of the ICMP protocol unreachable timer. Trigger | ||
401 | * the correct state machine transition that will close the association. | ||
402 | */ | ||
403 | void sctp_generate_proto_unreach_event(unsigned long data) | ||
404 | { | ||
405 | struct sctp_transport *transport = (struct sctp_transport *) data; | ||
406 | struct sctp_association *asoc = transport->asoc; | ||
407 | |||
408 | sctp_bh_lock_sock(asoc->base.sk); | ||
409 | if (sock_owned_by_user(asoc->base.sk)) { | ||
410 | SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); | ||
411 | |||
412 | /* Try again later. */ | ||
413 | if (!mod_timer(&transport->proto_unreach_timer, | ||
414 | jiffies + (HZ/20))) | ||
415 | sctp_association_hold(asoc); | ||
416 | goto out_unlock; | ||
417 | } | ||
418 | |||
419 | /* Is this structure just waiting around for us to actually | ||
420 | * get destroyed? | ||
421 | */ | ||
422 | if (asoc->base.dead) | ||
423 | goto out_unlock; | ||
424 | |||
425 | sctp_do_sm(SCTP_EVENT_T_OTHER, | ||
426 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | ||
427 | asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); | ||
428 | |||
429 | out_unlock: | ||
430 | sctp_bh_unlock_sock(asoc->base.sk); | ||
431 | sctp_association_put(asoc); | ||
432 | } | ||
433 | |||
434 | |||
400 | /* Inject a SACK Timeout event into the state machine. */ | 435 | /* Inject a SACK Timeout event into the state machine. */ |
401 | static void sctp_generate_sack_event(unsigned long data) | 436 | static void sctp_generate_sack_event(unsigned long data) |
402 | { | 437 | { |
@@ -476,7 +511,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
476 | * used to provide an upper bound to this doubling operation. | 511 | * used to provide an upper bound to this doubling operation. |
477 | * | 512 | * |
478 | * Special Case: the first HB doesn't trigger exponential backoff. | 513 | * Special Case: the first HB doesn't trigger exponential backoff. |
479 | * The first unacknowleged HB triggers it. We do this with a flag | 514 | * The first unacknowledged HB triggers it. We do this with a flag |
480 | * that indicates that we have an outstanding HB. | 515 | * that indicates that we have an outstanding HB. |
481 | */ | 516 | */ |
482 | if (!is_hb || transport->hb_sent) { | 517 | if (!is_hb || transport->hb_sent) { |
@@ -718,7 +753,7 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
718 | 753 | ||
719 | if (sctp_style(sk, TCP)) { | 754 | if (sctp_style(sk, TCP)) { |
720 | /* Change the sk->sk_state of a TCP-style socket that has | 755 | /* Change the sk->sk_state of a TCP-style socket that has |
721 | * sucessfully completed a connect() call. | 756 | * successfully completed a connect() call. |
722 | */ | 757 | */ |
723 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) | 758 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) |
724 | sk->sk_state = SCTP_SS_ESTABLISHED; | 759 | sk->sk_state = SCTP_SS_ESTABLISHED; |
@@ -962,6 +997,29 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc, | |||
962 | } | 997 | } |
963 | 998 | ||
964 | 999 | ||
1000 | /* Sent the next ASCONF packet currently stored in the association. | ||
1001 | * This happens after the ASCONF_ACK was succeffully processed. | ||
1002 | */ | ||
1003 | static void sctp_cmd_send_asconf(struct sctp_association *asoc) | ||
1004 | { | ||
1005 | /* Send the next asconf chunk from the addip chunk | ||
1006 | * queue. | ||
1007 | */ | ||
1008 | if (!list_empty(&asoc->addip_chunk_list)) { | ||
1009 | struct list_head *entry = asoc->addip_chunk_list.next; | ||
1010 | struct sctp_chunk *asconf = list_entry(entry, | ||
1011 | struct sctp_chunk, list); | ||
1012 | list_del_init(entry); | ||
1013 | |||
1014 | /* Hold the chunk until an ASCONF_ACK is received. */ | ||
1015 | sctp_chunk_hold(asconf); | ||
1016 | if (sctp_primitive_ASCONF(asoc, asconf)) | ||
1017 | sctp_chunk_free(asconf); | ||
1018 | else | ||
1019 | asoc->addip_last_asconf = asconf; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
965 | 1023 | ||
966 | /* These three macros allow us to pull the debugging code out of the | 1024 | /* These three macros allow us to pull the debugging code out of the |
967 | * main flow of sctp_do_sm() to keep attention focused on the real | 1025 | * main flow of sctp_do_sm() to keep attention focused on the real |
@@ -1417,6 +1475,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1417 | asoc->init_last_sent_to = t; | 1475 | asoc->init_last_sent_to = t; |
1418 | chunk->transport = t; | 1476 | chunk->transport = t; |
1419 | t->init_sent_count++; | 1477 | t->init_sent_count++; |
1478 | /* Set the new transport as primary */ | ||
1479 | sctp_assoc_set_primary(asoc, t); | ||
1420 | break; | 1480 | break; |
1421 | 1481 | ||
1422 | case SCTP_CMD_INIT_RESTART: | 1482 | case SCTP_CMD_INIT_RESTART: |
@@ -1615,6 +1675,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1615 | } | 1675 | } |
1616 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); | 1676 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); |
1617 | break; | 1677 | break; |
1678 | case SCTP_CMD_SEND_NEXT_ASCONF: | ||
1679 | sctp_cmd_send_asconf(asoc); | ||
1680 | break; | ||
1618 | default: | 1681 | default: |
1619 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1682 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1620 | cmd->verb, cmd->obj.ptr); | 1683 | cmd->verb, cmd->obj.ptr); |