Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 190764
b: refs/heads/master
c: 50b5d6a
h: refs/heads/master
v: v3
  • Loading branch information
Vlad Yasevich authored and David S. Miller committed May 6, 2010
1 parent b9caaea commit f798b92
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6ec82562ffc6f297d0de36d65776cff8e5704867
refs/heads/master: 50b5d6ad63821cea324a5a7a19854d4de1a0a819
1 change: 1 addition & 0 deletions trunk/include/net/sctp/sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
/* 2nd level prototypes */
void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);
void sctp_generate_proto_unreach_event(unsigned long peer);

void sctp_ootb_pkt_free(struct sctp_packet *);

Expand Down
3 changes: 3 additions & 0 deletions trunk/include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,9 @@ struct sctp_transport {
/* Heartbeat timer is per destination. */
struct timer_list hb_timer;

/* Timer to handle ICMP proto unreachable envets */
struct timer_list proto_unreach_timer;

/* Since we're using per-destination retransmission timers
* (see above), we're also using per-destination "transmitted"
* queues. This probably ought to be a private struct
Expand Down
22 changes: 18 additions & 4 deletions trunk/net/sctp/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,11 +440,25 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
{
SCTP_DEBUG_PRINTK("%s\n", __func__);

sctp_do_sm(SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
asoc->state, asoc->ep, asoc, t,
GFP_ATOMIC);
if (sock_owned_by_user(sk)) {
if (timer_pending(&t->proto_unreach_timer))
return;
else {
if (!mod_timer(&t->proto_unreach_timer,
jiffies + (HZ/20)))
sctp_association_hold(asoc);
}

} else {
if (timer_pending(&t->proto_unreach_timer) &&
del_timer(&t->proto_unreach_timer))
sctp_association_put(asoc);

sctp_do_sm(SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
asoc->state, asoc->ep, asoc, t,
GFP_ATOMIC);
}
}

/* Common lookup code for icmp/icmpv6 error handler. */
Expand Down
35 changes: 35 additions & 0 deletions trunk/net/sctp/sm_sideeffect.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,41 @@ void sctp_generate_heartbeat_event(unsigned long data)
sctp_transport_put(transport);
}

/* Handle the timeout of the ICMP protocol unreachable timer. Trigger
* the correct state machine transition that will close the association.
*/
void sctp_generate_proto_unreach_event(unsigned long data)
{
struct sctp_transport *transport = (struct sctp_transport *) data;
struct sctp_association *asoc = transport->asoc;

sctp_bh_lock_sock(asoc->base.sk);
if (sock_owned_by_user(asoc->base.sk)) {
SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);

/* Try again later. */
if (!mod_timer(&transport->proto_unreach_timer,
jiffies + (HZ/20)))
sctp_association_hold(asoc);
goto out_unlock;
}

/* Is this structure just waiting around for us to actually
* get destroyed?
*/
if (asoc->base.dead)
goto out_unlock;

sctp_do_sm(SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);

out_unlock:
sctp_bh_unlock_sock(asoc->base.sk);
sctp_association_put(asoc);
}


/* Inject a SACK Timeout event into the state machine. */
static void sctp_generate_sack_event(unsigned long data)
{
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/sctp/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
(unsigned long)peer);
setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event,
(unsigned long)peer);
setup_timer(&peer->proto_unreach_timer,
sctp_generate_proto_unreach_event, (unsigned long)peer);

/* Initialize the 64-bit random nonce sent with heartbeat. */
get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
Expand Down

0 comments on commit f798b92

Please sign in to comment.