Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * DECnet       An implementation of the DECnet protocol suite for the LINUX
0004  *              operating system.  DECnet is implemented using the  BSD Socket
0005  *              interface as the means of communication with the user level.
0006  *
0007  *              DECnet Socket Timer Functions
0008  *
0009  * Author:      Steve Whitehouse <SteveW@ACM.org>
0010  *
0011  *
0012  * Changes:
0013  *       Steve Whitehouse      : Made keepalive timer part of the same
0014  *                               timer idea.
0015  *       Steve Whitehouse      : Added checks for sk->sock_readers
0016  *       David S. Miller       : New socket locking
0017  *       Steve Whitehouse      : Timer grabs socket ref.
0018  */
0019 #include <linux/net.h>
0020 #include <linux/socket.h>
0021 #include <linux/skbuff.h>
0022 #include <linux/netdevice.h>
0023 #include <linux/timer.h>
0024 #include <linux/spinlock.h>
0025 #include <net/sock.h>
0026 #include <linux/atomic.h>
0027 #include <linux/jiffies.h>
0028 #include <net/flow.h>
0029 #include <net/dn.h>
0030 
0031 /*
0032  * Slow timer is for everything else (n * 500mS)
0033  */
0034 
0035 #define SLOW_INTERVAL (HZ/2)
0036 
0037 static void dn_slow_timer(struct timer_list *t);
0038 
0039 void dn_start_slow_timer(struct sock *sk)
0040 {
0041     timer_setup(&sk->sk_timer, dn_slow_timer, 0);
0042     sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL);
0043 }
0044 
0045 void dn_stop_slow_timer(struct sock *sk)
0046 {
0047     sk_stop_timer(sk, &sk->sk_timer);
0048 }
0049 
0050 static void dn_slow_timer(struct timer_list *t)
0051 {
0052     struct sock *sk = from_timer(sk, t, sk_timer);
0053     struct dn_scp *scp = DN_SK(sk);
0054 
0055     bh_lock_sock(sk);
0056 
0057     if (sock_owned_by_user(sk)) {
0058         sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 10);
0059         goto out;
0060     }
0061 
0062     /*
0063      * The persist timer is the standard slow timer used for retransmits
0064      * in both connection establishment and disconnection as well as
0065      * in the RUN state. The different states are catered for by changing
0066      * the function pointer in the socket. Setting the timer to a value
0067      * of zero turns it off. We allow the persist_fxn to turn the
0068      * timer off in a permant way by returning non-zero, so that
0069      * timer based routines may remove sockets. This is why we have a
0070      * sock_hold()/sock_put() around the timer to prevent the socket
0071      * going away in the middle.
0072      */
0073     if (scp->persist && scp->persist_fxn) {
0074         if (scp->persist <= SLOW_INTERVAL) {
0075             scp->persist = 0;
0076 
0077             if (scp->persist_fxn(sk))
0078                 goto out;
0079         } else {
0080             scp->persist -= SLOW_INTERVAL;
0081         }
0082     }
0083 
0084     /*
0085      * Check for keepalive timeout. After the other timer 'cos if
0086      * the previous timer caused a retransmit, we don't need to
0087      * do this. scp->stamp is the last time that we sent a packet.
0088      * The keepalive function sends a link service packet to the
0089      * other end. If it remains unacknowledged, the standard
0090      * socket timers will eventually shut the socket down. Each
0091      * time we do this, scp->stamp will be updated, thus
0092      * we won't try and send another until scp->keepalive has passed
0093      * since the last successful transmission.
0094      */
0095     if (scp->keepalive && scp->keepalive_fxn && (scp->state == DN_RUN)) {
0096         if (time_after_eq(jiffies, scp->stamp + scp->keepalive))
0097             scp->keepalive_fxn(sk);
0098     }
0099 
0100     sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL);
0101 out:
0102     bh_unlock_sock(sk);
0103     sock_put(sk);
0104 }