/*1* DECnet An implementation of the DECnet protocol suite for the LINUX2* operating system. DECnet is implemented using the BSD Socket3* interface as the means of communication with the user level.4*5* DECnet Socket Timer Functions6*7* Author: Steve Whitehouse <[email protected]>8*9*10* Changes:11* Steve Whitehouse : Made keepalive timer part of the same12* timer idea.13* Steve Whitehouse : Added checks for sk->sock_readers14* David S. Miller : New socket locking15* Steve Whitehouse : Timer grabs socket ref.16*/17#include <linux/net.h>18#include <linux/socket.h>19#include <linux/skbuff.h>20#include <linux/netdevice.h>21#include <linux/timer.h>22#include <linux/spinlock.h>23#include <net/sock.h>24#include <asm/atomic.h>25#include <net/flow.h>26#include <net/dn.h>2728/*29* Slow timer is for everything else (n * 500mS)30*/3132#define SLOW_INTERVAL (HZ/2)3334static void dn_slow_timer(unsigned long arg);3536void dn_start_slow_timer(struct sock *sk)37{38sk->sk_timer.expires = jiffies + SLOW_INTERVAL;39sk->sk_timer.function = dn_slow_timer;40sk->sk_timer.data = (unsigned long)sk;4142add_timer(&sk->sk_timer);43}4445void dn_stop_slow_timer(struct sock *sk)46{47del_timer(&sk->sk_timer);48}4950static void dn_slow_timer(unsigned long arg)51{52struct sock *sk = (struct sock *)arg;53struct dn_scp *scp = DN_SK(sk);5455sock_hold(sk);56bh_lock_sock(sk);5758if (sock_owned_by_user(sk)) {59sk->sk_timer.expires = jiffies + HZ / 10;60add_timer(&sk->sk_timer);61goto out;62}6364/*65* The persist timer is the standard slow timer used for retransmits66* in both connection establishment and disconnection as well as67* in the RUN state. The different states are catered for by changing68* the function pointer in the socket. Setting the timer to a value69* of zero turns it off. We allow the persist_fxn to turn the70* timer off in a permant way by returning non-zero, so that71* timer based routines may remove sockets. This is why we have a72* sock_hold()/sock_put() around the timer to prevent the socket73* going away in the middle.74*/75if (scp->persist && scp->persist_fxn) {76if (scp->persist <= SLOW_INTERVAL) {77scp->persist = 0;7879if (scp->persist_fxn(sk))80goto out;81} else {82scp->persist -= SLOW_INTERVAL;83}84}8586/*87* Check for keepalive timeout. After the other timer 'cos if88* the previous timer caused a retransmit, we don't need to89* do this. scp->stamp is the last time that we sent a packet.90* The keepalive function sends a link service packet to the91* other end. If it remains unacknowledged, the standard92* socket timers will eventually shut the socket down. Each93* time we do this, scp->stamp will be updated, thus94* we won't try and send another until scp->keepalive has passed95* since the last successful transmission.96*/97if (scp->keepalive && scp->keepalive_fxn && (scp->state == DN_RUN)) {98if ((jiffies - scp->stamp) >= scp->keepalive)99scp->keepalive_fxn(sk);100}101102sk->sk_timer.expires = jiffies + SLOW_INTERVAL;103104add_timer(&sk->sk_timer);105out:106bh_unlock_sock(sk);107sock_put(sk);108}109110111