diff options
| author | Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 2002-10-05 13:13:46 -0300 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 2002-10-05 13:13:46 -0300 |
| commit | 2bcff6c19fb53083e0cc0a9d85204bdf268b7b0f (patch) | |
| tree | 8e6e05eadada30e500db92329b38f0c39abe283b | |
| parent | c96542edd5bf18453a433ffb149c3cb8977f8a28 (diff) | |
o LLC: start using seq_file for proc stuff
| -rw-r--r-- | include/net/llc_main.h | 3 | ||||
| -rw-r--r-- | include/net/llc_proc.h | 18 | ||||
| -rw-r--r-- | net/llc/Makefile | 2 | ||||
| -rw-r--r-- | net/llc/af_llc.c | 100 | ||||
| -rw-r--r-- | net/llc/llc_if.c | 2 | ||||
| -rw-r--r-- | net/llc/llc_mac.c | 3 | ||||
| -rw-r--r-- | net/llc/llc_main.c | 12 | ||||
| -rw-r--r-- | net/llc/llc_proc.c | 227 |
8 files changed, 260 insertions, 107 deletions
diff --git a/include/net/llc_main.h b/include/net/llc_main.h index 434e86044dec..0e0d39742a2e 100644 --- a/include/net/llc_main.h +++ b/include/net/llc_main.h @@ -57,10 +57,11 @@ extern struct llc_sap *llc_sap_alloc(void); extern void llc_sap_save(struct llc_sap *sap); extern void llc_free_sap(struct llc_sap *sap); extern struct llc_sap *llc_sap_find(u8 lsap); -extern struct llc_station *llc_station_get(void); extern void llc_station_state_process(struct llc_station *station, struct sk_buff *skb); extern void llc_station_send_pdu(struct llc_station *station, struct sk_buff *skb); extern struct sk_buff *llc_alloc_frame(void); + +extern struct llc_station llc_main_station; #endif /* LLC_MAIN_H */ diff --git a/include/net/llc_proc.h b/include/net/llc_proc.h new file mode 100644 index 000000000000..c6e7306aa8c3 --- /dev/null +++ b/include/net/llc_proc.h @@ -0,0 +1,18 @@ +#ifndef LLC_PROC_H +#define LLC_PROC_H +/* + * Copyright (c) 1997 by Procom Technology, Inc. + * 2002 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ + +extern int llc_proc_init(void); +extern void llc_proc_exit(void); + +#endif /* LLC_PROC_H */ diff --git a/net/llc/Makefile b/net/llc/Makefile index 05ae5f67518d..5c9a53fe6988 100644 --- a/net/llc/Makefile +++ b/net/llc/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_LLC) += llc.o llc-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_mac.o llc_sap.o llc_s_st.o \ llc_main.o llc_s_ac.o llc_conn.o llc_c_st.o llc_stat.o llc_actn.o \ - llc_s_ev.o llc_evnt.o llc_pdu.o + llc_s_ev.o llc_evnt.o llc_pdu.o llc_proc.o llc-$(CONFIG_LLC_UI) += af_llc.o llc-objs := $(llc-y) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 2144915eee5b..0c99a4e6c01f 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -41,6 +41,7 @@ #include <net/llc_conn.h> #include <net/llc_mac.h> #include <net/llc_main.h> +#include <net/llc_proc.h> #include <linux/llc.h> #include <linux/if_arp.h> #include <linux/rtnetlink.h> @@ -1027,94 +1028,6 @@ out: return rc; } -#ifdef CONFIG_PROC_FS -#define MAC_FORMATTED_SIZE 17 -static void llc_ui_format_mac(char *bf, unsigned char *mac) -{ - sprintf(bf, "%02X:%02X:%02X:%02X:%02X:%02X", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); -} - -/** - * llc_ui_get_info - return info to procfs - * @buffer: where to put the formatted output - * @start: starting from - * @offset: offset into buffer. - * @length: size of the buffer - * - * Get the output of the local llc ui socket list to the caller. - * Returns the length of data wrote to buffer. - */ -static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - off_t begin = 0; - struct llc_sap *sap; - struct sock *sk; - struct list_head *sap_entry; - struct llc_station *station = llc_station_get(); - int len = sprintf(buffer, "SKt Mc local_mac_sap " - "remote_mac_sap tx_queue rx_queue st uid " - "link\n"); - - /* Output the LLC socket data for the /proc filesystem */ - read_lock_bh(&station->sap_list.lock); - list_for_each(sap_entry, &station->sap_list.list) { - sap = list_entry(sap_entry, struct llc_sap, node); - - read_lock_bh(&sap->sk_list.lock); - for (sk = sap->sk_list.list; sk; sk = sk->next) { - struct llc_opt *llc = llc_sk(sk); - - len += sprintf(buffer + len, "%2X %2X ", sk->type, - !llc_mac_null(llc->addr.sllc_mmac)); - if (llc->dev && llc_mac_null(llc->addr.sllc_mmac)) - llc_ui_format_mac(buffer + len, - llc->dev->dev_addr); - else { - if (!llc_mac_null(llc->addr.sllc_mmac)) - llc_ui_format_mac(buffer + len, - llc->addr.sllc_mmac); - else - sprintf(buffer + len, - "00:00:00:00:00:00"); - } - len += MAC_FORMATTED_SIZE; - len += sprintf(buffer + len, "@%02X ", sap->laddr.lsap); - llc_ui_format_mac(buffer + len, llc->addr.sllc_dmac); - len += MAC_FORMATTED_SIZE; - len += sprintf(buffer + len, - "@%02X %8d %8d %2d %3d ", - llc->addr.sllc_dsap, - atomic_read(&sk->wmem_alloc), - atomic_read(&sk->rmem_alloc), - sk->state, - sk->socket ? - SOCK_INODE(sk->socket)->i_uid : -1); - len += sprintf(buffer + len, "%4d\n", llc->link); - /* Are we still dumping unwanted data then discard the record */ - pos = begin + len; - - if (pos < offset) { - len = 0; /* Keep dumping into the buffer start */ - begin = pos; - } - if (pos > offset + length) /* We have dumped enough */ - break; - } - read_unlock_bh(&sap->sk_list.lock); - } - read_unlock_bh(&station->sap_list.lock); - - /* The data in question runs from begin to begin + len */ - *start = buffer + offset - begin; /* Start of wanted data */ - len -= offset - begin; /* Remove unwanted header data from length */ - if (len > length) - len = length; /* Remove unwanted tail data from length */ - return len; -} -#endif /* CONFIG_PROC_FS */ - static struct net_proto_family llc_ui_family_ops = { .family = PF_LLC, .create = llc_ui_create, @@ -1145,15 +1058,20 @@ static char llc_ui_banner[] __initdata = int __init llc_ui_init(void) { + int rc = llc_proc_init(); + + if (rc) + goto out; llc_ui_sap_last_autoport = LLC_SAP_DYN_START; sock_register(&llc_ui_family_ops); - proc_net_create("llc", 0, llc_ui_get_info); printk(llc_ui_banner); - return 0; + rc = 0; +out: + return rc; } void __exit llc_ui_exit(void) { - proc_net_remove("llc"); sock_unregister(PF_LLC); + llc_proc_exit(); } diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c index 1f1d241732a6..ffc0771f69e4 100644 --- a/net/llc/llc_if.c +++ b/net/llc/llc_if.c @@ -56,7 +56,7 @@ struct llc_sap *llc_sap_open(u8 lsap, int (*func)(struct sk_buff *skb, /* allocated a SAP; initialize it and clear out its memory pool */ sap->laddr.lsap = lsap; sap->rcv_func = func; - sap->station = llc_station_get(); + sap->station = &llc_main_station; /* initialized SAP; add it to list of SAPs this station manages */ llc_sap_save(sap); out: diff --git a/net/llc/llc_mac.c b/net/llc/llc_mac.c index ae97f73a607b..3f53410df740 100644 --- a/net/llc/llc_mac.c +++ b/net/llc/llc_mac.c @@ -197,12 +197,11 @@ static void fix_up_incoming_skb(struct sk_buff *skb) */ static void llc_station_rcv(struct sk_buff *skb) { - struct llc_station *station = llc_station_get(); struct llc_station_state_ev *ev = llc_station_ev(skb); ev->type = LLC_STATION_EV_TYPE_PDU; ev->reason = 0; - llc_station_state_process(station, skb); + llc_station_state_process(&llc_main_station, skb); } diff --git a/net/llc/llc_main.c b/net/llc/llc_main.c index f7b54e15882d..a8167171dc6b 100644 --- a/net/llc/llc_main.c +++ b/net/llc/llc_main.c @@ -50,7 +50,7 @@ static struct llc_station_state_trans * struct sk_buff *skb); static int llc_rtn_all_conns(struct llc_sap *sap); -static struct llc_station llc_main_station; /* only one of its kind */ +struct llc_station llc_main_station; /* only one of its kind */ #undef LLC_REFCNT_DEBUG #ifdef LLC_REFCNT_DEBUG @@ -340,16 +340,6 @@ static int llc_rtn_all_conns(struct llc_sap *sap) } /** - * llc_station_get - get addr of global station. - * - * Returns address of a place to copy the global station to it. - */ -struct llc_station *llc_station_get(void) -{ - return &llc_main_station; -} - -/** * llc_station_state_process: queue event and try to process queue. * @station: Address of the station * @skb: Address of the event diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c new file mode 100644 index 000000000000..e9f08b48dc68 --- /dev/null +++ b/net/llc/llc_proc.c @@ -0,0 +1,227 @@ +/* + * proc_llc.c - proc interface for LLC + * + * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org> + * 2002 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/socket.h> +#include <linux/sockios.h> +#include <asm/uaccess.h> +#include <asm/ioctls.h> +#include <linux/proc_fs.h> +#include <linux/in.h> +#include <linux/tcp.h> +#include <linux/netdevice.h> +#include <linux/inetdevice.h> +#include <linux/errno.h> +#include <net/sock.h> +#include <net/llc_if.h> +#include <net/llc_sap.h> +#include <net/llc_pdu.h> +#include <net/llc_conn.h> +#include <net/llc_mac.h> +#include <net/llc_main.h> +#include <linux/llc.h> +#include <linux/if_arp.h> +#include <linux/rtnetlink.h> +#include <linux/init.h> +#include <linux/seq_file.h> + +#ifdef CONFIG_PROC_FS +static void llc_ui_format_mac(struct seq_file *seq, unsigned char *mac) +{ + seq_printf(seq, "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +static __inline__ struct sock *llc_get_sk_idx(loff_t pos) +{ + struct list_head *sap_entry; + struct llc_sap *sap; + struct sock *sk = NULL; + + list_for_each(sap_entry, &llc_main_station.sap_list.list) { + sap = list_entry(sap_entry, struct llc_sap, node); + + read_lock_bh(&sap->sk_list.lock); + for (sk = sap->sk_list.list; pos && sk; sk = sk->next) + --pos; + if (!pos) { + if (!sk) + read_unlock_bh(&sap->sk_list.lock); + break; + } + read_unlock_bh(&sap->sk_list.lock); + } + return sk; +} + +static void *llc_seq_start(struct seq_file *seq, loff_t *pos) +{ + loff_t l = *pos; + + read_lock_bh(&llc_main_station.sap_list.lock); + if (!l) + return (void *)1; + return llc_get_sk_idx(--l); +} + +static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct sock* sk; + struct llc_opt *llc; + struct llc_sap *sap; + + ++*pos; + if (v == (void *)1) { + if (list_empty(&llc_main_station.sap_list.list)) { + sk = NULL; + goto out; + } + sap = list_entry(llc_main_station.sap_list.list.next, + struct llc_sap, node); + + read_lock_bh(&sap->sk_list.lock); + sk = sap->sk_list.list; + goto out; + } + sk = v; + if (sk->next) { + sk = sk->next; + goto out; + } + llc = llc_sk(sk); + sap = llc->sap; + read_unlock_bh(&sap->sk_list.lock); + sk = NULL; + for (;;) { + if (sap->node.next == &llc_main_station.sap_list.list) + break; + sap = list_entry(sap->node.next, struct llc_sap, node); + read_lock_bh(&sap->sk_list.lock); + if (sap->sk_list.list) { + sk = sap->sk_list.list; + break; + } + read_unlock_bh(&sap->sk_list.lock); + } +out: + return sk; +} + +static void llc_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock_bh(&llc_main_station.sap_list.lock); +} + +static int llc_seq_show(struct seq_file *seq, void *v) +{ + struct sock* sk; + struct llc_opt *llc; + + if (v == (void *)1) { + seq_puts(seq, "SKt Mc local_mac_sap remote_mac_sap " + " tx_queue rx_queue st uid link\n"); + goto out; + } + sk = v; + llc = llc_sk(sk); + + seq_printf(seq, "%2X %2X ", sk->type, + !llc_mac_null(llc->addr.sllc_mmac)); + + if (llc->dev && llc_mac_null(llc->addr.sllc_mmac)) + llc_ui_format_mac(seq, llc->dev->dev_addr); + else if (!llc_mac_null(llc->addr.sllc_mmac)) + llc_ui_format_mac(seq, llc->addr.sllc_mmac); + else + seq_printf(seq, "00:00:00:00:00:00"); + seq_printf(seq, "@%02X ", llc->sap->laddr.lsap); + llc_ui_format_mac(seq, llc->addr.sllc_dmac); + seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->addr.sllc_dsap, + atomic_read(&sk->wmem_alloc), atomic_read(&sk->rmem_alloc), + sk->state, sk->socket ? SOCK_INODE(sk->socket)->i_uid : -1, + llc->link); +out: + return 0; +} + +struct seq_operations llc_seq_ops = { + .start = llc_seq_start, + .next = llc_seq_next, + .stop = llc_seq_stop, + .show = llc_seq_show, +}; + +static int llc_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &llc_seq_ops); +} + +static int llc_proc_perms(struct inode* inode, int op) +{ + return 0; +} + +static struct file_operations llc_seq_fops = { + .open = llc_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static struct inode_operations llc_seq_inode = { + .permission = llc_proc_perms, +}; + +static struct proc_dir_entry *llc_proc_dir; + +int __init llc_proc_init(void) +{ + int rc = -ENOMEM; + struct proc_dir_entry *p; + + llc_proc_dir = proc_mkdir("llc", proc_net); + if (!llc_proc_dir) + goto out; + + p = create_proc_entry("socket", 0, llc_proc_dir); + if (!p) + goto out_socket; + + p->proc_fops = &llc_seq_fops; + p->proc_iops = &llc_seq_inode; + rc = 0; +out: + return rc; +out_socket: + remove_proc_entry("llc", proc_net); + goto out; +} + +void __exit llc_proc_exit(void) +{ + remove_proc_entry("socket", llc_proc_dir); + remove_proc_entry("llc", proc_net); +} +#else /* CONFIG_PROC_FS */ +int __init llc_proc_init(void) +{ + return 0; +} + +void __exit llc_proc_exit(void) +{ +} +#endif /* CONFIG_PROC_FS */ |
