patch-2.1.44 linux/net/rose/rose_timer.c
Next file: linux/net/rose/sysctl_net_rose.c
Previous file: linux/net/rose/rose_subr.c
Back to the patch index
Back to the overall index
- Lines: 234
- Date:
Mon Jul 7 08:20:00 1997
- Orig file:
v2.1.43/linux/net/rose/rose_timer.c
- Orig date:
Thu May 29 21:53:12 1997
diff -u --recursive --new-file v2.1.43/linux/net/rose/rose_timer.c linux/net/rose/rose_timer.c
@@ -1,5 +1,5 @@
/*
- * ROSE release 002
+ * ROSE release 003
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -11,6 +11,8 @@
*
* History
* ROSE 001 Jonathan(G4KLX) Cloned from nr_timer.c
+ * ROSE 003 Jonathan(G4KLX) New timer architecture.
+ * Implemented idle timer.
*/
#include <linux/config.h>
@@ -37,42 +39,103 @@
#include <linux/interrupt.h>
#include <net/rose.h>
-static void rose_timer(unsigned long);
+static void rose_heartbeat_expiry(unsigned long);
+static void rose_timer_expiry(unsigned long);
+static void rose_idletimer_expiry(unsigned long);
-/*
- * Linux set timer
- */
-void rose_set_timer(struct sock *sk)
+void rose_start_heartbeat(struct sock *sk)
{
- unsigned long flags;
-
- save_flags(flags); cli();
del_timer(&sk->timer);
- restore_flags(flags);
sk->timer.data = (unsigned long)sk;
- sk->timer.function = &rose_timer;
- sk->timer.expires = jiffies + (HZ / 10);
+ sk->timer.function = &rose_heartbeat_expiry;
+ sk->timer.expires = jiffies + 5 * HZ;
add_timer(&sk->timer);
}
-/*
- * ROSE Timer
- *
- * This routine is called every 100ms. Decrement timer by this
- * amount - if expired then process the event.
- */
-static void rose_timer(unsigned long param)
+void rose_start_t1timer(struct sock *sk)
+{
+ del_timer(&sk->protinfo.rose->timer);
+
+ sk->protinfo.rose->timer.data = (unsigned long)sk;
+ sk->protinfo.rose->timer.function = &rose_timer_expiry;
+ sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->t1;
+
+ add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_t2timer(struct sock *sk)
+{
+ del_timer(&sk->protinfo.rose->timer);
+
+ sk->protinfo.rose->timer.data = (unsigned long)sk;
+ sk->protinfo.rose->timer.function = &rose_timer_expiry;
+ sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->t2;
+
+ add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_t3timer(struct sock *sk)
+{
+ del_timer(&sk->protinfo.rose->timer);
+
+ sk->protinfo.rose->timer.data = (unsigned long)sk;
+ sk->protinfo.rose->timer.function = &rose_timer_expiry;
+ sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->t3;
+
+ add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_hbtimer(struct sock *sk)
+{
+ del_timer(&sk->protinfo.rose->timer);
+
+ sk->protinfo.rose->timer.data = (unsigned long)sk;
+ sk->protinfo.rose->timer.function = &rose_timer_expiry;
+ sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->hb;
+
+ add_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_start_idletimer(struct sock *sk)
+{
+ del_timer(&sk->protinfo.rose->idletimer);
+
+ if (sk->protinfo.rose->idle > 0) {
+ sk->protinfo.rose->idletimer.data = (unsigned long)sk;
+ sk->protinfo.rose->idletimer.function = &rose_idletimer_expiry;
+ sk->protinfo.rose->idletimer.expires = jiffies + sk->protinfo.rose->idle;
+
+ add_timer(&sk->protinfo.rose->idletimer);
+ }
+}
+
+void rose_stop_heartbeat(struct sock *sk)
+{
+ del_timer(&sk->timer);
+}
+
+void rose_stop_timer(struct sock *sk)
+{
+ del_timer(&sk->protinfo.rose->timer);
+}
+
+void rose_stop_idletimer(struct sock *sk)
+{
+ del_timer(&sk->protinfo.rose->idletimer);
+}
+
+static void rose_heartbeat_expiry(unsigned long param)
{
struct sock *sk = (struct sock *)param;
switch (sk->protinfo.rose->state) {
+
case ROSE_STATE_0:
/* Magic here: If we listen() and a new link dies before it
is accepted() it isn't 'dead' so doesn't get removed. */
if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
- del_timer(&sk->timer);
rose_destroy_socket(sk);
return;
}
@@ -87,57 +150,62 @@
sk->protinfo.rose->condition &= ~ROSE_COND_OWN_RX_BUSY;
sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
sk->protinfo.rose->vl = sk->protinfo.rose->vr;
- sk->protinfo.rose->timer = 0;
rose_write_internal(sk, ROSE_RR);
+ rose_stop_timer(sk); /* HB */
break;
}
- /*
- * Check for frames to transmit.
- */
- rose_kick(sk);
- break;
-
- default:
break;
}
- if (sk->protinfo.rose->timer == 0 || --sk->protinfo.rose->timer > 0) {
- rose_set_timer(sk);
- return;
- }
+ rose_start_heartbeat(sk);
+}
+
+static void rose_timer_expiry(unsigned long param)
+{
+ struct sock *sk = (struct sock *)param;
- /*
- * Timer has expired, it may have been T1, T2, T3 or HB. We can tell
- * by the socket state.
- */
switch (sk->protinfo.rose->state) {
- case ROSE_STATE_3: /* HB */
- if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) {
- sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
- rose_enquiry_response(sk);
- }
- break;
case ROSE_STATE_1: /* T1 */
case ROSE_STATE_4: /* T2 */
rose_write_internal(sk, ROSE_CLEAR_REQUEST);
sk->protinfo.rose->state = ROSE_STATE_2;
- sk->protinfo.rose->timer = sk->protinfo.rose->t3;
+ rose_start_t3timer(sk);
break;
case ROSE_STATE_2: /* T3 */
- rose_clear_queues(sk);
- sk->protinfo.rose->state = ROSE_STATE_0;
- sk->state = TCP_CLOSE;
- sk->err = ETIMEDOUT;
- sk->shutdown |= SEND_SHUTDOWN;
- if (!sk->dead)
- sk->state_change(sk);
- sk->dead = 1;
+ sk->protinfo.rose->neighbour->use--;
+ rose_disconnect(sk, ETIMEDOUT, -1, -1);
+ break;
+
+ case ROSE_STATE_3: /* HB */
+ if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) {
+ sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
+ rose_enquiry_response(sk);
+ }
break;
}
+}
+
+static void rose_idletimer_expiry(unsigned long param)
+{
+ struct sock *sk = (struct sock *)param;
+
+ rose_clear_queues(sk);
+
+ rose_write_internal(sk, ROSE_CLEAR_REQUEST);
+ sk->protinfo.rose->state = ROSE_STATE_2;
+
+ rose_start_t3timer(sk);
+
+ sk->state = TCP_CLOSE;
+ sk->err = 0;
+ sk->shutdown |= SEND_SHUTDOWN;
+
+ if (!sk->dead)
+ sk->state_change(sk);
- rose_set_timer(sk);
+ sk->dead = 1;
}
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov