[LLC]: Add sysctl support for the LLC timeouts
Arnaldo Carvalho de Melo [Thu, 22 Sep 2005 07:30:44 +0000 (04:30 -0300)]
Signed-off-by: Jochen Friedrich <jochen@scram.de>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>

include/linux/sysctl.h
include/net/llc.h
include/net/llc_conn.h
net/llc/Makefile
net/llc/af_llc.c
net/llc/llc_c_ac.c
net/llc/llc_conn.c
net/llc/llc_station.c
net/llc/sysctl_net_llc.c [new file with mode: 0644]

index 3a29a9f..fc8e367 100644 (file)
@@ -202,7 +202,8 @@ enum
        NET_TR=14,
        NET_DECNET=15,
        NET_ECONET=16,
-       NET_SCTP=17, 
+       NET_SCTP=17,
+       NET_LLC=18,
 };
 
 /* /proc/sys/kernel/random */
@@ -522,6 +523,29 @@ enum {
        NET_IPX_FORWARDING=2
 };
 
+/* /proc/sys/net/llc */
+enum {
+       NET_LLC2=1,
+       NET_LLC_STATION=2,
+};
+
+/* /proc/sys/net/llc/llc2 */
+enum {
+       NET_LLC2_TIMEOUT=1,
+};
+
+/* /proc/sys/net/llc/station */
+enum {
+       NET_LLC_STATION_ACK_TIMEOUT=1,
+};
+
+/* /proc/sys/net/llc/llc2/timeout */
+enum {
+       NET_LLC2_ACK_TIMEOUT=1,
+       NET_LLC2_P_TIMEOUT=2,
+       NET_LLC2_REJ_TIMEOUT=3,
+       NET_LLC2_BUSY_TIMEOUT=4,
+};
 
 /* /proc/sys/net/appletalk */
 enum {
index 71769a5..8b8e2be 100644 (file)
@@ -98,4 +98,11 @@ extern void llc_proc_exit(void);
 #define llc_proc_init()        (0)
 #define llc_proc_exit()        do { } while(0)
 #endif /* CONFIG_PROC_FS */
+#ifdef CONFIG_SYSCTL
+extern int llc_sysctl_init(void);
+extern void llc_sysctl_exit(void);
+#else
+#define llc_sysctl_init() (0)
+#define llc_sysctl_exit() do { } while(0)
+#endif /* CONFIG_SYSCTL */
 #endif /* LLC_H */
index 8ad3bc2..8a8ff48 100644 (file)
 #define LLC_EVENT                1
 #define LLC_PACKET               2
 
-#define LLC_P_TIME               2
-#define LLC_ACK_TIME             1
-#define LLC_REJ_TIME             3
-#define LLC_BUSY_TIME            3
+#define LLC2_P_TIME               2
+#define LLC2_ACK_TIME             1
+#define LLC2_REJ_TIME             3
+#define LLC2_BUSY_TIME            3
 
 struct llc_timer {
        struct timer_list timer;
-       u16               expire;       /* timer expire time */
+       unsigned long     expire;       /* timer expire time */
 };
 
 struct llc_sock {
index 5ebd4ed..4e260cf 100644 (file)
@@ -22,3 +22,4 @@ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
          llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o
 
 llc2-$(CONFIG_PROC_FS) += llc_proc.o
+llc2-$(CONFIG_SYSCTL)  += sysctl_net_llc.o
index 95444f2..ef12534 100644 (file)
@@ -877,22 +877,22 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
        case LLC_OPT_ACK_TMR_EXP:
                if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
                        goto out;
-               llc->ack_timer.expire = opt;
+               llc->ack_timer.expire = opt * HZ;
                break;
        case LLC_OPT_P_TMR_EXP:
                if (opt > LLC_OPT_MAX_P_TMR_EXP)
                        goto out;
-               llc->pf_cycle_timer.expire = opt;
+               llc->pf_cycle_timer.expire = opt * HZ;
                break;
        case LLC_OPT_REJ_TMR_EXP:
                if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
                        goto out;
-               llc->rej_sent_timer.expire = opt;
+               llc->rej_sent_timer.expire = opt * HZ;
                break;
        case LLC_OPT_BUSY_TMR_EXP:
                if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
                        goto out;
-               llc->busy_state_timer.expire = opt;
+               llc->busy_state_timer.expire = opt * HZ;
                break;
        case LLC_OPT_TX_WIN:
                if (opt > LLC_OPT_MAX_WIN)
@@ -942,17 +942,17 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
                goto out;
        switch (optname) {
        case LLC_OPT_RETRY:
-               val = llc->n2;                          break;
+               val = llc->n2;                                  break;
        case LLC_OPT_SIZE:
-               val = llc->n1;                          break;
+               val = llc->n1;                                  break;
        case LLC_OPT_ACK_TMR_EXP:
-               val = llc->ack_timer.expire;            break;
+               val = llc->ack_timer.expire / HZ;               break;
        case LLC_OPT_P_TMR_EXP:
-               val = llc->pf_cycle_timer.expire;       break;
+               val = llc->pf_cycle_timer.expire / HZ;          break;
        case LLC_OPT_REJ_TMR_EXP:
-               val = llc->rej_sent_timer.expire;       break;
+               val = llc->rej_sent_timer.expire / HZ;          break;
        case LLC_OPT_BUSY_TMR_EXP:
-               val = llc->busy_state_timer.expire;     break;
+               val = llc->busy_state_timer.expire / HZ;        break;
        case LLC_OPT_TX_WIN:
                val = llc->k;                           break;
        case LLC_OPT_RX_WIN:
@@ -999,6 +999,13 @@ static struct proto_ops llc_ui_ops = {
 extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
 extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
 
+static char llc_proc_err_msg[] __initdata =
+        KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
+static char llc_sysctl_err_msg[] __initdata =
+        KERN_CRIT "LLC: Unable to register the sysctl entries\n";
+static char llc_sock_err_msg[] __initdata =
+        KERN_CRIT "LLC: Unable to register the network family\n";
+
 static int __init llc2_init(void)
 {
        int rc = proto_register(&llc_proto, 0);
@@ -1010,13 +1017,28 @@ static int __init llc2_init(void)
        llc_station_init();
        llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
        rc = llc_proc_init();
-       if (rc != 0)
+       if (rc != 0) {
+               printk(llc_proc_err_msg);
                goto out_unregister_llc_proto;
-       sock_register(&llc_ui_family_ops);
+       }
+       rc = llc_sysctl_init();
+       if (rc) {
+               printk(llc_sysctl_err_msg);
+               goto out_proc;
+       }
+       rc = sock_register(&llc_ui_family_ops);
+       if (rc) {
+               printk(llc_sock_err_msg);
+               goto out_sysctl;
+       }
        llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
        llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
 out:
        return rc;
+out_sysctl:
+       llc_sysctl_exit();
+out_proc:
+       llc_proc_exit();
 out_unregister_llc_proto:
        proto_unregister(&llc_proto);
        goto out;
@@ -1029,6 +1051,7 @@ static void __exit llc2_exit(void)
        llc_remove_pack(LLC_DEST_CONN);
        sock_unregister(PF_LLC);
        llc_proc_exit();
+       llc_sysctl_exit();
        proto_unregister(&llc_proto);
 }
 
index 50c827e..a4daa91 100644 (file)
@@ -620,7 +620,7 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
        if (!llc->remote_busy_flag) {
                llc->remote_busy_flag = 1;
                mod_timer(&llc->busy_state_timer.timer,
-                        jiffies + llc->busy_state_timer.expire * HZ);
+                        jiffies + llc->busy_state_timer.expire);
        }
        return 0;
 }
@@ -853,7 +853,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
 
        llc_conn_set_p_flag(sk, 1);
        mod_timer(&llc->pf_cycle_timer.timer,
-                 jiffies + llc->pf_cycle_timer.expire * HZ);
+                 jiffies + llc->pf_cycle_timer.expire);
        return 0;
 }
 
