diff options
| author | Stephen Hemminger <shemminger@osdl.org> | 2003-08-30 05:23:54 -0700 |
|---|---|---|
| committer | Stephen Hemminger <shemminger@osdl.org> | 2003-08-30 05:23:54 -0700 |
| commit | 8a60115f2a8ea4e61fee280277404bce03152db8 (patch) | |
| tree | 081986f99628d91da849c7c78d8ae70dbef9efc1 /net | |
| parent | 6d808d57b677859a6ebd6ee8597b8485cdb4169e (diff) | |
[ATALK]: Convert AARP over to seq_file.
The output format is slightly changed:
- address is printed in same format as /proc/net/atalk/interface
- retry and last_sent are only shown for unresolved entries
- times shown in seconds.hundreths rather than raw jiffies
- column headers changed to same format as /proc/net/atalk/interface
Diffstat (limited to 'net')
| -rw-r--r-- | net/appletalk/aarp.c | 239 |
1 files changed, 160 insertions, 79 deletions
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 2e465f65e9b0..473fa99d7be0 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -37,6 +37,7 @@ #include <linux/atalk.h> #include <linux/init.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME; int sysctl_aarp_tick_time = AARP_TICK_TIME; @@ -888,96 +889,176 @@ void aarp_device_down(struct net_device *dev) write_unlock_bh(&aarp_lock); } -/* Called from proc fs */ -static int aarp_get_info(char *buffer, char **start, off_t offset, int length) +#ifdef CONFIG_PROC_FS +struct aarp_iter_state { + int bucket; + struct aarp_entry **table; +}; + +/* + * Get the aarp entry that is in the chain described + * by the iterator. + * If pos is set then skip till that index. + * pos = 1 is the first entry + */ +static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos) { - /* we should dump all our AARP entries */ + int ct = iter->bucket; + struct aarp_entry **table = iter->table; + loff_t off = 0; struct aarp_entry *entry; - int ct, len = sprintf(buffer, - "%-10.10s %-10.10s%-18.18s%12.12s%12.12s " - "xmit_count status\n", - "address", "device", "hw addr", "last_sent", - "expires"); - - read_lock_bh(&aarp_lock); - - for (ct = 0; ct < AARP_HASH_SIZE; ct++) { - for (entry = resolved[ct]; entry; entry = entry->next) { - len += sprintf(buffer + len, "%6u:%-3u ", - (unsigned int)ntohs(entry->target_addr.s_net), - (unsigned int)(entry->target_addr.s_node)); - len += sprintf(buffer + len, "%-10.10s", - entry->dev->name); - len += sprintf(buffer + len, - "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - (int)(entry->hwaddr[0] & 0x000000FF), - (int)(entry->hwaddr[1] & 0x000000FF), - (int)(entry->hwaddr[2] & 0x000000FF), - (int)(entry->hwaddr[3] & 0x000000FF), - (int)(entry->hwaddr[4] & 0x000000FF), - (int)(entry->hwaddr[5] & 0x000000FF)); - len += sprintf(buffer + len, "%12lu ""%12lu ", - (unsigned long)entry->last_sent, - (unsigned long)entry->expires_at); - len += sprintf(buffer + len, "%10u", - (unsigned int)entry->xmit_count); - - len += sprintf(buffer + len, " resolved\n"); + + rescan: + while(ct < AARP_HASH_SIZE) { + for (entry = table[ct]; entry; entry = entry->next) { + if (!pos || ++off == *pos) { + iter->table = table; + iter->bucket = ct; + return entry; + } } + ++ct; } - for (ct = 0; ct < AARP_HASH_SIZE; ct++) { - for (entry = unresolved[ct]; entry; entry = entry->next) { - len += sprintf(buffer + len, "%6u:%-3u ", - (unsigned int)ntohs(entry->target_addr.s_net), - (unsigned int)(entry->target_addr.s_node)); - len += sprintf(buffer + len, "%-10.10s", - entry->dev->name); - len += sprintf(buffer + len, - "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - (int)(entry->hwaddr[0] & 0x000000FF), - (int)(entry->hwaddr[1] & 0x000000FF), - (int)(entry->hwaddr[2] & 0x000000FF), - (int)(entry->hwaddr[3] & 0x000000FF), - (int)(entry->hwaddr[4] & 0x000000FF), - (int)(entry->hwaddr[5] & 0x000000FF)); - len += sprintf(buffer + len, "%12lu ""%12lu ", - (unsigned long)entry->last_sent, - (unsigned long)entry->expires_at); - len += sprintf(buffer + len, "%10u", - (unsigned int)entry->xmit_count); - len += sprintf(buffer + len, " unresolved\n"); - } + if (table == resolved) { + ct = 0; + table = unresolved; + goto rescan; + } + if (table == unresolved) { + ct = 0; + table = proxies; + goto rescan; } + return NULL; +} - for (ct = 0; ct < AARP_HASH_SIZE; ct++) { - for (entry = proxies[ct]; entry; entry = entry->next) { - len += sprintf(buffer + len, "%6u:%-3u ", - (unsigned int)ntohs(entry->target_addr.s_net), - (unsigned int)(entry->target_addr.s_node)); - len += sprintf(buffer + len, "%-10.10s", - entry->dev->name); - len += sprintf(buffer + len, - "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - (int)(entry->hwaddr[0] & 0x000000FF), - (int)(entry->hwaddr[1] & 0x000000FF), - (int)(entry->hwaddr[2] & 0x000000FF), - (int)(entry->hwaddr[3] & 0x000000FF), - (int)(entry->hwaddr[4] & 0x000000FF), - (int)(entry->hwaddr[5] & 0x000000FF)); - len += sprintf(buffer + len, "%12lu ""%12lu ", - (unsigned long)entry->last_sent, - (unsigned long)entry->expires_at); - len += sprintf(buffer + len, "%10u", - (unsigned int)entry->xmit_count); - len += sprintf(buffer + len, " proxy\n"); - } +static void *aarp_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct aarp_iter_state *iter = seq->private; + + read_lock_bh(&aarp_lock); + iter->table = resolved; + iter->bucket = 0; + + return *pos ? iter_next(iter, pos) : ((void *)1); +} + +static void *aarp_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct aarp_entry *entry = v; + struct aarp_iter_state *iter = seq->private; + + ++*pos; + + /* first line after header */ + if (v == ((void *)1)) + entry = iter_next(iter, NULL); + + /* next entry in current bucket */ + else if (entry->next) + entry = entry->next; + + /* next bucket or table */ + else { + ++iter->bucket; + entry = iter_next(iter, NULL); } + return entry; +} +static void aarp_seq_stop(struct seq_file *seq, void *v) +{ read_unlock_bh(&aarp_lock); - return len; } +static const char *dt2str(unsigned long ticks) +{ + static char buf[32]; + + sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100 ) / HZ); + + return buf; +} + +static int aarp_seq_show(struct seq_file *seq, void *v) +{ + struct aarp_iter_state *iter = seq->private; + struct aarp_entry *entry = v; + unsigned long now = jiffies; + + if (v == ((void *)1)) + seq_puts(seq, + "Address Interface Hardware Address" + " Expires LastSend Retry Status\n"); + else { + seq_printf(seq, "%04X:%02X %-12s", + ntohs(entry->target_addr.s_net), + (unsigned int) entry->target_addr.s_node, + entry->dev ? entry->dev->name : "????"); + seq_printf(seq, "%02X:%02X:%02X:%02X:%02X:%02X", + entry->hwaddr[0] & 0xFF, + entry->hwaddr[1] & 0xFF, + entry->hwaddr[2] & 0xFF, + entry->hwaddr[3] & 0xFF, + entry->hwaddr[4] & 0xFF, + entry->hwaddr[5] & 0xFF); + seq_printf(seq, " %8s", + dt2str((long)entry->expires_at - (long)now)); + if (iter->table == unresolved) + seq_printf(seq, " %8s %6hu", + dt2str(now - entry->last_sent), + entry->xmit_count); + else + seq_puts(seq, " "); + seq_printf(seq, " %s\n", + (iter->table == resolved) ? "resolved" + : (iter->table == unresolved) ? "unresolved" + : (iter->table == proxies) ? "proxies" + : "unknown"); + } + return 0; +} + +static struct seq_operations aarp_seq_ops = { + .start = aarp_seq_start, + .next = aarp_seq_next, + .stop = aarp_seq_stop, + .show = aarp_seq_show, +}; + +static int aarp_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + struct aarp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + + if (!s) + goto out; + + rc = seq_open(file, &aarp_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = s; + memset(s, 0, sizeof(*s)); +out: + return rc; +out_kfree: + kfree(s); + goto out; +} + +struct file_operations atalk_seq_arp_fops = { + .owner = THIS_MODULE, + .open = aarp_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; +#endif + /* General module cleanup. Called from cleanup_module() in ddp.c. */ void aarp_cleanup_module(void) { @@ -990,7 +1071,7 @@ void aarp_cleanup_module(void) #ifdef CONFIG_PROC_FS void aarp_register_proc_fs(void) { - proc_net_create("aarp", 0, aarp_get_info); + proc_net_fops_create("aarp", S_IRUGO, &atalk_seq_arp_fops); } void aarp_unregister_proc_fs(void) |