@@ -1131,7 +1131,7 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
 {
        struct llc_sock *llc = llc_sk(sk);
 
-       mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ);
+       mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire);
        return 0;
 }
 
@@ -1140,7 +1140,7 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
        struct llc_sock *llc = llc_sk(sk);
 
        mod_timer(&llc->rej_sent_timer.timer,
-                 jiffies + llc->rej_sent_timer.expire * HZ);
+                 jiffies + llc->rej_sent_timer.expire);
        return 0;
 }
 
@@ -1151,7 +1151,7 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
 
        if (!timer_pending(&llc->ack_timer.timer))
                mod_timer(&llc->ack_timer.timer,
-                         jiffies + llc->ack_timer.expire * HZ);
+                         jiffies + llc->ack_timer.expire);
        return 0;
 }
 
@@ -1199,7 +1199,7 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
                }
                if (unacked)
                        mod_timer(&llc->ack_timer.timer,
-                                 jiffies + llc->ack_timer.expire * HZ);
+                                 jiffies + llc->ack_timer.expire);
        } else if (llc->failed_data_req) {
                u8 f_bit;
 
index ce7b893..d3783f8 100644 (file)
@@ -40,6 +40,11 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
 /* Offset table on connection states transition diagram */
 static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
 
+int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ;
+int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ;
+int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ;
+int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ;
+
 /**
  *     llc_conn_state_process - sends event to connection state machine
  *     @sk: connection
@@ -799,22 +804,22 @@ static void llc_sk_init(struct sock* sk)
        llc->dec_step = llc->connect_step = 1;
 
        init_timer(&llc->ack_timer.timer);
-       llc->ack_timer.expire         = LLC_ACK_TIME;
+       llc->ack_timer.expire         = sysctl_llc2_ack_timeout;
        llc->ack_timer.timer.data     = (unsigned long)sk;
        llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
 
        init_timer(&llc->pf_cycle_timer.timer);
-       llc->pf_cycle_timer.expire         = LLC_P_TIME;
+       llc->pf_cycle_timer.expire         = sysctl_llc2_p_timeout;
        llc->pf_cycle_timer.timer.data     = (unsigned long)sk;
        llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
 
        init_timer(&llc->rej_sent_timer.timer);
-       llc->rej_sent_timer.expire         = LLC_REJ_TIME;
+       llc->rej_sent_timer.expire         = sysctl_llc2_rej_timeout;
        llc->rej_sent_timer.timer.data     = (unsigned long)sk;
        llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
 
        init_timer(&llc->busy_state_timer.timer);
-       llc->busy_state_timer.expire         = LLC_BUSY_TIME;
+       llc->busy_state_timer.expire         = sysctl_llc2_busy_timeout;
        llc->busy_state_timer.timer.data     = (unsigned long)sk;
        llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
 
index 85a7ac2..2d764b0 100644 (file)
@@ -50,6 +50,10 @@ struct llc_station {
        struct sk_buff_head         mac_pdu_q;
 };
 
+#define LLC_STATION_ACK_TIME (3 * HZ)
+
+int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME;
+
 /* Types of events (possible values in 'ev->type') */
 #define LLC_STATION_EV_TYPE_SIMPLE     1
 #define LLC_STATION_EV_TYPE_CONDITION  2
@@ -218,7 +222,8 @@ static void llc_station_send_pdu(struct sk_buff *skb)
 
 static int llc_station_ac_start_ack_timer(struct sk_buff *skb)
 {
-       mod_timer(&llc_main_station.ack_timer, jiffies + LLC_ACK_TIME * HZ);
+       mod_timer(&llc_main_station.ack_timer,
+                 jiffies + sysctl_llc_station_ack_timeout);
        return 0;
 }
 
@@ -687,7 +692,8 @@ int __init llc_station_init(void)
        init_timer(&llc_main_station.ack_timer);
        llc_main_station.ack_timer.data     = (unsigned long)&llc_main_station;
        llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;
-
+       llc_main_station.ack_timer.expires  = jiffies +
+                                               sysctl_llc_station_ack_timeout;
        skb = alloc_skb(0, GFP_ATOMIC);
        if (!skb)
                goto out;
@@ -695,7 +701,6 @@ int __init llc_station_init(void)
        llc_set_station_handler(llc_station_rcv);
        ev = llc_station_ev(skb);
        memset(ev, 0, sizeof(*ev));
-       llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
        llc_main_station.maximum_retry  = 1;
        llc_main_station.state          = LLC_STATION_STATE_DOWN;
        ev->type        = LLC_STATION_EV_TYPE_SIMPLE;
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c
new file mode 100644 (file)
index 0000000..4d99d2f
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * sysctl_net_llc.c: sysctl interface to LLC net subsystem.
+ * 
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+
+#ifndef CONFIG_SYSCTL
+#error This file should not be compiled without CONFIG_SYSCTL defined
+#endif
+
+extern int sysctl_llc2_ack_timeout;
+extern int sysctl_llc2_busy_timeout;
+extern int sysctl_llc2_p_timeout;
+extern int sysctl_llc2_rej_timeout;
+extern int sysctl_llc_station_ack_timeout;
+
+static struct ctl_table llc2_timeout_table[] = {
+       {
+               .ctl_name       = NET_LLC2_ACK_TIMEOUT,
+               .procname       = "ack",
+               .data           = &sysctl_llc2_ack_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       {
+               .ctl_name       = NET_LLC2_BUSY_TIMEOUT,
+               .procname       = "busy",
+               .data           = &sysctl_llc2_busy_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       {
+               .ctl_name       = NET_LLC2_P_TIMEOUT,
+               .procname       = "p",
+               .data           = &sysctl_llc2_p_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       {
+               .ctl_name       = NET_LLC2_REJ_TIMEOUT,
+               .procname       = "rej",
+               .data           = &sysctl_llc2_rej_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       { 0 },
+};
+
+static struct ctl_table llc_station_table[] = {
+       {
+               .ctl_name       = NET_LLC_STATION_ACK_TIMEOUT,
+               .procname       = "ack_timeout",
+               .data           = &sysctl_llc_station_ack_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       { 0 },
+};
+
+static struct ctl_table llc2_dir_timeout_table[] = {
+       {
+               .ctl_name       = NET_LLC2,
+               .procname       = "timeout",
+               .mode           = 0555,
+               .child          = llc2_timeout_table,
+               },
+       { 0 },
+};
+
+static struct ctl_table llc_table[] = {
+       {
+               .ctl_name       = NET_LLC2,
+               .procname       = "llc2",
+               .mode           = 0555,
+               .child          = llc2_dir_timeout_table,
+               },
+       {
+               .ctl_name       = NET_LLC_STATION,
+               .procname       = "station",
+               .mode           = 0555,
+               .child          = llc_station_table,
+       },
+       { 0 },
+};
+
+static struct ctl_table llc_dir_table[] = {
+       {
+               .ctl_name       = NET_LLC,
+               .procname       = "llc",
+               .mode           = 0555,
+               .child          = llc_table,
+               },
+       { 0 },
+};
+
+static struct ctl_table llc_root_table[] = {
+       {
+               .ctl_name       = CTL_NET,
+               .procname       = "net",
+               .mode           = 0555,
+               .child          = llc_dir_table,
+       },
+       { 0 },
+};
+
+static struct ctl_table_header *llc_table_header;
+
+int __init llc_sysctl_init(void)
+{
+       llc_table_header = register_sysctl_table(llc_root_table, 1);
+
+       return llc_table_header ? 0 : -ENOMEM;
+}
+
+void llc_sysctl_exit(void)
+{
+       if (llc_table_header) {
+               unregister_sysctl_table(llc_table_header);
+               llc_table_header = NULL;
+       }
+}