Hi,
we had decided that different files must move from sysfs to debugfs in recent discussion with gregkh. But their was also the problem that we currently use /dev/batman-adv to send special batman-adv "icmp" packets to the mesh. This file is maybe a problem when we want to support different batX interfaces on a single machine.
So we have the problem that we want to move different files to debugfs and get support for it in batctl. It seemed to be easier (better readable) for me to first start to get a single file to debugfs and then build on top of the created infrastructure in batctl/batman-adv-kernelland to move more files. My choice was /dev/batman-adv as we had some open question how good it works with debugfs.
Unfortunately I am not able to continue it today, but don't want to stop other people working on similar things. I will attach v0 (aka works for me, but maybe not perfect/good enough) versions of these patches to support them. Please feel free to discuss the patches.
Best regards, Sven
batctl uses /dev/batman-adv to send special batman-adv icmp packets to other nodes in the mesh. To get it working with multiple batX devices we must ensure that every mesh device can have their own socket which is used to inject those packets in exactly one mesh.
The current implementation still doesn't allow to use complete separated meshes as we rely on structures which are not part of the private data of a batman device.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- batman-adv-kernelland/Makefile.kbuild | 2 +- batman-adv-kernelland/bat_debugfs.c | 76 +++++++ batman-adv-kernelland/bat_debugfs.h | 33 +++ batman-adv-kernelland/device.c | 363 --------------------------------- batman-adv-kernelland/device.h | 38 ---- batman-adv-kernelland/icmp_socket.c | 337 ++++++++++++++++++++++++++++++ batman-adv-kernelland/icmp_socket.h | 29 +++ batman-adv-kernelland/main.c | 21 ++- batman-adv-kernelland/routing.c | 4 +- batman-adv-kernelland/types.h | 5 +- 10 files changed, 495 insertions(+), 413 deletions(-) create mode 100644 batman-adv-kernelland/bat_debugfs.c create mode 100644 batman-adv-kernelland/bat_debugfs.h delete mode 100644 batman-adv-kernelland/device.c delete mode 100644 batman-adv-kernelland/device.h create mode 100644 batman-adv-kernelland/icmp_socket.c create mode 100644 batman-adv-kernelland/icmp_socket.h
diff --git a/batman-adv-kernelland/Makefile.kbuild b/batman-adv-kernelland/Makefile.kbuild index e9b58b9..d42f6a3 100644 --- a/batman-adv-kernelland/Makefile.kbuild +++ b/batman-adv-kernelland/Makefile.kbuild @@ -32,4 +32,4 @@ EXTRA_CFLAGS += -DREVISION_VERSION="r$(REVISION)" endif
obj-m += batman-adv.o -batman-adv-objs := main.o bat_sysfs.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o gateway_common.o gateway_client.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) +batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o gateway_common.o gateway_client.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) diff --git a/batman-adv-kernelland/bat_debugfs.c b/batman-adv-kernelland/bat_debugfs.c new file mode 100644 index 0000000..19e7bee --- /dev/null +++ b/batman-adv-kernelland/bat_debugfs.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include <linux/debugfs.h> + +#include "main.h" +#include "bat_debugfs.h" +#include "translation-table.h" +#include "originator.h" +#include "hard-interface.h" +#include "gateway_common.h" +#include "gateway_client.h" +#include "vis.h" +#include "icmp_socket.h" +#include "compat.h" + +static struct dentry *bat_debugfs; + +void debugfs_init(void) +{ + bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); +} + +void debugfs_destroy(void) +{ + if (bat_debugfs) { + debugfs_remove_recursive(bat_debugfs); + bat_debugfs = NULL; + } +} + +int debugfs_add_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (!bat_debugfs) + goto out; + + bat_priv->debug_dir = debugfs_create_dir(dev->name, bat_debugfs); + if (!bat_priv->debug_dir) + goto out; + + bat_socket_setup(bat_priv); + + return 0; +out: + return -ENOMEM; +} + +void debugfs_del_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (bat_debugfs) { + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; + } +} diff --git a/batman-adv-kernelland/bat_debugfs.h b/batman-adv-kernelland/bat_debugfs.h new file mode 100644 index 0000000..5cdd332 --- /dev/null +++ b/batman-adv-kernelland/bat_debugfs.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#ifndef BAT_DEBUGFS_H +#define BAT_DEBUGFS_H + +#define DEBUGFS_BAT_SUBDIR "batman_adv" + +void debugfs_init(void); +void debugfs_destroy(void); +int debugfs_add_meshif(struct net_device *dev); +void debugfs_del_meshif(struct net_device *dev); + +#endif diff --git a/batman-adv-kernelland/device.c b/batman-adv-kernelland/device.c deleted file mode 100644 index 8a99ea9..0000000 --- a/batman-adv-kernelland/device.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include <linux/device.h> -#include "main.h" -#include "device.h" -#include "send.h" -#include "types.h" -#include "hash.h" -#include "hard-interface.h" - -#include "compat.h" - -static struct class *batman_class; - -static int Major; /* Major number assigned to our device driver */ - -static const struct file_operations fops = { - .open = bat_device_open, - .release = bat_device_release, - .read = bat_device_read, - .write = bat_device_write, - .poll = bat_device_poll, -}; - -static struct device_client *device_client_hash[256]; - -void bat_device_init(void) -{ - memset(device_client_hash, 0, sizeof(device_client_hash)); -} - -int bat_device_setup(void) -{ - int tmp_major; - - if (Major) - return 1; - - /* register our device - kernel assigns a free major number */ - tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops); - if (tmp_major < 0) { - printk(KERN_ERR "batman-adv:" - "Registering the character device failed with %d\n", - tmp_major); - return 0; - } - - batman_class = class_create(THIS_MODULE, "batman-adv"); - - if (IS_ERR(batman_class)) { - printk(KERN_ERR "batman-adv:" - "Could not register class 'batman-adv'\n"); - return 0; - } - - device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL, - "batman-adv"); - - Major = tmp_major; - return 1; -} - -void bat_device_destroy(void) -{ - if (!Major) - return; - - device_destroy(batman_class, MKDEV(Major, 0)); - class_destroy(batman_class); - - /* Unregister the device */ - unregister_chrdev(Major, DRIVER_DEVICE); - - Major = 0; -} - -int bat_device_open(struct inode *inode, struct file *file) -{ - unsigned int i; - struct device_client *device_client; - - device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL); - - if (!device_client) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) { - if (!device_client_hash[i]) { - device_client_hash[i] = device_client; - break; - } - } - - if (i == ARRAY_SIZE(device_client_hash)) { - printk(KERN_ERR "batman-adv:" - "Error - can't add another packet client: " - "maximum number of clients reached\n"); - kfree(device_client); - return -EXFULL; - } - - INIT_LIST_HEAD(&device_client->queue_list); - device_client->queue_len = 0; - device_client->index = i; - spin_lock_init(&device_client->lock); - init_waitqueue_head(&device_client->queue_wait); - - file->private_data = device_client; - - inc_module_count(); - return 0; -} - -int bat_device_release(struct inode *inode, struct file *file) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - struct list_head *list_pos, *list_pos_tmp; - unsigned long flags; - - spin_lock_irqsave(&device_client->lock, flags); - - /* for all packets in the queue ... */ - list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) { - device_packet = list_entry(list_pos, - struct device_packet, list); - - list_del(list_pos); - kfree(device_packet); - } - - device_client_hash[device_client->index] = NULL; - spin_unlock_irqrestore(&device_client->lock, flags); - - kfree(device_client); - dec_module_count(); - - return 0; -} - -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - size_t packet_len; - int error; - unsigned long flags; - - if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0)) - return -EAGAIN; - - if ((!buf) || (count < sizeof(struct icmp_packet))) - return -EINVAL; - - if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; - - error = wait_event_interruptible(device_client->queue_wait, - device_client->queue_len); - - if (error) - return error; - - spin_lock_irqsave(&device_client->lock, flags); - - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - list_del(&device_packet->list); - device_client->queue_len--; - - spin_unlock_irqrestore(&device_client->lock, flags); - - error = __copy_to_user(buf, &device_packet->icmp_packet, - device_packet->icmp_len); - - packet_len = device_packet->icmp_len; - kfree(device_packet); - - if (error) - return error; - - return packet_len; -} - -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct icmp_packet_rr icmp_packet; - struct orig_node *orig_node; - struct batman_if *batman_if; - size_t packet_len = sizeof(struct icmp_packet); - uint8_t dstaddr[ETH_ALEN]; - unsigned long flags; - - if (len < sizeof(struct icmp_packet)) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "invalid packet size\n"); - return -EINVAL; - } - - if (len >= sizeof(struct icmp_packet_rr)) - packet_len = sizeof(struct icmp_packet_rr); - - if (!access_ok(VERIFY_READ, buff, packet_len)) - return -EFAULT; - - if (__copy_from_user(&icmp_packet, buff, packet_len)) - return -EFAULT; - - if (icmp_packet.packet_type != BAT_ICMP) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus packet type (expected: BAT_ICMP)\n"); - return -EINVAL; - } - - if (icmp_packet.msg_type != ECHO_REQUEST) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus message type (expected: ECHO_REQUEST)\n"); - return -EINVAL; - } - - icmp_packet.uid = device_client->index; - - if (icmp_packet.version != COMPAT_VERSION) { - icmp_packet.msg_type = PARAMETER_PROBLEM; - icmp_packet.ttl = COMPAT_VERSION; - bat_device_add_packet(device_client, &icmp_packet, packet_len); - goto out; - } - - if (atomic_read(&module_state) != MODULE_ACTIVE) - goto dst_unreach; - - spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); - - if (!orig_node) - goto unlock; - - if (!orig_node->router) - goto unlock; - - batman_if = orig_node->router->if_incoming; - memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - - spin_unlock_irqrestore(&orig_hash_lock, flags); - - if (!batman_if) - goto dst_unreach; - - if (batman_if->if_status != IF_ACTIVE) - goto dst_unreach; - - memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN); - - if (packet_len == sizeof(struct icmp_packet_rr)) - memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); - - send_raw_packet((unsigned char *)&icmp_packet, - packet_len, batman_if, dstaddr); - - goto out; - -unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); -dst_unreach: - icmp_packet.msg_type = DESTINATION_UNREACHABLE; - bat_device_add_packet(device_client, &icmp_packet, packet_len); -out: - return len; -} - -unsigned int bat_device_poll(struct file *file, poll_table *wait) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - - poll_wait(file, &device_client->queue_wait, wait); - - if (device_client->queue_len > 0) - return POLLIN | POLLRDNORM; - - return 0; -} - -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet_rr *icmp_packet, - size_t icmp_len) -{ - struct device_packet *device_packet; - unsigned long flags; - - device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL); - - if (!device_packet) - return; - - INIT_LIST_HEAD(&device_packet->list); - memcpy(&device_packet->icmp_packet, icmp_packet, icmp_len); - device_packet->icmp_len = icmp_len; - - spin_lock_irqsave(&device_client->lock, flags); - - /* while waiting for the lock the device_client could have been - * deleted */ - if (!device_client_hash[icmp_packet->uid]) { - spin_unlock_irqrestore(&device_client->lock, flags); - kfree(device_packet); - return; - } - - list_add_tail(&device_packet->list, &device_client->queue_list); - device_client->queue_len++; - - if (device_client->queue_len > 100) { - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - - list_del(&device_packet->list); - kfree(device_packet); - device_client->queue_len--; - } - - spin_unlock_irqrestore(&device_client->lock, flags); - - wake_up(&device_client->queue_wait); -} - -void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet, - size_t icmp_len) -{ - struct device_client *hash = device_client_hash[icmp_packet->uid]; - - if (hash) - bat_device_add_packet(hash, icmp_packet, icmp_len); -} diff --git a/batman-adv-kernelland/device.h b/batman-adv-kernelland/device.h deleted file mode 100644 index 0775432..0000000 --- a/batman-adv-kernelland/device.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include "types.h" - -void bat_device_init(void); -int bat_device_setup(void); -void bat_device_destroy(void); -int bat_device_open(struct inode *inode, struct file *file); -int bat_device_release(struct inode *inode, struct file *file); -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos); -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off); -unsigned int bat_device_poll(struct file *file, poll_table *wait); -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet_rr *icmp_packet, - size_t icmp_len); -void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet, - size_t icmp_len); diff --git a/batman-adv-kernelland/icmp_socket.c b/batman-adv-kernelland/icmp_socket.c new file mode 100644 index 0000000..c24bd08 --- /dev/null +++ b/batman-adv-kernelland/icmp_socket.c @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include <linux/debugfs.h> +#include "main.h" +#include "icmp_socket.h" +#include "send.h" +#include "types.h" +#include "hash.h" +#include "hard-interface.h" + +#include "compat.h" + + +static struct socket_client *socket_client_hash[256]; + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet_rr *icmp_packet, + size_t icmp_len); + +void bat_socket_init(void) +{ + memset(socket_client_hash, 0, sizeof(socket_client_hash)); +} + +static int bat_socket_open(struct inode *inode, struct file *file) +{ + unsigned int i; + struct socket_client *socket_client; + + socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL); + + if (!socket_client) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(socket_client_hash); i++) { + if (!socket_client_hash[i]) { + socket_client_hash[i] = socket_client; + break; + } + } + + if (i == ARRAY_SIZE(socket_client_hash)) { + printk(KERN_ERR "batman-adv:" + "Error - can't add another packet client: " + "maximum number of clients reached\n"); + kfree(socket_client); + return -EXFULL; + } + + INIT_LIST_HEAD(&socket_client->queue_list); + socket_client->queue_len = 0; + socket_client->index = i; + spin_lock_init(&socket_client->lock); + init_waitqueue_head(&socket_client->queue_wait); + + file->private_data = socket_client; + + inc_module_count(); + return 0; +} + +static int bat_socket_release(struct inode *inode, struct file *file) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + struct list_head *list_pos, *list_pos_tmp; + unsigned long flags; + + spin_lock_irqsave(&socket_client->lock, flags); + + /* for all packets in the queue ... */ + list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) { + socket_packet = list_entry(list_pos, + struct socket_packet, list); + + list_del(list_pos); + kfree(socket_packet); + } + + socket_client_hash[socket_client->index] = NULL; + spin_unlock_irqrestore(&socket_client->lock, flags); + + kfree(socket_client); + dec_module_count(); + + return 0; +} + +static ssize_t bat_socket_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + size_t packet_len; + int error; + unsigned long flags; + + if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0)) + return -EAGAIN; + + if ((!buf) || (count < sizeof(struct icmp_packet))) + return -EINVAL; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + error = wait_event_interruptible(socket_client->queue_wait, + socket_client->queue_len); + + if (error) + return error; + + spin_lock_irqsave(&socket_client->lock, flags); + + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + list_del(&socket_packet->list); + socket_client->queue_len--; + + spin_unlock_irqrestore(&socket_client->lock, flags); + + error = __copy_to_user(buf, &socket_packet->icmp_packet, + socket_packet->icmp_len); + + packet_len = socket_packet->icmp_len; + kfree(socket_packet); + + if (error) + return error; + + return packet_len; +} + +static ssize_t bat_socket_write(struct file *file, const char __user *buff, + size_t len, loff_t *off) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct icmp_packet_rr icmp_packet; + struct orig_node *orig_node; + struct batman_if *batman_if; + size_t packet_len = sizeof(struct icmp_packet); + uint8_t dstaddr[ETH_ALEN]; + unsigned long flags; + + if (len < sizeof(struct icmp_packet)) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "invalid packet size\n"); + return -EINVAL; + } + + if (len >= sizeof(struct icmp_packet_rr)) + packet_len = sizeof(struct icmp_packet_rr); + + if (!access_ok(VERIFY_READ, buff, packet_len)) + return -EFAULT; + + if (__copy_from_user(&icmp_packet, buff, packet_len)) + return -EFAULT; + + if (icmp_packet.packet_type != BAT_ICMP) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus packet type (expected: BAT_ICMP)\n"); + return -EINVAL; + } + + if (icmp_packet.msg_type != ECHO_REQUEST) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus message type (expected: ECHO_REQUEST)\n"); + return -EINVAL; + } + + icmp_packet.uid = socket_client->index; + + if (icmp_packet.version != COMPAT_VERSION) { + icmp_packet.msg_type = PARAMETER_PROBLEM; + icmp_packet.ttl = COMPAT_VERSION; + bat_socket_add_packet(socket_client, &icmp_packet, packet_len); + goto out; + } + + if (atomic_read(&module_state) != MODULE_ACTIVE) + goto dst_unreach; + + spin_lock_irqsave(&orig_hash_lock, flags); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); + + if (!orig_node) + goto unlock; + + if (!orig_node->router) + goto unlock; + + batman_if = orig_node->router->if_incoming; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + + spin_unlock_irqrestore(&orig_hash_lock, flags); + + if (!batman_if) + goto dst_unreach; + + if (batman_if->if_status != IF_ACTIVE) + goto dst_unreach; + + memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN); + + if (packet_len == sizeof(struct icmp_packet_rr)) + memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); + + send_raw_packet((unsigned char *)&icmp_packet, + packet_len, batman_if, dstaddr); + + goto out; + +unlock: + spin_unlock_irqrestore(&orig_hash_lock, flags); +dst_unreach: + icmp_packet.msg_type = DESTINATION_UNREACHABLE; + bat_socket_add_packet(socket_client, &icmp_packet, packet_len); +out: + return len; +} + +static unsigned int bat_socket_poll(struct file *file, poll_table *wait) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + + poll_wait(file, &socket_client->queue_wait, wait); + + if (socket_client->queue_len > 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static const struct file_operations fops = { + .open = bat_socket_open, + .release = bat_socket_release, + .read = bat_socket_read, + .write = bat_socket_write, + .poll = bat_socket_poll, +}; + +int bat_socket_setup(struct bat_priv *bat_priv) +{ + struct dentry *d; + + if (!bat_priv->debug_dir) + goto err; + + d = debugfs_create_file(ICMP_SOCKET, S_IWUSR | S_IRUSR, + bat_priv->debug_dir, NULL, &fops); + if (d) + goto err; + + return 0; + +err: + return 1; +} + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet_rr *icmp_packet, + size_t icmp_len) +{ + struct socket_packet *socket_packet; + unsigned long flags; + + socket_packet = kmalloc(sizeof(struct socket_packet), GFP_KERNEL); + + if (!socket_packet) + return; + + INIT_LIST_HEAD(&socket_packet->list); + memcpy(&socket_packet->icmp_packet, icmp_packet, icmp_len); + socket_packet->icmp_len = icmp_len; + + spin_lock_irqsave(&socket_client->lock, flags); + + /* while waiting for the lock the socket_client could have been + * deleted */ + if (!socket_client_hash[icmp_packet->uid]) { + spin_unlock_irqrestore(&socket_client->lock, flags); + kfree(socket_packet); + return; + } + + list_add_tail(&socket_packet->list, &socket_client->queue_list); + socket_client->queue_len++; + + if (socket_client->queue_len > 100) { + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + + list_del(&socket_packet->list); + kfree(socket_packet); + socket_client->queue_len--; + } + + spin_unlock_irqrestore(&socket_client->lock, flags); + + wake_up(&socket_client->queue_wait); +} + +void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet, + size_t icmp_len) +{ + struct socket_client *hash = socket_client_hash[icmp_packet->uid]; + + if (hash) + bat_socket_add_packet(hash, icmp_packet, icmp_len); +} diff --git a/batman-adv-kernelland/icmp_socket.h b/batman-adv-kernelland/icmp_socket.h new file mode 100644 index 0000000..2dc954a --- /dev/null +++ b/batman-adv-kernelland/icmp_socket.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "types.h" + +#define ICMP_SOCKET "socket" + +void bat_socket_init(void); +int bat_socket_setup(struct bat_priv *bat_priv); +void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet, + size_t icmp_len); diff --git a/batman-adv-kernelland/main.c b/batman-adv-kernelland/main.c index d03a7fa..cbabba6 100644 --- a/batman-adv-kernelland/main.c +++ b/batman-adv-kernelland/main.c @@ -21,11 +21,12 @@
#include "main.h" #include "bat_sysfs.h" +#include "bat_debugfs.h" #include "routing.h" #include "send.h" #include "originator.h" #include "soft-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "hard-interface.h" #include "gateway_client.h" @@ -85,7 +86,8 @@ int init_module(void) if (!bat_event_workqueue) return -ENOMEM;
- bat_device_init(); + bat_socket_init(); + debugfs_init();
/* initialize layer 2 interface */ soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", @@ -110,6 +112,11 @@ int init_module(void) if (retval < 0) goto unreg_soft_device;
+ retval = debugfs_add_meshif(soft_device); + + if (retval < 0) + goto unreg_sysfs; + register_netdevice_notifier(&hard_if_notifier); dev_add_pack(&batman_adv_packet_type);
@@ -119,6 +126,8 @@ int init_module(void)
return 0;
+unreg_sysfs: + sysfs_del_meshif(soft_device); unreg_soft_device: unregister_netdevice(soft_device); free_soft_device: @@ -136,6 +145,7 @@ void cleanup_module(void) hardif_remove_interfaces();
if (soft_device) { + debugfs_del_meshif(soft_device); sysfs_del_meshif(soft_device); unregister_netdev(soft_device); soft_device = NULL; @@ -147,7 +157,7 @@ void cleanup_module(void) bat_event_workqueue = NULL; }
-/* activates the module, creates bat device, starts timer ... */ +/* activates the module, starts timer ... */ void activate_module(void) { if (originator_init() < 1) @@ -161,9 +171,6 @@ void activate_module(void)
hna_local_add(soft_device->dev_addr);
- if (bat_device_setup() < 1) - goto end; - if (vis_init() < 1) goto err;
@@ -199,7 +206,7 @@ void deactivate_module(void) hna_global_free();
synchronize_net(); - bat_device_destroy(); + debugfs_destroy();
synchronize_rcu(); atomic_set(&module_state, MODULE_INACTIVE); diff --git a/batman-adv-kernelland/routing.c b/batman-adv-kernelland/routing.c index a93ed46..d08d0f6 100644 --- a/batman-adv-kernelland/routing.c +++ b/batman-adv-kernelland/routing.c @@ -25,7 +25,7 @@ #include "hash.h" #include "soft-interface.h" #include "hard-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "originator.h" #include "types.h" @@ -801,7 +801,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
/* add data to device queue */ if (icmp_packet->msg_type != ECHO_REQUEST) { - bat_device_receive_packet(icmp_packet, icmp_len); + bat_socket_receive_packet(icmp_packet, icmp_len); return NET_RX_DROP; }
diff --git a/batman-adv-kernelland/types.h b/batman-adv-kernelland/types.h index f9dda8e..75930cf 100644 --- a/batman-adv-kernelland/types.h +++ b/batman-adv-kernelland/types.h @@ -129,9 +129,10 @@ struct bat_priv { char num_ifaces; struct batman_if *primary_if; struct kobject *mesh_obj; + struct dentry *debug_dir; };
-struct device_client { +struct socket_client { struct list_head queue_list; unsigned int queue_len; unsigned char index; @@ -139,7 +140,7 @@ struct device_client { wait_queue_head_t queue_wait; };
-struct device_packet { +struct socket_packet { struct list_head list; size_t icmp_len; struct icmp_packet_rr icmp_packet;
The batman-adv device which was only usable for a single batX net device was replaced with a file in debugfs which can be used the same way as /dev/batman-adv before.
It seems that the debugfs has no 100% common mount path in current distributions and maybe isn't mounted at all. So before we try to access a batman file in debugfs, we have to search for the mountpoint in /proc/mounts and maybe mount it manually in /sys/kernel/debug.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- batctl/Makefile | 4 +- batctl/debugfs.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++ batctl/debugfs.h | 46 +++++++++ batctl/main.h | 2 +- batctl/ping.c | 21 +++- batctl/traceroute.c | 21 +++- 6 files changed, 350 insertions(+), 13 deletions(-) create mode 100644 batctl/debugfs.c create mode 100644 batctl/debugfs.h
diff --git a/batctl/Makefile b/batctl/Makefile index db375f7..bc591da 100644 --- a/batctl/Makefile +++ b/batctl/Makefile @@ -39,8 +39,8 @@ SRC_FILES = "(.c)|(.h)|(Makefile)|(INSTALL)|(LIESMICH)|(README EXTRA_MODULES_C := bisect.c EXTRA_MODULES_H := bisect.h
-SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c $(EXTRA_MODULES_C) -SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h $(EXTRA_MODULES_H) +SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) +SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) SRC_O = $(SRC_C:.c=.o)
PACKAGE_NAME = batctl diff --git a/batctl/debugfs.c b/batctl/debugfs.c new file mode 100644 index 0000000..cfe1254 --- /dev/null +++ b/batctl/debugfs.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2009 Clark Williams williams@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@cn.fujitsu.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "debugfs.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <linux/magic.h> +#include <sys/vfs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef DEBUGFS_MAGIC +#define DEBUGFS_MAGIC 0x64626720 +#endif + +static int debugfs_premounted; +static char debugfs_mountpoint[MAX_PATH+1]; + +static const char *debugfs_known_mountpoints[] = { + "/sys/kernel/debug/", + "/debug/", + 0, +}; + +/* use this to force a umount */ +void debugfs_force_cleanup(void) +{ + debugfs_find_mountpoint(); + debugfs_premounted = 0; + debugfs_umount(); +} + +/* construct a full path to a debugfs element */ +int debugfs_make_path(const char *element, char *buffer, int size) +{ + int len; + + if (strlen(debugfs_mountpoint) == 0) { + buffer[0] = '\0'; + return -1; + } + + len = strlen(debugfs_mountpoint) + strlen(element) + 1; + if (len >= size) + return len+1; + + snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element); + return 0; +} + +static int debugfs_found; + +/* find the path to the mounted debugfs */ +const char *debugfs_find_mountpoint(void) +{ + const char **ptr; + char type[100]; + FILE *fp; + + if (debugfs_found) + return (const char *) debugfs_mountpoint; + + ptr = debugfs_known_mountpoints; + while (*ptr) { + if (debugfs_valid_mountpoint(*ptr) == 0) { + debugfs_found = 1; + strcpy(debugfs_mountpoint, *ptr); + return debugfs_mountpoint; + } + ptr++; + } + + /* give up and parse /proc/mounts */ + fp = fopen("/proc/mounts", "r"); + if (fp == NULL) { + printf("Error - can't open /proc/mounts for read: %s\n", + strerror(errno)); + return NULL; + } + + while (fscanf(fp, "%*s %" + STR(MAX_PATH) + "s %99s %*s %*d %*d\n", + debugfs_mountpoint, type) == 2) { + if (strcmp(type, "debugfs") == 0) + break; + } + fclose(fp); + + if (strcmp(type, "debugfs") != 0) + return NULL; + + debugfs_found = 1; + + return debugfs_mountpoint; +} + +/* verify that a mountpoint is actually a debugfs instance */ + +int debugfs_valid_mountpoint(const char *debugfs) +{ + struct statfs st_fs; + + if (statfs(debugfs, &st_fs) < 0) + return -ENOENT; + else if (st_fs.f_type != (long) DEBUGFS_MAGIC) + return -ENOENT; + + return 0; +} + + +int debugfs_valid_entry(const char *path) +{ + struct stat st; + + if (stat(path, &st)) + return -errno; + + return 0; +} + +/* mount the debugfs somewhere if it's not mounted */ + +char *debugfs_mount(const char *mountpoint) +{ + /* see if it's already mounted */ + if (debugfs_find_mountpoint()) { + debugfs_premounted = 1; + return debugfs_mountpoint; + } + + /* if not mounted and no argument */ + if (mountpoint == NULL) + mountpoint = "/sys/kernel/debug"; + + if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) + return NULL; + + /* save the mountpoint */ + strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint)); + debugfs_found = 1; + + return debugfs_mountpoint; +} + +/* umount the debugfs */ + +int debugfs_umount(void) +{ + char umountcmd[128]; + int ret; + + /* if it was already mounted, leave it */ + if (debugfs_premounted) + return 0; + + /* make sure it's a valid mount point */ + ret = debugfs_valid_mountpoint(debugfs_mountpoint); + if (ret) + return ret; + + snprintf(umountcmd, sizeof(umountcmd), + "/bin/umount %s", debugfs_mountpoint); + return system(umountcmd); +} + +int debugfs_write(const char *entry, const char *value) +{ + char path[MAX_PATH+1]; + int ret, count; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* get how many chars we're going to write */ + count = strlen(value); + + /* open the debugfs entry */ + fd = open(path, O_RDWR); + if (fd < 0) + return -errno; + + while (count > 0) { + /* write it */ + ret = write(fd, value, count); + if (ret <= 0) { + if (ret == EAGAIN) + continue; + close(fd); + return -errno; + } + count -= ret; + } + + /* close it */ + close(fd); + + /* return success */ + return 0; +} + +/* + * read a debugfs entry + * returns the number of chars read or a negative errno + */ +int debugfs_read(const char *entry, char *buffer, size_t size) +{ + char path[MAX_PATH+1]; + int ret; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* open the debugfs entry */ + fd = open(path, O_RDONLY); + if (fd < 0) + return -errno; + + do { + /* read it */ + ret = read(fd, buffer, size); + if (ret == 0) { + close(fd); + return EOF; + } + } while (ret < 0 && errno == EAGAIN); + + /* close it */ + close(fd); + + /* make *sure* there's a null character at the end */ + buffer[ret] = '\0'; + + /* return the number of chars read */ + return ret; +} diff --git a/batctl/debugfs.h b/batctl/debugfs.h new file mode 100644 index 0000000..45f6339 --- /dev/null +++ b/batctl/debugfs.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 Clark Williams williams@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@cn.fujitsu.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#ifndef __DEBUGFS_H__ +#define __DEBUGFS_H__ + +#include <sys/mount.h> +#include <string.h> + +#ifndef MAX_PATH +# define MAX_PATH 256 +#endif + +#ifndef STR +# define _STR(x) #x +# define STR(x) _STR(x) +#endif + +extern const char *debugfs_find_mountpoint(void); +extern int debugfs_valid_mountpoint(const char *debugfs); +extern int debugfs_valid_entry(const char *path); +extern char *debugfs_mount(const char *mountpoint); +extern int debugfs_umount(void); +extern int debugfs_write(const char *entry, const char *value); +extern int debugfs_read(const char *entry, char *buffer, size_t size); +extern void debugfs_force_cleanup(void); +extern int debugfs_make_path(const char *element, char *buffer, int size); + +#endif /* __DEBUGFS_H__ */ diff --git a/batctl/main.h b/batctl/main.h index 9c83a7e..2fe603e 100644 --- a/batctl/main.h +++ b/batctl/main.h @@ -23,4 +23,4 @@
#define SOURCE_VERSION "0.3.0-alpha" /*put exactly one distinct word inside the string like "0.3-pre-alpha" or "0.3-rc1" or "0.3" */
-#define BAT_DEVICE "/dev/batman-adv" +#define SOCKET_PATH "batman_adv/bat0/socket" diff --git a/batctl/ping.c b/batctl/ping.c index 0352870..9df5c07 100644 --- a/batctl/ping.c +++ b/batctl/ping.c @@ -35,6 +35,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
char is_aborted = 0; @@ -79,6 +80,8 @@ int ping(int argc, char **argv) float min = 0.0, max = 0.0, avg = 0.0; uint8_t last_rr_cur = 0, last_rr[BAT_RR_LEN][ETH_ALEN]; size_t packet_len; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hc:i:t:R")) != -1) { switch (optchar) { @@ -139,11 +142,19 @@ int ping(int argc, char **argv) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler);
- ping_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + ping_fd = open(icmp_socket, O_RDWR);
if (ping_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -177,7 +188,7 @@ int ping(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(ping_fd, (char *)&icmp_packet_out, packet_len) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
@@ -207,7 +218,7 @@ int ping(int argc, char **argv) read_len = read(ping_fd, (char *)&icmp_packet_in, packet_len);
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
diff --git a/batctl/traceroute.c b/batctl/traceroute.c index b9b838e..00fcd89 100644 --- a/batctl/traceroute.c +++ b/batctl/traceroute.c @@ -34,6 +34,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
#define TTL_MAX 50 @@ -59,6 +60,8 @@ int traceroute(int argc, char **argv) int ret = EXIT_FAILURE, res, trace_fd = 0, i; int found_args = 1, optchar, seq_counter = 0, read_opt = USE_BAT_HOSTS; double time_delta; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hn")) != -1) { switch (optchar) { @@ -99,11 +102,19 @@ int traceroute(int argc, char **argv)
mac_string = ether_ntoa_long(dst_mac);
- trace_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + trace_fd = open(icmp_socket, O_RDWR);
if (trace_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -123,7 +134,7 @@ int traceroute(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(trace_fd, (char *)&icmp_packet_out, sizeof(icmp_packet_out)) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }
@@ -149,7 +160,7 @@ int traceroute(int argc, char **argv) read_len = read(trace_fd, (char *)&icmp_packet_in, sizeof(icmp_packet_in));
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }
Sven Eckelmann wrote:
Unfortunately I am not able to continue it today, but don't want to stop other people working on similar things. I will attach v0 (aka works for me, but maybe not perfect/good enough) versions of these patches to support them. Please feel free to discuss the patches.
I converted the remaining files from sysfs to debugfs, but I noticed that there is a problem with the output functions (see "BUG" comments in patch 3). The problem is that we may sleep during the prints in the output functions, but we disabled interrupts.... which is bad. This problem was also their before we converted from /proc to /sys. It seems that it was first introduced in r1517. The old way for hna_global_fill_buffer_text hna_local_fill_buffer_text solved it, but restricted the output to 4096 bytes. So we could either stay with a "slow" and maybe inconsistent output or restricted output length or copy the data to a local buffer and then creating the output without spinlock or something completely different.
The patches are for trunk, but I would provide backported versions when the patches are discussed and we could solve the problem in a sane way.
Best regards, Sven
batctl uses /dev/batman-adv to send special batman-adv icmp packets to other nodes in the mesh. To get it working with multiple batX devices we must ensure that every mesh device can have their own socket which is used to inject those packets in exactly one mesh.
The current implementation still doesn't allow to use complete separated meshes as we rely on structures which are not part of the private data of a batman device.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- batman-adv-kernelland/Makefile.kbuild | 2 +- batman-adv-kernelland/bat_debugfs.c | 76 +++++++ batman-adv-kernelland/bat_debugfs.h | 33 +++ batman-adv-kernelland/compat.h | 65 +++++- batman-adv-kernelland/device.c | 363 --------------------------------- batman-adv-kernelland/device.h | 38 ---- batman-adv-kernelland/icmp_socket.c | 338 ++++++++++++++++++++++++++++++ batman-adv-kernelland/icmp_socket.h | 29 +++ batman-adv-kernelland/main.c | 21 ++- batman-adv-kernelland/routing.c | 4 +- batman-adv-kernelland/types.h | 5 +- 11 files changed, 551 insertions(+), 423 deletions(-) create mode 100644 batman-adv-kernelland/bat_debugfs.c create mode 100644 batman-adv-kernelland/bat_debugfs.h delete mode 100644 batman-adv-kernelland/device.c delete mode 100644 batman-adv-kernelland/device.h create mode 100644 batman-adv-kernelland/icmp_socket.c create mode 100644 batman-adv-kernelland/icmp_socket.h
diff --git a/batman-adv-kernelland/Makefile.kbuild b/batman-adv-kernelland/Makefile.kbuild index e9b58b9..d42f6a3 100644 --- a/batman-adv-kernelland/Makefile.kbuild +++ b/batman-adv-kernelland/Makefile.kbuild @@ -32,4 +32,4 @@ EXTRA_CFLAGS += -DREVISION_VERSION="r$(REVISION)" endif
obj-m += batman-adv.o -batman-adv-objs := main.o bat_sysfs.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o gateway_common.o gateway_client.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) +batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o gateway_common.o gateway_client.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) diff --git a/batman-adv-kernelland/bat_debugfs.c b/batman-adv-kernelland/bat_debugfs.c new file mode 100644 index 0000000..19e7bee --- /dev/null +++ b/batman-adv-kernelland/bat_debugfs.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include <linux/debugfs.h> + +#include "main.h" +#include "bat_debugfs.h" +#include "translation-table.h" +#include "originator.h" +#include "hard-interface.h" +#include "gateway_common.h" +#include "gateway_client.h" +#include "vis.h" +#include "icmp_socket.h" +#include "compat.h" + +static struct dentry *bat_debugfs; + +void debugfs_init(void) +{ + bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); +} + +void debugfs_destroy(void) +{ + if (bat_debugfs) { + debugfs_remove_recursive(bat_debugfs); + bat_debugfs = NULL; + } +} + +int debugfs_add_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (!bat_debugfs) + goto out; + + bat_priv->debug_dir = debugfs_create_dir(dev->name, bat_debugfs); + if (!bat_priv->debug_dir) + goto out; + + bat_socket_setup(bat_priv); + + return 0; +out: + return -ENOMEM; +} + +void debugfs_del_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (bat_debugfs) { + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; + } +} diff --git a/batman-adv-kernelland/bat_debugfs.h b/batman-adv-kernelland/bat_debugfs.h new file mode 100644 index 0000000..5cdd332 --- /dev/null +++ b/batman-adv-kernelland/bat_debugfs.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#ifndef BAT_DEBUGFS_H +#define BAT_DEBUGFS_H + +#define DEBUGFS_BAT_SUBDIR "batman_adv" + +void debugfs_init(void); +void debugfs_destroy(void); +int debugfs_add_meshif(struct net_device *dev); +void debugfs_del_meshif(struct net_device *dev); + +#endif diff --git a/batman-adv-kernelland/compat.h b/batman-adv-kernelland/compat.h index 088b3ae..59a6031 100644 --- a/batman-adv-kernelland/compat.h +++ b/batman-adv-kernelland/compat.h @@ -164,12 +164,6 @@ static inline char *pack_hex_byte(char *buf, u8 byte) return buf; }
-#define device_create(_cls, _parent, _devt, _device, _fmt) \ - class_device_create(_cls, _parent, _devt, _device, _fmt) - -#define device_destroy(_cls, _device) \ - class_device_destroy(_cls, _device) - #endif /* < KERNEL_VERSION(2, 6, 26) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) @@ -178,10 +172,61 @@ static inline char *pack_hex_byte(char *buf, u8 byte) #define dereference_function_descriptor(p) (p) #endif
-#ifndef device_create -#define device_create(_cls, _parent, _devt, _device, _fmt) \ - device_create_drvdata(_cls, _parent, _devt, _device, _fmt) -#endif +#include <linux/debugfs.h> + +static inline void debugfs_remove_recursive(struct dentry *dentry) +{ + struct dentry *child; + struct dentry *parent; + + if (!dentry) + return; + + parent = dentry->d_parent; + if (!parent || !parent->d_inode) + return; + + parent = dentry; + + while (1) { + /* + * When all dentries under "parent" has been removed, + * walk up the tree until we reach our starting point. + */ + if (list_empty(&parent->d_subdirs)) { + if (parent == dentry) + break; + parent = parent->d_parent; + } + child = list_entry(parent->d_subdirs.next, struct dentry, + d_u.d_child); +next_sibling: + + /* + * If "child" isn't empty, walk down the tree and + * remove all its descendants first. + */ + if (!list_empty(&child->d_subdirs)) { + parent = child; + continue; + } + debugfs_remove(child); + if (parent->d_subdirs.next == &child->d_u.d_child) { + /* + * Try the next sibling. + */ + if (child->d_u.d_child.next != &parent->d_subdirs) { + child = list_entry(child->d_u.d_child.next, + struct dentry, + d_u.d_child); + goto next_sibling; + } + break; + } + } + + debugfs_remove(dentry); +}
#endif /* < KERNEL_VERSION(2, 6, 27) */
diff --git a/batman-adv-kernelland/device.c b/batman-adv-kernelland/device.c deleted file mode 100644 index 8a99ea9..0000000 --- a/batman-adv-kernelland/device.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include <linux/device.h> -#include "main.h" -#include "device.h" -#include "send.h" -#include "types.h" -#include "hash.h" -#include "hard-interface.h" - -#include "compat.h" - -static struct class *batman_class; - -static int Major; /* Major number assigned to our device driver */ - -static const struct file_operations fops = { - .open = bat_device_open, - .release = bat_device_release, - .read = bat_device_read, - .write = bat_device_write, - .poll = bat_device_poll, -}; - -static struct device_client *device_client_hash[256]; - -void bat_device_init(void) -{ - memset(device_client_hash, 0, sizeof(device_client_hash)); -} - -int bat_device_setup(void) -{ - int tmp_major; - - if (Major) - return 1; - - /* register our device - kernel assigns a free major number */ - tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops); - if (tmp_major < 0) { - printk(KERN_ERR "batman-adv:" - "Registering the character device failed with %d\n", - tmp_major); - return 0; - } - - batman_class = class_create(THIS_MODULE, "batman-adv"); - - if (IS_ERR(batman_class)) { - printk(KERN_ERR "batman-adv:" - "Could not register class 'batman-adv'\n"); - return 0; - } - - device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL, - "batman-adv"); - - Major = tmp_major; - return 1; -} - -void bat_device_destroy(void) -{ - if (!Major) - return; - - device_destroy(batman_class, MKDEV(Major, 0)); - class_destroy(batman_class); - - /* Unregister the device */ - unregister_chrdev(Major, DRIVER_DEVICE); - - Major = 0; -} - -int bat_device_open(struct inode *inode, struct file *file) -{ - unsigned int i; - struct device_client *device_client; - - device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL); - - if (!device_client) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) { - if (!device_client_hash[i]) { - device_client_hash[i] = device_client; - break; - } - } - - if (i == ARRAY_SIZE(device_client_hash)) { - printk(KERN_ERR "batman-adv:" - "Error - can't add another packet client: " - "maximum number of clients reached\n"); - kfree(device_client); - return -EXFULL; - } - - INIT_LIST_HEAD(&device_client->queue_list); - device_client->queue_len = 0; - device_client->index = i; - spin_lock_init(&device_client->lock); - init_waitqueue_head(&device_client->queue_wait); - - file->private_data = device_client; - - inc_module_count(); - return 0; -} - -int bat_device_release(struct inode *inode, struct file *file) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - struct list_head *list_pos, *list_pos_tmp; - unsigned long flags; - - spin_lock_irqsave(&device_client->lock, flags); - - /* for all packets in the queue ... */ - list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) { - device_packet = list_entry(list_pos, - struct device_packet, list); - - list_del(list_pos); - kfree(device_packet); - } - - device_client_hash[device_client->index] = NULL; - spin_unlock_irqrestore(&device_client->lock, flags); - - kfree(device_client); - dec_module_count(); - - return 0; -} - -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - size_t packet_len; - int error; - unsigned long flags; - - if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0)) - return -EAGAIN; - - if ((!buf) || (count < sizeof(struct icmp_packet))) - return -EINVAL; - - if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; - - error = wait_event_interruptible(device_client->queue_wait, - device_client->queue_len); - - if (error) - return error; - - spin_lock_irqsave(&device_client->lock, flags); - - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - list_del(&device_packet->list); - device_client->queue_len--; - - spin_unlock_irqrestore(&device_client->lock, flags); - - error = __copy_to_user(buf, &device_packet->icmp_packet, - device_packet->icmp_len); - - packet_len = device_packet->icmp_len; - kfree(device_packet); - - if (error) - return error; - - return packet_len; -} - -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct icmp_packet_rr icmp_packet; - struct orig_node *orig_node; - struct batman_if *batman_if; - size_t packet_len = sizeof(struct icmp_packet); - uint8_t dstaddr[ETH_ALEN]; - unsigned long flags; - - if (len < sizeof(struct icmp_packet)) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "invalid packet size\n"); - return -EINVAL; - } - - if (len >= sizeof(struct icmp_packet_rr)) - packet_len = sizeof(struct icmp_packet_rr); - - if (!access_ok(VERIFY_READ, buff, packet_len)) - return -EFAULT; - - if (__copy_from_user(&icmp_packet, buff, packet_len)) - return -EFAULT; - - if (icmp_packet.packet_type != BAT_ICMP) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus packet type (expected: BAT_ICMP)\n"); - return -EINVAL; - } - - if (icmp_packet.msg_type != ECHO_REQUEST) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus message type (expected: ECHO_REQUEST)\n"); - return -EINVAL; - } - - icmp_packet.uid = device_client->index; - - if (icmp_packet.version != COMPAT_VERSION) { - icmp_packet.msg_type = PARAMETER_PROBLEM; - icmp_packet.ttl = COMPAT_VERSION; - bat_device_add_packet(device_client, &icmp_packet, packet_len); - goto out; - } - - if (atomic_read(&module_state) != MODULE_ACTIVE) - goto dst_unreach; - - spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); - - if (!orig_node) - goto unlock; - - if (!orig_node->router) - goto unlock; - - batman_if = orig_node->router->if_incoming; - memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - - spin_unlock_irqrestore(&orig_hash_lock, flags); - - if (!batman_if) - goto dst_unreach; - - if (batman_if->if_status != IF_ACTIVE) - goto dst_unreach; - - memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN); - - if (packet_len == sizeof(struct icmp_packet_rr)) - memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); - - send_raw_packet((unsigned char *)&icmp_packet, - packet_len, batman_if, dstaddr); - - goto out; - -unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); -dst_unreach: - icmp_packet.msg_type = DESTINATION_UNREACHABLE; - bat_device_add_packet(device_client, &icmp_packet, packet_len); -out: - return len; -} - -unsigned int bat_device_poll(struct file *file, poll_table *wait) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - - poll_wait(file, &device_client->queue_wait, wait); - - if (device_client->queue_len > 0) - return POLLIN | POLLRDNORM; - - return 0; -} - -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet_rr *icmp_packet, - size_t icmp_len) -{ - struct device_packet *device_packet; - unsigned long flags; - - device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL); - - if (!device_packet) - return; - - INIT_LIST_HEAD(&device_packet->list); - memcpy(&device_packet->icmp_packet, icmp_packet, icmp_len); - device_packet->icmp_len = icmp_len; - - spin_lock_irqsave(&device_client->lock, flags); - - /* while waiting for the lock the device_client could have been - * deleted */ - if (!device_client_hash[icmp_packet->uid]) { - spin_unlock_irqrestore(&device_client->lock, flags); - kfree(device_packet); - return; - } - - list_add_tail(&device_packet->list, &device_client->queue_list); - device_client->queue_len++; - - if (device_client->queue_len > 100) { - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - - list_del(&device_packet->list); - kfree(device_packet); - device_client->queue_len--; - } - - spin_unlock_irqrestore(&device_client->lock, flags); - - wake_up(&device_client->queue_wait); -} - -void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet, - size_t icmp_len) -{ - struct device_client *hash = device_client_hash[icmp_packet->uid]; - - if (hash) - bat_device_add_packet(hash, icmp_packet, icmp_len); -} diff --git a/batman-adv-kernelland/device.h b/batman-adv-kernelland/device.h deleted file mode 100644 index 0775432..0000000 --- a/batman-adv-kernelland/device.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include "types.h" - -void bat_device_init(void); -int bat_device_setup(void); -void bat_device_destroy(void); -int bat_device_open(struct inode *inode, struct file *file); -int bat_device_release(struct inode *inode, struct file *file); -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos); -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off); -unsigned int bat_device_poll(struct file *file, poll_table *wait); -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet_rr *icmp_packet, - size_t icmp_len); -void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet, - size_t icmp_len); diff --git a/batman-adv-kernelland/icmp_socket.c b/batman-adv-kernelland/icmp_socket.c new file mode 100644 index 0000000..33d2714 --- /dev/null +++ b/batman-adv-kernelland/icmp_socket.c @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include <linux/debugfs.h> +#include "main.h" +#include "icmp_socket.h" +#include "send.h" +#include "types.h" +#include "hash.h" +#include "hard-interface.h" + +#include "compat.h" + + +static struct socket_client *socket_client_hash[256]; + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet_rr *icmp_packet, + size_t icmp_len); + +void bat_socket_init(void) +{ + memset(socket_client_hash, 0, sizeof(socket_client_hash)); +} + +static int bat_socket_open(struct inode *inode, struct file *file) +{ + unsigned int i; + struct socket_client *socket_client; + + socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL); + + if (!socket_client) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(socket_client_hash); i++) { + if (!socket_client_hash[i]) { + socket_client_hash[i] = socket_client; + break; + } + } + + if (i == ARRAY_SIZE(socket_client_hash)) { + printk(KERN_ERR "batman-adv:" + "Error - can't add another packet client: " + "maximum number of clients reached\n"); + kfree(socket_client); + return -EXFULL; + } + + INIT_LIST_HEAD(&socket_client->queue_list); + socket_client->queue_len = 0; + socket_client->index = i; + spin_lock_init(&socket_client->lock); + init_waitqueue_head(&socket_client->queue_wait); + + file->private_data = socket_client; + + inc_module_count(); + return 0; +} + +static int bat_socket_release(struct inode *inode, struct file *file) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + struct list_head *list_pos, *list_pos_tmp; + unsigned long flags; + + spin_lock_irqsave(&socket_client->lock, flags); + + /* for all packets in the queue ... */ + list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) { + socket_packet = list_entry(list_pos, + struct socket_packet, list); + + list_del(list_pos); + kfree(socket_packet); + } + + socket_client_hash[socket_client->index] = NULL; + spin_unlock_irqrestore(&socket_client->lock, flags); + + kfree(socket_client); + dec_module_count(); + + return 0; +} + +static ssize_t bat_socket_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + size_t packet_len; + int error; + unsigned long flags; + + if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0)) + return -EAGAIN; + + if ((!buf) || (count < sizeof(struct icmp_packet))) + return -EINVAL; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + error = wait_event_interruptible(socket_client->queue_wait, + socket_client->queue_len); + + if (error) + return error; + + spin_lock_irqsave(&socket_client->lock, flags); + + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + list_del(&socket_packet->list); + socket_client->queue_len--; + + spin_unlock_irqrestore(&socket_client->lock, flags); + + error = __copy_to_user(buf, &socket_packet->icmp_packet, + socket_packet->icmp_len); + + packet_len = socket_packet->icmp_len; + kfree(socket_packet); + + if (error) + return error; + + return packet_len; +} + +static ssize_t bat_socket_write(struct file *file, const char __user *buff, + size_t len, loff_t *off) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct icmp_packet_rr icmp_packet; + struct orig_node *orig_node; + struct batman_if *batman_if; + size_t packet_len = sizeof(struct icmp_packet); + uint8_t dstaddr[ETH_ALEN]; + unsigned long flags; + + if (len < sizeof(struct icmp_packet)) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "invalid packet size\n"); + return -EINVAL; + } + + if (len >= sizeof(struct icmp_packet_rr)) + packet_len = sizeof(struct icmp_packet_rr); + + if (!access_ok(VERIFY_READ, buff, packet_len)) + return -EFAULT; + + if (__copy_from_user(&icmp_packet, buff, packet_len)) + return -EFAULT; + + if (icmp_packet.packet_type != BAT_ICMP) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus packet type (expected: BAT_ICMP)\n"); + return -EINVAL; + } + + if (icmp_packet.msg_type != ECHO_REQUEST) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus message type (expected: ECHO_REQUEST)\n"); + return -EINVAL; + } + + icmp_packet.uid = socket_client->index; + + if (icmp_packet.version != COMPAT_VERSION) { + icmp_packet.msg_type = PARAMETER_PROBLEM; + icmp_packet.ttl = COMPAT_VERSION; + bat_socket_add_packet(socket_client, &icmp_packet, packet_len); + goto out; + } + + if (atomic_read(&module_state) != MODULE_ACTIVE) + goto dst_unreach; + + spin_lock_irqsave(&orig_hash_lock, flags); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); + + if (!orig_node) + goto unlock; + + if (!orig_node->router) + goto unlock; + + batman_if = orig_node->router->if_incoming; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + + spin_unlock_irqrestore(&orig_hash_lock, flags); + + if (!batman_if) + goto dst_unreach; + + if (batman_if->if_status != IF_ACTIVE) + goto dst_unreach; + + memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN); + + if (packet_len == sizeof(struct icmp_packet_rr)) + memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); + + send_raw_packet((unsigned char *)&icmp_packet, + packet_len, batman_if, dstaddr); + + goto out; + +unlock: + spin_unlock_irqrestore(&orig_hash_lock, flags); +dst_unreach: + icmp_packet.msg_type = DESTINATION_UNREACHABLE; + bat_socket_add_packet(socket_client, &icmp_packet, packet_len); +out: + return len; +} + +static unsigned int bat_socket_poll(struct file *file, poll_table *wait) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + + poll_wait(file, &socket_client->queue_wait, wait); + + if (socket_client->queue_len > 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .open = bat_socket_open, + .release = bat_socket_release, + .read = bat_socket_read, + .write = bat_socket_write, + .poll = bat_socket_poll, +}; + +int bat_socket_setup(struct bat_priv *bat_priv) +{ + struct dentry *d; + + if (!bat_priv->debug_dir) + goto err; + + d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR, + bat_priv->debug_dir, NULL, &fops); + if (d) + goto err; + + return 0; + +err: + return 1; +} + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet_rr *icmp_packet, + size_t icmp_len) +{ + struct socket_packet *socket_packet; + unsigned long flags; + + socket_packet = kmalloc(sizeof(struct socket_packet), GFP_KERNEL); + + if (!socket_packet) + return; + + INIT_LIST_HEAD(&socket_packet->list); + memcpy(&socket_packet->icmp_packet, icmp_packet, icmp_len); + socket_packet->icmp_len = icmp_len; + + spin_lock_irqsave(&socket_client->lock, flags); + + /* while waiting for the lock the socket_client could have been + * deleted */ + if (!socket_client_hash[icmp_packet->uid]) { + spin_unlock_irqrestore(&socket_client->lock, flags); + kfree(socket_packet); + return; + } + + list_add_tail(&socket_packet->list, &socket_client->queue_list); + socket_client->queue_len++; + + if (socket_client->queue_len > 100) { + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + + list_del(&socket_packet->list); + kfree(socket_packet); + socket_client->queue_len--; + } + + spin_unlock_irqrestore(&socket_client->lock, flags); + + wake_up(&socket_client->queue_wait); +} + +void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet, + size_t icmp_len) +{ + struct socket_client *hash = socket_client_hash[icmp_packet->uid]; + + if (hash) + bat_socket_add_packet(hash, icmp_packet, icmp_len); +} diff --git a/batman-adv-kernelland/icmp_socket.h b/batman-adv-kernelland/icmp_socket.h new file mode 100644 index 0000000..2dc954a --- /dev/null +++ b/batman-adv-kernelland/icmp_socket.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "types.h" + +#define ICMP_SOCKET "socket" + +void bat_socket_init(void); +int bat_socket_setup(struct bat_priv *bat_priv); +void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet, + size_t icmp_len); diff --git a/batman-adv-kernelland/main.c b/batman-adv-kernelland/main.c index d03a7fa..cbabba6 100644 --- a/batman-adv-kernelland/main.c +++ b/batman-adv-kernelland/main.c @@ -21,11 +21,12 @@
#include "main.h" #include "bat_sysfs.h" +#include "bat_debugfs.h" #include "routing.h" #include "send.h" #include "originator.h" #include "soft-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "hard-interface.h" #include "gateway_client.h" @@ -85,7 +86,8 @@ int init_module(void) if (!bat_event_workqueue) return -ENOMEM;
- bat_device_init(); + bat_socket_init(); + debugfs_init();
/* initialize layer 2 interface */ soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", @@ -110,6 +112,11 @@ int init_module(void) if (retval < 0) goto unreg_soft_device;
+ retval = debugfs_add_meshif(soft_device); + + if (retval < 0) + goto unreg_sysfs; + register_netdevice_notifier(&hard_if_notifier); dev_add_pack(&batman_adv_packet_type);
@@ -119,6 +126,8 @@ int init_module(void)
return 0;
+unreg_sysfs: + sysfs_del_meshif(soft_device); unreg_soft_device: unregister_netdevice(soft_device); free_soft_device: @@ -136,6 +145,7 @@ void cleanup_module(void) hardif_remove_interfaces();
if (soft_device) { + debugfs_del_meshif(soft_device); sysfs_del_meshif(soft_device); unregister_netdev(soft_device); soft_device = NULL; @@ -147,7 +157,7 @@ void cleanup_module(void) bat_event_workqueue = NULL; }
-/* activates the module, creates bat device, starts timer ... */ +/* activates the module, starts timer ... */ void activate_module(void) { if (originator_init() < 1) @@ -161,9 +171,6 @@ void activate_module(void)
hna_local_add(soft_device->dev_addr);
- if (bat_device_setup() < 1) - goto end; - if (vis_init() < 1) goto err;
@@ -199,7 +206,7 @@ void deactivate_module(void) hna_global_free();
synchronize_net(); - bat_device_destroy(); + debugfs_destroy();
synchronize_rcu(); atomic_set(&module_state, MODULE_INACTIVE); diff --git a/batman-adv-kernelland/routing.c b/batman-adv-kernelland/routing.c index a93ed46..d08d0f6 100644 --- a/batman-adv-kernelland/routing.c +++ b/batman-adv-kernelland/routing.c @@ -25,7 +25,7 @@ #include "hash.h" #include "soft-interface.h" #include "hard-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "originator.h" #include "types.h" @@ -801,7 +801,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
/* add data to device queue */ if (icmp_packet->msg_type != ECHO_REQUEST) { - bat_device_receive_packet(icmp_packet, icmp_len); + bat_socket_receive_packet(icmp_packet, icmp_len); return NET_RX_DROP; }
diff --git a/batman-adv-kernelland/types.h b/batman-adv-kernelland/types.h index f9dda8e..75930cf 100644 --- a/batman-adv-kernelland/types.h +++ b/batman-adv-kernelland/types.h @@ -129,9 +129,10 @@ struct bat_priv { char num_ifaces; struct batman_if *primary_if; struct kobject *mesh_obj; + struct dentry *debug_dir; };
-struct device_client { +struct socket_client { struct list_head queue_list; unsigned int queue_len; unsigned char index; @@ -139,7 +140,7 @@ struct device_client { wait_queue_head_t queue_wait; };
-struct device_packet { +struct socket_packet { struct list_head list; size_t icmp_len; struct icmp_packet_rr icmp_packet;
The batman-adv device which was only usable for a single batX net device was replaced with a file in debugfs which can be used the same way as /dev/batman-adv before.
It seems that the debugfs has no 100% common mount path in current distributions and maybe isn't mounted at all. So before we try to access a batman file in debugfs, we have to search for the mountpoint in /proc/mounts and maybe mount it manually in /sys/kernel/debug.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- batctl/Makefile | 4 +- batctl/debugfs.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++ batctl/debugfs.h | 46 +++++++++ batctl/main.h | 2 +- batctl/ping.c | 21 +++- batctl/traceroute.c | 21 +++- 6 files changed, 350 insertions(+), 13 deletions(-) create mode 100644 batctl/debugfs.c create mode 100644 batctl/debugfs.h
diff --git a/batctl/Makefile b/batctl/Makefile index db375f7..bc591da 100644 --- a/batctl/Makefile +++ b/batctl/Makefile @@ -39,8 +39,8 @@ SRC_FILES = "(.c)|(.h)|(Makefile)|(INSTALL)|(LIESMICH)|(README EXTRA_MODULES_C := bisect.c EXTRA_MODULES_H := bisect.h
-SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c $(EXTRA_MODULES_C) -SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h $(EXTRA_MODULES_H) +SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) +SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) SRC_O = $(SRC_C:.c=.o)
PACKAGE_NAME = batctl diff --git a/batctl/debugfs.c b/batctl/debugfs.c new file mode 100644 index 0000000..cfe1254 --- /dev/null +++ b/batctl/debugfs.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2009 Clark Williams williams@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@cn.fujitsu.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "debugfs.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <linux/magic.h> +#include <sys/vfs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef DEBUGFS_MAGIC +#define DEBUGFS_MAGIC 0x64626720 +#endif + +static int debugfs_premounted; +static char debugfs_mountpoint[MAX_PATH+1]; + +static const char *debugfs_known_mountpoints[] = { + "/sys/kernel/debug/", + "/debug/", + 0, +}; + +/* use this to force a umount */ +void debugfs_force_cleanup(void) +{ + debugfs_find_mountpoint(); + debugfs_premounted = 0; + debugfs_umount(); +} + +/* construct a full path to a debugfs element */ +int debugfs_make_path(const char *element, char *buffer, int size) +{ + int len; + + if (strlen(debugfs_mountpoint) == 0) { + buffer[0] = '\0'; + return -1; + } + + len = strlen(debugfs_mountpoint) + strlen(element) + 1; + if (len >= size) + return len+1; + + snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element); + return 0; +} + +static int debugfs_found; + +/* find the path to the mounted debugfs */ +const char *debugfs_find_mountpoint(void) +{ + const char **ptr; + char type[100]; + FILE *fp; + + if (debugfs_found) + return (const char *) debugfs_mountpoint; + + ptr = debugfs_known_mountpoints; + while (*ptr) { + if (debugfs_valid_mountpoint(*ptr) == 0) { + debugfs_found = 1; + strcpy(debugfs_mountpoint, *ptr); + return debugfs_mountpoint; + } + ptr++; + } + + /* give up and parse /proc/mounts */ + fp = fopen("/proc/mounts", "r"); + if (fp == NULL) { + printf("Error - can't open /proc/mounts for read: %s\n", + strerror(errno)); + return NULL; + } + + while (fscanf(fp, "%*s %" + STR(MAX_PATH) + "s %99s %*s %*d %*d\n", + debugfs_mountpoint, type) == 2) { + if (strcmp(type, "debugfs") == 0) + break; + } + fclose(fp); + + if (strcmp(type, "debugfs") != 0) + return NULL; + + debugfs_found = 1; + + return debugfs_mountpoint; +} + +/* verify that a mountpoint is actually a debugfs instance */ + +int debugfs_valid_mountpoint(const char *debugfs) +{ + struct statfs st_fs; + + if (statfs(debugfs, &st_fs) < 0) + return -ENOENT; + else if (st_fs.f_type != (long) DEBUGFS_MAGIC) + return -ENOENT; + + return 0; +} + + +int debugfs_valid_entry(const char *path) +{ + struct stat st; + + if (stat(path, &st)) + return -errno; + + return 0; +} + +/* mount the debugfs somewhere if it's not mounted */ + +char *debugfs_mount(const char *mountpoint) +{ + /* see if it's already mounted */ + if (debugfs_find_mountpoint()) { + debugfs_premounted = 1; + return debugfs_mountpoint; + } + + /* if not mounted and no argument */ + if (mountpoint == NULL) + mountpoint = "/sys/kernel/debug"; + + if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) + return NULL; + + /* save the mountpoint */ + strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint)); + debugfs_found = 1; + + return debugfs_mountpoint; +} + +/* umount the debugfs */ + +int debugfs_umount(void) +{ + char umountcmd[128]; + int ret; + + /* if it was already mounted, leave it */ + if (debugfs_premounted) + return 0; + + /* make sure it's a valid mount point */ + ret = debugfs_valid_mountpoint(debugfs_mountpoint); + if (ret) + return ret; + + snprintf(umountcmd, sizeof(umountcmd), + "/bin/umount %s", debugfs_mountpoint); + return system(umountcmd); +} + +int debugfs_write(const char *entry, const char *value) +{ + char path[MAX_PATH+1]; + int ret, count; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* get how many chars we're going to write */ + count = strlen(value); + + /* open the debugfs entry */ + fd = open(path, O_RDWR); + if (fd < 0) + return -errno; + + while (count > 0) { + /* write it */ + ret = write(fd, value, count); + if (ret <= 0) { + if (ret == EAGAIN) + continue; + close(fd); + return -errno; + } + count -= ret; + } + + /* close it */ + close(fd); + + /* return success */ + return 0; +} + +/* + * read a debugfs entry + * returns the number of chars read or a negative errno + */ +int debugfs_read(const char *entry, char *buffer, size_t size) +{ + char path[MAX_PATH+1]; + int ret; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* open the debugfs entry */ + fd = open(path, O_RDONLY); + if (fd < 0) + return -errno; + + do { + /* read it */ + ret = read(fd, buffer, size); + if (ret == 0) { + close(fd); + return EOF; + } + } while (ret < 0 && errno == EAGAIN); + + /* close it */ + close(fd); + + /* make *sure* there's a null character at the end */ + buffer[ret] = '\0'; + + /* return the number of chars read */ + return ret; +} diff --git a/batctl/debugfs.h b/batctl/debugfs.h new file mode 100644 index 0000000..45f6339 --- /dev/null +++ b/batctl/debugfs.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 Clark Williams williams@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@cn.fujitsu.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#ifndef __DEBUGFS_H__ +#define __DEBUGFS_H__ + +#include <sys/mount.h> +#include <string.h> + +#ifndef MAX_PATH +# define MAX_PATH 256 +#endif + +#ifndef STR +# define _STR(x) #x +# define STR(x) _STR(x) +#endif + +extern const char *debugfs_find_mountpoint(void); +extern int debugfs_valid_mountpoint(const char *debugfs); +extern int debugfs_valid_entry(const char *path); +extern char *debugfs_mount(const char *mountpoint); +extern int debugfs_umount(void); +extern int debugfs_write(const char *entry, const char *value); +extern int debugfs_read(const char *entry, char *buffer, size_t size); +extern void debugfs_force_cleanup(void); +extern int debugfs_make_path(const char *element, char *buffer, int size); + +#endif /* __DEBUGFS_H__ */ diff --git a/batctl/main.h b/batctl/main.h index 9c83a7e..2fe603e 100644 --- a/batctl/main.h +++ b/batctl/main.h @@ -23,4 +23,4 @@
#define SOURCE_VERSION "0.3.0-alpha" /*put exactly one distinct word inside the string like "0.3-pre-alpha" or "0.3-rc1" or "0.3" */
-#define BAT_DEVICE "/dev/batman-adv" +#define SOCKET_PATH "batman_adv/bat0/socket" diff --git a/batctl/ping.c b/batctl/ping.c index 0352870..9df5c07 100644 --- a/batctl/ping.c +++ b/batctl/ping.c @@ -35,6 +35,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
char is_aborted = 0; @@ -79,6 +80,8 @@ int ping(int argc, char **argv) float min = 0.0, max = 0.0, avg = 0.0; uint8_t last_rr_cur = 0, last_rr[BAT_RR_LEN][ETH_ALEN]; size_t packet_len; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hc:i:t:R")) != -1) { switch (optchar) { @@ -139,11 +142,19 @@ int ping(int argc, char **argv) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler);
- ping_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + ping_fd = open(icmp_socket, O_RDWR);
if (ping_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -177,7 +188,7 @@ int ping(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(ping_fd, (char *)&icmp_packet_out, packet_len) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
@@ -207,7 +218,7 @@ int ping(int argc, char **argv) read_len = read(ping_fd, (char *)&icmp_packet_in, packet_len);
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
diff --git a/batctl/traceroute.c b/batctl/traceroute.c index b9b838e..00fcd89 100644 --- a/batctl/traceroute.c +++ b/batctl/traceroute.c @@ -34,6 +34,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
#define TTL_MAX 50 @@ -59,6 +60,8 @@ int traceroute(int argc, char **argv) int ret = EXIT_FAILURE, res, trace_fd = 0, i; int found_args = 1, optchar, seq_counter = 0, read_opt = USE_BAT_HOSTS; double time_delta; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hn")) != -1) { switch (optchar) { @@ -99,11 +102,19 @@ int traceroute(int argc, char **argv)
mac_string = ether_ntoa_long(dst_mac);
- trace_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + trace_fd = open(icmp_socket, O_RDWR);
if (trace_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -123,7 +134,7 @@ int traceroute(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(trace_fd, (char *)&icmp_packet_out, sizeof(icmp_packet_out)) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }
@@ -149,7 +160,7 @@ int traceroute(int argc, char **argv) read_len = read(trace_fd, (char *)&icmp_packet_in, sizeof(icmp_packet_in));
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }
Files which represent more than a single attribute aren't allowed in sysfs. As we have some files which aren't essential and are lists or tables aggregated from data from different places inside batman-adv, we must place them in a filesystem without such a restriction.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- batman-adv-kernelland/bat_debugfs.c | 79 ++++++++++++++++++++ batman-adv-kernelland/bat_sysfs.c | 91 ----------------------- batman-adv-kernelland/gateway_client.c | 64 +++++----------- batman-adv-kernelland/gateway_client.h | 3 +- batman-adv-kernelland/main.h | 1 + batman-adv-kernelland/originator.c | 61 +++++----------- batman-adv-kernelland/originator.h | 3 +- batman-adv-kernelland/translation-table.c | 114 ++++++++++------------------- batman-adv-kernelland/translation-table.h | 6 +- batman-adv-kernelland/vis.c | 59 +++++---------- batman-adv-kernelland/vis.h | 3 +- 11 files changed, 181 insertions(+), 303 deletions(-)
diff --git a/batman-adv-kernelland/bat_debugfs.c b/batman-adv-kernelland/bat_debugfs.c index 19e7bee..9113601 100644 --- a/batman-adv-kernelland/bat_debugfs.c +++ b/batman-adv-kernelland/bat_debugfs.c @@ -34,6 +34,68 @@
static struct dentry *bat_debugfs;
+static int originators_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, orig_seq_print_text, net_dev); +} + +static int gateways_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, gw_client_seq_print_text, net_dev); +} + +static int transtable_global_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_global_seq_print_text, net_dev); +} + +static int transtable_local_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_local_seq_print_text, net_dev); +} + +static int vis_data_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, vis_seq_print_text, net_dev); +} + +struct bat_debuginfo { + struct attribute attr; + const struct file_operations fops; +}; + +#define BAT_DEBUGINFO(_name, _mode, _open) \ +struct bat_debuginfo bat_debuginfo_##_name = { \ + .attr = { .name = __stringify(_name), \ + .mode = _mode, }, \ + .fops = { .owner = THIS_MODULE, \ + .open = _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } \ +}; + +static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); +static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); +static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); +static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); +static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); + +static struct bat_debuginfo *mesh_debuginfos[] = { + &bat_debuginfo_originators, + &bat_debuginfo_gateways, + &bat_debuginfo_transtable_global, + &bat_debuginfo_transtable_local, + &bat_debuginfo_vis_data, + NULL, +}; + void debugfs_init(void) { bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); @@ -50,6 +112,8 @@ void debugfs_destroy(void) int debugfs_add_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); + struct bat_debuginfo **bat_debug; + struct dentry *file;
if (!bat_debugfs) goto out; @@ -60,7 +124,22 @@ int debugfs_add_meshif(struct net_device *dev)
bat_socket_setup(bat_priv);
+ for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) { + file = debugfs_create_file(((*bat_debug)->attr).name, + S_IFREG | ((*bat_debug)->attr).mode, + bat_priv->debug_dir, + dev, &(*bat_debug)->fops); + if (!file) { + printk(KERN_ERR "batman-adv:Can't add debugfs file: " + "%s/%s\n", dev->name, ((*bat_debug)->attr).name); + goto rem_attr; + } + } + return 0; +rem_attr: + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; out: return -ENOMEM; } diff --git a/batman-adv-kernelland/bat_sysfs.c b/batman-adv-kernelland/bat_sysfs.c index 7690368..a689aec 100644 --- a/batman-adv-kernelland/bat_sysfs.c +++ b/batman-adv-kernelland/bat_sysfs.c @@ -39,14 +39,6 @@ struct bat_attribute bat_attr_##_name = { \ .store = _store, \ };
-#define BAT_BIN_ATTR(_name, _mode, _read, _write) \ -struct bin_attribute bat_attr_##_name = { \ - .attr = { .name = __stringify(_name), \ - .mode = _mode, }, \ - .read = _read, \ - .write = _write, \ -}; - static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -305,77 +297,11 @@ static struct bat_attribute *mesh_attrs[] = { NULL, };
-static ssize_t transtable_local_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_local_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t transtable_global_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_global_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t originators_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return orig_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t gateways_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return gw_client_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t vis_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return vis_fill_buffer_text(net_dev, buff, count, off); -} - -static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL); -static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL); -static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL); -static BAT_BIN_ATTR(gateways, S_IRUGO, gateways_read, NULL); -static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL); - -static struct bin_attribute *mesh_bin_attrs[] = { - &bat_attr_transtable_local, - &bat_attr_transtable_global, - &bat_attr_originators, - &bat_attr_gateways, - &bat_attr_vis_data, - NULL, -}; - int sysfs_add_meshif(struct net_device *dev) { struct kobject *batif_kobject = &dev->dev.kobj; struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; int err;
/* FIXME: should be done in the general mesh setup @@ -411,21 +337,8 @@ int sysfs_add_meshif(struct net_device *dev) } }
- for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) { - err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr)); - if (err) { - printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", - dev->name, SYSFS_IF_MESH_SUBDIR, - ((*bin_attr)->attr).name); - goto rem_bin_attr; - } - } - return 0;
-rem_bin_attr: - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr)); rem_attr: for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); @@ -440,10 +353,6 @@ void sysfs_del_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; - - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); diff --git a/batman-adv-kernelland/gateway_client.c b/batman-adv-kernelland/gateway_client.c index a5e4f5f..552ef6f 100644 --- a/batman-adv-kernelland/gateway_client.c +++ b/batman-adv-kernelland/gateway_client.c @@ -317,8 +317,7 @@ void gw_node_list_free(void) spin_unlock(&gw_list_lock); }
-static int _write_buffer_text(unsigned char *buff, int bytes_written, - struct gw_node *gw_node) +static int _write_buffer_text(struct seq_file *seq, struct gw_node *gw_node) { int down, up; char gw_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; @@ -327,8 +326,7 @@ static int _write_buffer_text(unsigned char *buff, int bytes_written, addr_to_string(router_str, gw_node->orig_node->router->addr); gw_srv_class_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
- return sprintf(buff + bytes_written, - "%s %-17s (%3i) %17s [%10s]: %3i - %i%s/%i%s\n", + return seq_printf(seq, "%s %-17s (%3i) %17s [%10s]: %3i - %i%s/%i%s\n", (curr_gateway == gw_node ? "=>" : " "), gw_str, gw_node->orig_node->router->tq_avg, @@ -341,51 +339,38 @@ static int _write_buffer_text(unsigned char *buff, int bytes_written, (up > 2048 ? "MBit" : "KBit")); }
-int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int gw_client_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct gw_node *gw_node; - size_t hdr_len, tmp_len; - int bytes_written = 0, gw_count = 0; + int gw_count = 0;
rcu_read_lock(); if (!bat_priv->primary_if) { rcu_read_unlock();
- if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - please " - "specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - please " + "specify interfaces to enable it\n", + net_dev->name); }
if (bat_priv->primary_if->if_status != IF_ACTIVE) { rcu_read_unlock();
- if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " + return seq_printf(seq, "BATMAN mesh %s disabled - " "primary interface not active\n", net_dev->name); - - return 0; }
- hdr_len = sprintf(buff, " %-12s (%s/%i) %17s [%10s]: gw_class ... " - "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", - "Gateway", "#", TQ_MAX_VALUE, "Nexthop", - "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->dev, - bat_priv->primary_if->addr_str, - net_dev->name); + seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " + "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", + "Gateway", "#", TQ_MAX_VALUE, "Nexthop", + "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, + bat_priv->primary_if->dev, bat_priv->primary_if->addr_str, + net_dev->name); rcu_read_unlock();
- if (off < hdr_len) - bytes_written = hdr_len; - rcu_read_lock(); list_for_each_entry_rcu(gw_node, &gw_list, list) { if (gw_node->deleted) @@ -394,26 +379,15 @@ int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, if (!gw_node->orig_node->router) continue;
- if (count < bytes_written + (2 * ETH_STR_LEN) + 30) - break; - - tmp_len = _write_buffer_text(buff, bytes_written, gw_node); + _write_buffer_text(seq, gw_node); gw_count++; - - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; } rcu_read_unlock();
- if ((gw_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No gateways in range ...\n"); + if (gw_count == 0) + seq_printf(seq, "No gateways in range ...\n");
- return bytes_written; + return 0; }
bool gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) diff --git a/batman-adv-kernelland/gateway_client.h b/batman-adv-kernelland/gateway_client.h index 38dc142..6a71cee 100644 --- a/batman-adv-kernelland/gateway_client.h +++ b/batman-adv-kernelland/gateway_client.h @@ -27,6 +27,5 @@ void gw_node_update(struct orig_node *orig_node, uint8_t new_gwflags); void gw_node_delete(struct orig_node *orig_node); void gw_node_purge_deleted(void); void gw_node_list_free(void); -int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int gw_client_seq_print_text(struct seq_file *seq, void *offset); bool gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb); diff --git a/batman-adv-kernelland/main.h b/batman-adv-kernelland/main.h index 730343e..ef2cbfd 100644 --- a/batman-adv-kernelland/main.h +++ b/batman-adv-kernelland/main.h @@ -123,6 +123,7 @@ extern int bat_debug_type(int type); #include <linux/workqueue.h> /* workqueue */ #include <net/sock.h> /* struct sock */ #include <linux/jiffies.h> +#include <linux/seq_file.h> #include "types.h"
#ifndef REVISION_VERSION diff --git a/batman-adv-kernelland/originator.c b/batman-adv-kernelland/originator.c index 2c84f0d..28e35b6 100644 --- a/batman-adv-kernelland/originator.c +++ b/batman-adv-kernelland/originator.c @@ -284,38 +284,31 @@ void purge_orig(struct work_struct *work) start_purge_timer(); }
-ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int orig_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct orig_node *orig_node; struct neigh_node *neigh_node; - size_t hdr_len, tmp_len; - int batman_count = 0, bytes_written = 0; + int batman_count = 0; unsigned long flags; char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
if ((!bat_priv->primary_if) || (bat_priv->primary_if->if_status != IF_ACTIVE)) { - if (off > 0) - return 0; - if (!bat_priv->primary_if) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name);
- return sprintf(buff, - "BATMAN mesh %s " - "disabled - primary interface not active\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); }
rcu_read_lock(); - hdr_len = sprintf(buff, - " %-14s (%s/%i) %17s [%10s]: %20s " + seq_printf(seq, " %-14s (%s/%i) %17s [%10s]: %20s " "... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR, @@ -323,9 +316,6 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, net_dev->name); rcu_read_unlock();
- if (off < hdr_len) - bytes_written = hdr_len; - spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) { @@ -338,44 +328,29 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, if (orig_node->router->tq_avg == 0) continue;
- /* estimated line length */ - if (count < bytes_written + 200) - break; - addr_to_string(orig_str, orig_node->orig); addr_to_string(router_str, orig_node->router->addr);
- tmp_len = sprintf(buff + bytes_written, - "%-17s (%3i) %17s [%10s]:", - orig_str, orig_node->router->tq_avg, - router_str, - orig_node->router->if_incoming->dev); + seq_printf(seq, "%-17s (%3i) %17s [%10s]:", + orig_str, orig_node->router->tq_avg, router_str, + orig_node->router->if_incoming->dev);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { addr_to_string(orig_str, neigh_node->addr); - tmp_len += sprintf(buff + bytes_written + tmp_len, - " %17s (%3i)", orig_str, + seq_printf(seq, " %17s (%3i)", orig_str, neigh_node->tq_avg); }
- tmp_len += sprintf(buff + bytes_written + tmp_len, "\n"); - + seq_printf(seq, "\n"); batman_count++; - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; }
spin_unlock_irqrestore(&orig_hash_lock, flags);
- if ((batman_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No batman nodes in range ...\n"); + if ((batman_count == 0)) + seq_printf(seq, "No batman nodes in range ...\n");
- return bytes_written; + return 0; }
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) diff --git a/batman-adv-kernelland/originator.h b/batman-adv-kernelland/originator.h index afbc7c0..e91e8a1 100644 --- a/batman-adv-kernelland/originator.h +++ b/batman-adv-kernelland/originator.h @@ -28,7 +28,6 @@ struct orig_node *get_orig_node(uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming); -ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int orig_seq_print_text(struct seq_file *seq, void *offset); int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); diff --git a/batman-adv-kernelland/translation-table.c b/batman-adv-kernelland/translation-table.c index 12880d5..21425b0 100644 --- a/batman-adv-kernelland/translation-table.c +++ b/batman-adv-kernelland/translation-table.c @@ -161,59 +161,41 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len) return i; }
-int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_local_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_local_entry *hna_local_entry; HASHIT(hashit); - int bytes_written = 0; unsigned long flags; - size_t hdr_len;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Locally retrieved addresses (from %s) " - "announced via HNA:\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Locally retrieved addresses (from %s) " + "announced via HNA:\n", + net_dev->name);
+ /* BUG cannot take irqlock and then call function which may sleep */ spin_lock_irqsave(&hna_local_hash_lock, flags);
while (hash_iterate(hna_local_hash, &hashit)) { - hdr_len += 21; - - if (count < bytes_written + 22) - break; - - if (off >= hdr_len) - continue; - hna_local_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 22, - " * " MAC_FMT "\n", - hna_local_entry->addr[0], - hna_local_entry->addr[1], - hna_local_entry->addr[2], - hna_local_entry->addr[3], - hna_local_entry->addr[4], - hna_local_entry->addr[5]); + seq_printf(seq, " * " MAC_FMT "\n", + hna_local_entry->addr[0], + hna_local_entry->addr[1], + hna_local_entry->addr[2], + hna_local_entry->addr[3], + hna_local_entry->addr[4], + hna_local_entry->addr[5]); }
spin_unlock_irqrestore(&hna_local_hash_lock, flags); - return bytes_written; + return 0; }
static void _hna_local_del(void *data) @@ -379,64 +361,46 @@ void hna_global_add_orig(struct orig_node *orig_node, spin_unlock_irqrestore(&hna_global_hash_lock, flags); }
-int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_global_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_global_entry *hna_global_entry; HASHIT(hashit); - int bytes_written = 0; unsigned long flags; - size_t hdr_len;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Globally announced HNAs received via the mesh %s\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", + net_dev->name);
+ /* BUG cannot take irqlock and then call function which may sleep */ spin_lock_irqsave(&hna_global_hash_lock, flags);
while (hash_iterate(hna_global_hash, &hashit)) { - hdr_len += 43; - - if (count < bytes_written + 44) - break; - - if (off >= hdr_len) - continue; - hna_global_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 44, - " * " MAC_FMT " via " MAC_FMT "\n", - hna_global_entry->addr[0], - hna_global_entry->addr[1], - hna_global_entry->addr[2], - hna_global_entry->addr[3], - hna_global_entry->addr[4], - hna_global_entry->addr[5], - hna_global_entry->orig_node->orig[0], - hna_global_entry->orig_node->orig[1], - hna_global_entry->orig_node->orig[2], - hna_global_entry->orig_node->orig[3], - hna_global_entry->orig_node->orig[4], - hna_global_entry->orig_node->orig[5]); + seq_printf(seq, " * " MAC_FMT " via " MAC_FMT "\n", + hna_global_entry->addr[0], + hna_global_entry->addr[1], + hna_global_entry->addr[2], + hna_global_entry->addr[3], + hna_global_entry->addr[4], + hna_global_entry->addr[5], + hna_global_entry->orig_node->orig[0], + hna_global_entry->orig_node->orig[1], + hna_global_entry->orig_node->orig[2], + hna_global_entry->orig_node->orig[3], + hna_global_entry->orig_node->orig[4], + hna_global_entry->orig_node->orig[5]); }
spin_unlock_irqrestore(&hna_global_hash_lock, flags); - return bytes_written; + return 0; }
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, diff --git a/batman-adv-kernelland/translation-table.h b/batman-adv-kernelland/translation-table.h index 8f412fc..8b3429e 100644 --- a/batman-adv-kernelland/translation-table.h +++ b/batman-adv-kernelland/translation-table.h @@ -25,15 +25,13 @@ int hna_local_init(void); void hna_local_add(uint8_t *addr); void hna_local_remove(uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); -int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_local_seq_print_text(struct seq_file *seq, void *offset); void hna_local_purge(struct work_struct *work); void hna_local_free(void); int hna_global_init(void); void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); -int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_global_seq_print_text(struct seq_file *seq, void *offset); void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, char *orig_str); void hna_global_del_orig(struct orig_node *orig_node, char *message); diff --git a/batman-adv-kernelland/vis.c b/batman-adv-kernelland/vis.c index 6b719bd..cb811ad 100644 --- a/batman-adv-kernelland/vis.c +++ b/batman-adv-kernelland/vis.c @@ -124,52 +124,50 @@ static void vis_data_insert_interface(const uint8_t *interface, hlist_add_head(&entry->list, if_list); }
-static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) +static void vis_data_read_prim_sec(struct seq_file *seq, + struct hlist_head *if_list) { struct if_list_entry *entry; struct hlist_node *pos; char tmp_addr_str[ETH_STR_LEN]; - size_t len = 0;
hlist_for_each_entry(entry, pos, if_list, list) { if (entry->primary) - len += sprintf(buff + len, "PRIMARY, "); + seq_printf(seq, "PRIMARY, "); else { addr_to_string(tmp_addr_str, entry->addr); - len += sprintf(buff + len, "SEC %s, ", tmp_addr_str); + seq_printf(seq, "SEC %s, ", tmp_addr_str); } } - - return len; }
/* read an entry */ -static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, - uint8_t *src, bool primary) +static int vis_data_read_entry(struct seq_file *seq, + struct vis_info_entry *entry, + uint8_t *src, bool primary) { char to[40];
addr_to_string(to, entry->dest); if (primary && entry->quality == 0) - return sprintf(buff, "HNA %s, ", to); + return seq_printf(seq, "HNA %s, ", to); else if (compare_orig(entry->src, src)) - return sprintf(buff, "TQ %s %d, ", to, entry->quality); + return seq_printf(seq, "TQ %s %d, ", to, entry->quality);
return 0; }
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +ssize_t vis_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); struct vis_info *info; struct vis_info_entry *entries; + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; - size_t hdr_len, tmp_len; - int i, bytes_written = 0; + int i; char tmp_addr_str[ETH_STR_LEN]; unsigned long flags; int vis_server = atomic_read(&bat_priv->vis_mode); @@ -178,18 +176,13 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, (vis_server == VIS_TYPE_CLIENT_UPDATE)) return 0;
- hdr_len = 0; - + /* BUG cannot take irqlock and then call function which may sleep */ spin_lock_irqsave(&vis_hash_lock, flags); while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info));
- /* estimated line length */ - if (count < bytes_written + 200) - break; - for (i = 0; i < info->packet.entries; i++) { if (entries[i].quality == 0) continue; @@ -200,30 +193,18 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
hlist_for_each_entry(entry, pos, &vis_if_list, list) { addr_to_string(tmp_addr_str, entry->addr); - tmp_len = sprintf(buff + bytes_written, - "%s,", tmp_addr_str); + seq_printf(seq, "%s,", tmp_addr_str);
for (i = 0; i < info->packet.entries; i++) - tmp_len += vis_data_read_entry( - buff + bytes_written + tmp_len, - &entries[i], entry->addr, - entry->primary); + vis_data_read_entry(seq, &entries[i], + entry->addr, + entry->primary);
/* add primary/secondary records */ if (compare_orig(entry->addr, info->packet.vis_orig)) - tmp_len += vis_data_read_prim_sec( - buff + bytes_written + tmp_len, - &vis_if_list); + vis_data_read_prim_sec(seq, &vis_if_list);
- tmp_len += sprintf(buff + bytes_written + tmp_len, - "\n"); - - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; + seq_printf(seq, "\n"); }
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { @@ -233,7 +214,7 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, } spin_unlock_irqrestore(&vis_hash_lock, flags);
- return bytes_written; + return 0; }
/* add the info packet to the send list, if it was not diff --git a/batman-adv-kernelland/vis.h b/batman-adv-kernelland/vis.h index 9c1fd77..5f5751c 100644 --- a/batman-adv-kernelland/vis.h +++ b/batman-adv-kernelland/vis.h @@ -47,8 +47,7 @@ struct recvlist_node { extern struct hashtable_t *vis_hash; extern spinlock_t vis_hash_lock;
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +ssize_t vis_seq_print_text(struct seq_file *seq, void *offset); void receive_server_sync_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, int vis_info_len);
Files which represent more than a single attribute aren't allowed in sysfs. As we have some files which aren't essential and are lists or tables aggregated from data from different places inside batman-adv, we must place them in a filesystem without such a restriction.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- Just fixed a return type which created a compiler warning.
batman-adv-kernelland/bat_debugfs.c | 79 ++++++++++++++++++++ batman-adv-kernelland/bat_sysfs.c | 91 ----------------------- batman-adv-kernelland/gateway_client.c | 64 +++++----------- batman-adv-kernelland/gateway_client.h | 3 +- batman-adv-kernelland/main.h | 1 + batman-adv-kernelland/originator.c | 61 +++++----------- batman-adv-kernelland/originator.h | 3 +- batman-adv-kernelland/translation-table.c | 114 ++++++++++------------------- batman-adv-kernelland/translation-table.h | 6 +- batman-adv-kernelland/vis.c | 59 +++++---------- batman-adv-kernelland/vis.h | 3 +- 11 files changed, 181 insertions(+), 303 deletions(-)
diff --git a/batman-adv-kernelland/bat_debugfs.c b/batman-adv-kernelland/bat_debugfs.c index 19e7bee..9113601 100644 --- a/batman-adv-kernelland/bat_debugfs.c +++ b/batman-adv-kernelland/bat_debugfs.c @@ -34,6 +34,68 @@
static struct dentry *bat_debugfs;
+static int originators_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, orig_seq_print_text, net_dev); +} + +static int gateways_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, gw_client_seq_print_text, net_dev); +} + +static int transtable_global_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_global_seq_print_text, net_dev); +} + +static int transtable_local_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_local_seq_print_text, net_dev); +} + +static int vis_data_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, vis_seq_print_text, net_dev); +} + +struct bat_debuginfo { + struct attribute attr; + const struct file_operations fops; +}; + +#define BAT_DEBUGINFO(_name, _mode, _open) \ +struct bat_debuginfo bat_debuginfo_##_name = { \ + .attr = { .name = __stringify(_name), \ + .mode = _mode, }, \ + .fops = { .owner = THIS_MODULE, \ + .open = _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } \ +}; + +static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); +static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); +static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); +static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); +static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); + +static struct bat_debuginfo *mesh_debuginfos[] = { + &bat_debuginfo_originators, + &bat_debuginfo_gateways, + &bat_debuginfo_transtable_global, + &bat_debuginfo_transtable_local, + &bat_debuginfo_vis_data, + NULL, +}; + void debugfs_init(void) { bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); @@ -50,6 +112,8 @@ void debugfs_destroy(void) int debugfs_add_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); + struct bat_debuginfo **bat_debug; + struct dentry *file;
if (!bat_debugfs) goto out; @@ -60,7 +124,22 @@ int debugfs_add_meshif(struct net_device *dev)
bat_socket_setup(bat_priv);
+ for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) { + file = debugfs_create_file(((*bat_debug)->attr).name, + S_IFREG | ((*bat_debug)->attr).mode, + bat_priv->debug_dir, + dev, &(*bat_debug)->fops); + if (!file) { + printk(KERN_ERR "batman-adv:Can't add debugfs file: " + "%s/%s\n", dev->name, ((*bat_debug)->attr).name); + goto rem_attr; + } + } + return 0; +rem_attr: + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; out: return -ENOMEM; } diff --git a/batman-adv-kernelland/bat_sysfs.c b/batman-adv-kernelland/bat_sysfs.c index 7690368..a689aec 100644 --- a/batman-adv-kernelland/bat_sysfs.c +++ b/batman-adv-kernelland/bat_sysfs.c @@ -39,14 +39,6 @@ struct bat_attribute bat_attr_##_name = { \ .store = _store, \ };
-#define BAT_BIN_ATTR(_name, _mode, _read, _write) \ -struct bin_attribute bat_attr_##_name = { \ - .attr = { .name = __stringify(_name), \ - .mode = _mode, }, \ - .read = _read, \ - .write = _write, \ -}; - static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -305,77 +297,11 @@ static struct bat_attribute *mesh_attrs[] = { NULL, };
-static ssize_t transtable_local_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_local_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t transtable_global_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_global_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t originators_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return orig_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t gateways_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return gw_client_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t vis_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return vis_fill_buffer_text(net_dev, buff, count, off); -} - -static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL); -static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL); -static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL); -static BAT_BIN_ATTR(gateways, S_IRUGO, gateways_read, NULL); -static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL); - -static struct bin_attribute *mesh_bin_attrs[] = { - &bat_attr_transtable_local, - &bat_attr_transtable_global, - &bat_attr_originators, - &bat_attr_gateways, - &bat_attr_vis_data, - NULL, -}; - int sysfs_add_meshif(struct net_device *dev) { struct kobject *batif_kobject = &dev->dev.kobj; struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; int err;
/* FIXME: should be done in the general mesh setup @@ -411,21 +337,8 @@ int sysfs_add_meshif(struct net_device *dev) } }
- for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) { - err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr)); - if (err) { - printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", - dev->name, SYSFS_IF_MESH_SUBDIR, - ((*bin_attr)->attr).name); - goto rem_bin_attr; - } - } - return 0;
-rem_bin_attr: - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr)); rem_attr: for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); @@ -440,10 +353,6 @@ void sysfs_del_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; - - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); diff --git a/batman-adv-kernelland/gateway_client.c b/batman-adv-kernelland/gateway_client.c index a5e4f5f..552ef6f 100644 --- a/batman-adv-kernelland/gateway_client.c +++ b/batman-adv-kernelland/gateway_client.c @@ -317,8 +317,7 @@ void gw_node_list_free(void) spin_unlock(&gw_list_lock); }
-static int _write_buffer_text(unsigned char *buff, int bytes_written, - struct gw_node *gw_node) +static int _write_buffer_text(struct seq_file *seq, struct gw_node *gw_node) { int down, up; char gw_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; @@ -327,8 +326,7 @@ static int _write_buffer_text(unsigned char *buff, int bytes_written, addr_to_string(router_str, gw_node->orig_node->router->addr); gw_srv_class_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
- return sprintf(buff + bytes_written, - "%s %-17s (%3i) %17s [%10s]: %3i - %i%s/%i%s\n", + return seq_printf(seq, "%s %-17s (%3i) %17s [%10s]: %3i - %i%s/%i%s\n", (curr_gateway == gw_node ? "=>" : " "), gw_str, gw_node->orig_node->router->tq_avg, @@ -341,51 +339,38 @@ static int _write_buffer_text(unsigned char *buff, int bytes_written, (up > 2048 ? "MBit" : "KBit")); }
-int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int gw_client_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct gw_node *gw_node; - size_t hdr_len, tmp_len; - int bytes_written = 0, gw_count = 0; + int gw_count = 0;
rcu_read_lock(); if (!bat_priv->primary_if) { rcu_read_unlock();
- if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - please " - "specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - please " + "specify interfaces to enable it\n", + net_dev->name); }
if (bat_priv->primary_if->if_status != IF_ACTIVE) { rcu_read_unlock();
- if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " + return seq_printf(seq, "BATMAN mesh %s disabled - " "primary interface not active\n", net_dev->name); - - return 0; }
- hdr_len = sprintf(buff, " %-12s (%s/%i) %17s [%10s]: gw_class ... " - "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", - "Gateway", "#", TQ_MAX_VALUE, "Nexthop", - "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->dev, - bat_priv->primary_if->addr_str, - net_dev->name); + seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " + "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", + "Gateway", "#", TQ_MAX_VALUE, "Nexthop", + "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, + bat_priv->primary_if->dev, bat_priv->primary_if->addr_str, + net_dev->name); rcu_read_unlock();
- if (off < hdr_len) - bytes_written = hdr_len; - rcu_read_lock(); list_for_each_entry_rcu(gw_node, &gw_list, list) { if (gw_node->deleted) @@ -394,26 +379,15 @@ int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, if (!gw_node->orig_node->router) continue;
- if (count < bytes_written + (2 * ETH_STR_LEN) + 30) - break; - - tmp_len = _write_buffer_text(buff, bytes_written, gw_node); + _write_buffer_text(seq, gw_node); gw_count++; - - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; } rcu_read_unlock();
- if ((gw_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No gateways in range ...\n"); + if (gw_count == 0) + seq_printf(seq, "No gateways in range ...\n");
- return bytes_written; + return 0; }
bool gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) diff --git a/batman-adv-kernelland/gateway_client.h b/batman-adv-kernelland/gateway_client.h index 38dc142..6a71cee 100644 --- a/batman-adv-kernelland/gateway_client.h +++ b/batman-adv-kernelland/gateway_client.h @@ -27,6 +27,5 @@ void gw_node_update(struct orig_node *orig_node, uint8_t new_gwflags); void gw_node_delete(struct orig_node *orig_node); void gw_node_purge_deleted(void); void gw_node_list_free(void); -int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int gw_client_seq_print_text(struct seq_file *seq, void *offset); bool gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb); diff --git a/batman-adv-kernelland/main.h b/batman-adv-kernelland/main.h index 730343e..ef2cbfd 100644 --- a/batman-adv-kernelland/main.h +++ b/batman-adv-kernelland/main.h @@ -123,6 +123,7 @@ extern int bat_debug_type(int type); #include <linux/workqueue.h> /* workqueue */ #include <net/sock.h> /* struct sock */ #include <linux/jiffies.h> +#include <linux/seq_file.h> #include "types.h"
#ifndef REVISION_VERSION diff --git a/batman-adv-kernelland/originator.c b/batman-adv-kernelland/originator.c index 2c84f0d..28e35b6 100644 --- a/batman-adv-kernelland/originator.c +++ b/batman-adv-kernelland/originator.c @@ -284,38 +284,31 @@ void purge_orig(struct work_struct *work) start_purge_timer(); }
-ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int orig_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct orig_node *orig_node; struct neigh_node *neigh_node; - size_t hdr_len, tmp_len; - int batman_count = 0, bytes_written = 0; + int batman_count = 0; unsigned long flags; char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
if ((!bat_priv->primary_if) || (bat_priv->primary_if->if_status != IF_ACTIVE)) { - if (off > 0) - return 0; - if (!bat_priv->primary_if) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name);
- return sprintf(buff, - "BATMAN mesh %s " - "disabled - primary interface not active\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); }
rcu_read_lock(); - hdr_len = sprintf(buff, - " %-14s (%s/%i) %17s [%10s]: %20s " + seq_printf(seq, " %-14s (%s/%i) %17s [%10s]: %20s " "... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR, @@ -323,9 +316,6 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, net_dev->name); rcu_read_unlock();
- if (off < hdr_len) - bytes_written = hdr_len; - spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) { @@ -338,44 +328,29 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, if (orig_node->router->tq_avg == 0) continue;
- /* estimated line length */ - if (count < bytes_written + 200) - break; - addr_to_string(orig_str, orig_node->orig); addr_to_string(router_str, orig_node->router->addr);
- tmp_len = sprintf(buff + bytes_written, - "%-17s (%3i) %17s [%10s]:", - orig_str, orig_node->router->tq_avg, - router_str, - orig_node->router->if_incoming->dev); + seq_printf(seq, "%-17s (%3i) %17s [%10s]:", + orig_str, orig_node->router->tq_avg, router_str, + orig_node->router->if_incoming->dev);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { addr_to_string(orig_str, neigh_node->addr); - tmp_len += sprintf(buff + bytes_written + tmp_len, - " %17s (%3i)", orig_str, + seq_printf(seq, " %17s (%3i)", orig_str, neigh_node->tq_avg); }
- tmp_len += sprintf(buff + bytes_written + tmp_len, "\n"); - + seq_printf(seq, "\n"); batman_count++; - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; }
spin_unlock_irqrestore(&orig_hash_lock, flags);
- if ((batman_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No batman nodes in range ...\n"); + if ((batman_count == 0)) + seq_printf(seq, "No batman nodes in range ...\n");
- return bytes_written; + return 0; }
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) diff --git a/batman-adv-kernelland/originator.h b/batman-adv-kernelland/originator.h index afbc7c0..e91e8a1 100644 --- a/batman-adv-kernelland/originator.h +++ b/batman-adv-kernelland/originator.h @@ -28,7 +28,6 @@ struct orig_node *get_orig_node(uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming); -ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int orig_seq_print_text(struct seq_file *seq, void *offset); int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); diff --git a/batman-adv-kernelland/translation-table.c b/batman-adv-kernelland/translation-table.c index 12880d5..21425b0 100644 --- a/batman-adv-kernelland/translation-table.c +++ b/batman-adv-kernelland/translation-table.c @@ -161,59 +161,41 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len) return i; }
-int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_local_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_local_entry *hna_local_entry; HASHIT(hashit); - int bytes_written = 0; unsigned long flags; - size_t hdr_len;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Locally retrieved addresses (from %s) " - "announced via HNA:\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Locally retrieved addresses (from %s) " + "announced via HNA:\n", + net_dev->name);
+ /* BUG cannot take irqlock and then call function which may sleep */ spin_lock_irqsave(&hna_local_hash_lock, flags);
while (hash_iterate(hna_local_hash, &hashit)) { - hdr_len += 21; - - if (count < bytes_written + 22) - break; - - if (off >= hdr_len) - continue; - hna_local_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 22, - " * " MAC_FMT "\n", - hna_local_entry->addr[0], - hna_local_entry->addr[1], - hna_local_entry->addr[2], - hna_local_entry->addr[3], - hna_local_entry->addr[4], - hna_local_entry->addr[5]); + seq_printf(seq, " * " MAC_FMT "\n", + hna_local_entry->addr[0], + hna_local_entry->addr[1], + hna_local_entry->addr[2], + hna_local_entry->addr[3], + hna_local_entry->addr[4], + hna_local_entry->addr[5]); }
spin_unlock_irqrestore(&hna_local_hash_lock, flags); - return bytes_written; + return 0; }
static void _hna_local_del(void *data) @@ -379,64 +361,46 @@ void hna_global_add_orig(struct orig_node *orig_node, spin_unlock_irqrestore(&hna_global_hash_lock, flags); }
-int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_global_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_global_entry *hna_global_entry; HASHIT(hashit); - int bytes_written = 0; unsigned long flags; - size_t hdr_len;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Globally announced HNAs received via the mesh %s\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", + net_dev->name);
+ /* BUG cannot take irqlock and then call function which may sleep */ spin_lock_irqsave(&hna_global_hash_lock, flags);
while (hash_iterate(hna_global_hash, &hashit)) { - hdr_len += 43; - - if (count < bytes_written + 44) - break; - - if (off >= hdr_len) - continue; - hna_global_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 44, - " * " MAC_FMT " via " MAC_FMT "\n", - hna_global_entry->addr[0], - hna_global_entry->addr[1], - hna_global_entry->addr[2], - hna_global_entry->addr[3], - hna_global_entry->addr[4], - hna_global_entry->addr[5], - hna_global_entry->orig_node->orig[0], - hna_global_entry->orig_node->orig[1], - hna_global_entry->orig_node->orig[2], - hna_global_entry->orig_node->orig[3], - hna_global_entry->orig_node->orig[4], - hna_global_entry->orig_node->orig[5]); + seq_printf(seq, " * " MAC_FMT " via " MAC_FMT "\n", + hna_global_entry->addr[0], + hna_global_entry->addr[1], + hna_global_entry->addr[2], + hna_global_entry->addr[3], + hna_global_entry->addr[4], + hna_global_entry->addr[5], + hna_global_entry->orig_node->orig[0], + hna_global_entry->orig_node->orig[1], + hna_global_entry->orig_node->orig[2], + hna_global_entry->orig_node->orig[3], + hna_global_entry->orig_node->orig[4], + hna_global_entry->orig_node->orig[5]); }
spin_unlock_irqrestore(&hna_global_hash_lock, flags); - return bytes_written; + return 0; }
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, diff --git a/batman-adv-kernelland/translation-table.h b/batman-adv-kernelland/translation-table.h index 8f412fc..8b3429e 100644 --- a/batman-adv-kernelland/translation-table.h +++ b/batman-adv-kernelland/translation-table.h @@ -25,15 +25,13 @@ int hna_local_init(void); void hna_local_add(uint8_t *addr); void hna_local_remove(uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); -int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_local_seq_print_text(struct seq_file *seq, void *offset); void hna_local_purge(struct work_struct *work); void hna_local_free(void); int hna_global_init(void); void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); -int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_global_seq_print_text(struct seq_file *seq, void *offset); void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, char *orig_str); void hna_global_del_orig(struct orig_node *orig_node, char *message); diff --git a/batman-adv-kernelland/vis.c b/batman-adv-kernelland/vis.c index 6b719bd..ab5d76a 100644 --- a/batman-adv-kernelland/vis.c +++ b/batman-adv-kernelland/vis.c @@ -124,52 +124,50 @@ static void vis_data_insert_interface(const uint8_t *interface, hlist_add_head(&entry->list, if_list); }
-static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) +static void vis_data_read_prim_sec(struct seq_file *seq, + struct hlist_head *if_list) { struct if_list_entry *entry; struct hlist_node *pos; char tmp_addr_str[ETH_STR_LEN]; - size_t len = 0;
hlist_for_each_entry(entry, pos, if_list, list) { if (entry->primary) - len += sprintf(buff + len, "PRIMARY, "); + seq_printf(seq, "PRIMARY, "); else { addr_to_string(tmp_addr_str, entry->addr); - len += sprintf(buff + len, "SEC %s, ", tmp_addr_str); + seq_printf(seq, "SEC %s, ", tmp_addr_str); } } - - return len; }
/* read an entry */ -static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, - uint8_t *src, bool primary) +static int vis_data_read_entry(struct seq_file *seq, + struct vis_info_entry *entry, + uint8_t *src, bool primary) { char to[40];
addr_to_string(to, entry->dest); if (primary && entry->quality == 0) - return sprintf(buff, "HNA %s, ", to); + return seq_printf(seq, "HNA %s, ", to); else if (compare_orig(entry->src, src)) - return sprintf(buff, "TQ %s %d, ", to, entry->quality); + return seq_printf(seq, "TQ %s %d, ", to, entry->quality);
return 0; }
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int vis_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); struct vis_info *info; struct vis_info_entry *entries; + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; - size_t hdr_len, tmp_len; - int i, bytes_written = 0; + int i; char tmp_addr_str[ETH_STR_LEN]; unsigned long flags; int vis_server = atomic_read(&bat_priv->vis_mode); @@ -178,18 +176,13 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, (vis_server == VIS_TYPE_CLIENT_UPDATE)) return 0;
- hdr_len = 0; - + /* BUG cannot take irqlock and then call function which may sleep */ spin_lock_irqsave(&vis_hash_lock, flags); while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info));
- /* estimated line length */ - if (count < bytes_written + 200) - break; - for (i = 0; i < info->packet.entries; i++) { if (entries[i].quality == 0) continue; @@ -200,30 +193,18 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
hlist_for_each_entry(entry, pos, &vis_if_list, list) { addr_to_string(tmp_addr_str, entry->addr); - tmp_len = sprintf(buff + bytes_written, - "%s,", tmp_addr_str); + seq_printf(seq, "%s,", tmp_addr_str);
for (i = 0; i < info->packet.entries; i++) - tmp_len += vis_data_read_entry( - buff + bytes_written + tmp_len, - &entries[i], entry->addr, - entry->primary); + vis_data_read_entry(seq, &entries[i], + entry->addr, + entry->primary);
/* add primary/secondary records */ if (compare_orig(entry->addr, info->packet.vis_orig)) - tmp_len += vis_data_read_prim_sec( - buff + bytes_written + tmp_len, - &vis_if_list); + vis_data_read_prim_sec(seq, &vis_if_list);
- tmp_len += sprintf(buff + bytes_written + tmp_len, - "\n"); - - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; + seq_printf(seq, "\n"); }
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { @@ -233,7 +214,7 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, } spin_unlock_irqrestore(&vis_hash_lock, flags);
- return bytes_written; + return 0; }
/* add the info packet to the send list, if it was not diff --git a/batman-adv-kernelland/vis.h b/batman-adv-kernelland/vis.h index 9c1fd77..5dd6521 100644 --- a/batman-adv-kernelland/vis.h +++ b/batman-adv-kernelland/vis.h @@ -47,8 +47,7 @@ struct recvlist_node { extern struct hashtable_t *vis_hash; extern spinlock_t vis_hash_lock;
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int vis_seq_print_text(struct seq_file *seq, void *offset); void receive_server_sync_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, int vis_info_len);
Files which represent more than a single attribute aren't allowed in sysfs. As we have some files which aren't essential and are lists or tables aggregated from data from different places inside batman-adv, we must place them in a filesystem without such a restriction.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- I've adjusted the output of transtable_global, vis_data and transtable_global to use an extra buffer inside the spin_lock_irqsave and do the actual printing outside the spinlock. Even if it is not the perfect solution, it should be good enough for now - aka doesn't create a deadlock on file reads.
batman-adv-kernelland/bat_debugfs.c | 79 +++++++++++++++ batman-adv-kernelland/bat_sysfs.c | 91 ----------------- batman-adv-kernelland/gateway_client.c | 64 ++++--------- batman-adv-kernelland/gateway_client.h | 3 +- batman-adv-kernelland/main.h | 1 + batman-adv-kernelland/originator.c | 61 ++++-------- batman-adv-kernelland/originator.h | 3 +- batman-adv-kernelland/translation-table.c | 151 +++++++++++++++-------------- batman-adv-kernelland/translation-table.h | 6 +- batman-adv-kernelland/vis.c | 111 +++++++++++++++------ batman-adv-kernelland/vis.h | 3 +- 11 files changed, 278 insertions(+), 295 deletions(-)
diff --git a/batman-adv-kernelland/bat_debugfs.c b/batman-adv-kernelland/bat_debugfs.c index 19e7bee..9113601 100644 --- a/batman-adv-kernelland/bat_debugfs.c +++ b/batman-adv-kernelland/bat_debugfs.c @@ -34,6 +34,68 @@
static struct dentry *bat_debugfs;
+static int originators_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, orig_seq_print_text, net_dev); +} + +static int gateways_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, gw_client_seq_print_text, net_dev); +} + +static int transtable_global_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_global_seq_print_text, net_dev); +} + +static int transtable_local_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_local_seq_print_text, net_dev); +} + +static int vis_data_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, vis_seq_print_text, net_dev); +} + +struct bat_debuginfo { + struct attribute attr; + const struct file_operations fops; +}; + +#define BAT_DEBUGINFO(_name, _mode, _open) \ +struct bat_debuginfo bat_debuginfo_##_name = { \ + .attr = { .name = __stringify(_name), \ + .mode = _mode, }, \ + .fops = { .owner = THIS_MODULE, \ + .open = _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } \ +}; + +static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); +static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); +static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); +static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); +static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); + +static struct bat_debuginfo *mesh_debuginfos[] = { + &bat_debuginfo_originators, + &bat_debuginfo_gateways, + &bat_debuginfo_transtable_global, + &bat_debuginfo_transtable_local, + &bat_debuginfo_vis_data, + NULL, +}; + void debugfs_init(void) { bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); @@ -50,6 +112,8 @@ void debugfs_destroy(void) int debugfs_add_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); + struct bat_debuginfo **bat_debug; + struct dentry *file;
if (!bat_debugfs) goto out; @@ -60,7 +124,22 @@ int debugfs_add_meshif(struct net_device *dev)
bat_socket_setup(bat_priv);
+ for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) { + file = debugfs_create_file(((*bat_debug)->attr).name, + S_IFREG | ((*bat_debug)->attr).mode, + bat_priv->debug_dir, + dev, &(*bat_debug)->fops); + if (!file) { + printk(KERN_ERR "batman-adv:Can't add debugfs file: " + "%s/%s\n", dev->name, ((*bat_debug)->attr).name); + goto rem_attr; + } + } + return 0; +rem_attr: + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; out: return -ENOMEM; } diff --git a/batman-adv-kernelland/bat_sysfs.c b/batman-adv-kernelland/bat_sysfs.c index 7690368..a689aec 100644 --- a/batman-adv-kernelland/bat_sysfs.c +++ b/batman-adv-kernelland/bat_sysfs.c @@ -39,14 +39,6 @@ struct bat_attribute bat_attr_##_name = { \ .store = _store, \ };
-#define BAT_BIN_ATTR(_name, _mode, _read, _write) \ -struct bin_attribute bat_attr_##_name = { \ - .attr = { .name = __stringify(_name), \ - .mode = _mode, }, \ - .read = _read, \ - .write = _write, \ -}; - static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -305,77 +297,11 @@ static struct bat_attribute *mesh_attrs[] = { NULL, };
-static ssize_t transtable_local_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_local_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t transtable_global_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_global_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t originators_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return orig_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t gateways_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return gw_client_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t vis_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return vis_fill_buffer_text(net_dev, buff, count, off); -} - -static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL); -static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL); -static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL); -static BAT_BIN_ATTR(gateways, S_IRUGO, gateways_read, NULL); -static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL); - -static struct bin_attribute *mesh_bin_attrs[] = { - &bat_attr_transtable_local, - &bat_attr_transtable_global, - &bat_attr_originators, - &bat_attr_gateways, - &bat_attr_vis_data, - NULL, -}; - int sysfs_add_meshif(struct net_device *dev) { struct kobject *batif_kobject = &dev->dev.kobj; struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; int err;
/* FIXME: should be done in the general mesh setup @@ -411,21 +337,8 @@ int sysfs_add_meshif(struct net_device *dev) } }
- for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) { - err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr)); - if (err) { - printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", - dev->name, SYSFS_IF_MESH_SUBDIR, - ((*bin_attr)->attr).name); - goto rem_bin_attr; - } - } - return 0;
-rem_bin_attr: - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr)); rem_attr: for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); @@ -440,10 +353,6 @@ void sysfs_del_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; - - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); diff --git a/batman-adv-kernelland/gateway_client.c b/batman-adv-kernelland/gateway_client.c index a5e4f5f..552ef6f 100644 --- a/batman-adv-kernelland/gateway_client.c +++ b/batman-adv-kernelland/gateway_client.c @@ -317,8 +317,7 @@ void gw_node_list_free(void) spin_unlock(&gw_list_lock); }
-static int _write_buffer_text(unsigned char *buff, int bytes_written, - struct gw_node *gw_node) +static int _write_buffer_text(struct seq_file *seq, struct gw_node *gw_node) { int down, up; char gw_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; @@ -327,8 +326,7 @@ static int _write_buffer_text(unsigned char *buff, int bytes_written, addr_to_string(router_str, gw_node->orig_node->router->addr); gw_srv_class_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
- return sprintf(buff + bytes_written, - "%s %-17s (%3i) %17s [%10s]: %3i - %i%s/%i%s\n", + return seq_printf(seq, "%s %-17s (%3i) %17s [%10s]: %3i - %i%s/%i%s\n", (curr_gateway == gw_node ? "=>" : " "), gw_str, gw_node->orig_node->router->tq_avg, @@ -341,51 +339,38 @@ static int _write_buffer_text(unsigned char *buff, int bytes_written, (up > 2048 ? "MBit" : "KBit")); }
-int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int gw_client_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct gw_node *gw_node; - size_t hdr_len, tmp_len; - int bytes_written = 0, gw_count = 0; + int gw_count = 0;
rcu_read_lock(); if (!bat_priv->primary_if) { rcu_read_unlock();
- if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - please " - "specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - please " + "specify interfaces to enable it\n", + net_dev->name); }
if (bat_priv->primary_if->if_status != IF_ACTIVE) { rcu_read_unlock();
- if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " + return seq_printf(seq, "BATMAN mesh %s disabled - " "primary interface not active\n", net_dev->name); - - return 0; }
- hdr_len = sprintf(buff, " %-12s (%s/%i) %17s [%10s]: gw_class ... " - "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", - "Gateway", "#", TQ_MAX_VALUE, "Nexthop", - "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->dev, - bat_priv->primary_if->addr_str, - net_dev->name); + seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " + "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", + "Gateway", "#", TQ_MAX_VALUE, "Nexthop", + "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, + bat_priv->primary_if->dev, bat_priv->primary_if->addr_str, + net_dev->name); rcu_read_unlock();
- if (off < hdr_len) - bytes_written = hdr_len; - rcu_read_lock(); list_for_each_entry_rcu(gw_node, &gw_list, list) { if (gw_node->deleted) @@ -394,26 +379,15 @@ int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, if (!gw_node->orig_node->router) continue;
- if (count < bytes_written + (2 * ETH_STR_LEN) + 30) - break; - - tmp_len = _write_buffer_text(buff, bytes_written, gw_node); + _write_buffer_text(seq, gw_node); gw_count++; - - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; } rcu_read_unlock();
- if ((gw_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No gateways in range ...\n"); + if (gw_count == 0) + seq_printf(seq, "No gateways in range ...\n");
- return bytes_written; + return 0; }
bool gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) diff --git a/batman-adv-kernelland/gateway_client.h b/batman-adv-kernelland/gateway_client.h index 38dc142..6a71cee 100644 --- a/batman-adv-kernelland/gateway_client.h +++ b/batman-adv-kernelland/gateway_client.h @@ -27,6 +27,5 @@ void gw_node_update(struct orig_node *orig_node, uint8_t new_gwflags); void gw_node_delete(struct orig_node *orig_node); void gw_node_purge_deleted(void); void gw_node_list_free(void); -int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int gw_client_seq_print_text(struct seq_file *seq, void *offset); bool gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb); diff --git a/batman-adv-kernelland/main.h b/batman-adv-kernelland/main.h index 730343e..ef2cbfd 100644 --- a/batman-adv-kernelland/main.h +++ b/batman-adv-kernelland/main.h @@ -123,6 +123,7 @@ extern int bat_debug_type(int type); #include <linux/workqueue.h> /* workqueue */ #include <net/sock.h> /* struct sock */ #include <linux/jiffies.h> +#include <linux/seq_file.h> #include "types.h"
#ifndef REVISION_VERSION diff --git a/batman-adv-kernelland/originator.c b/batman-adv-kernelland/originator.c index 2c84f0d..28e35b6 100644 --- a/batman-adv-kernelland/originator.c +++ b/batman-adv-kernelland/originator.c @@ -284,38 +284,31 @@ void purge_orig(struct work_struct *work) start_purge_timer(); }
-ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int orig_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct orig_node *orig_node; struct neigh_node *neigh_node; - size_t hdr_len, tmp_len; - int batman_count = 0, bytes_written = 0; + int batman_count = 0; unsigned long flags; char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
if ((!bat_priv->primary_if) || (bat_priv->primary_if->if_status != IF_ACTIVE)) { - if (off > 0) - return 0; - if (!bat_priv->primary_if) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name);
- return sprintf(buff, - "BATMAN mesh %s " - "disabled - primary interface not active\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); }
rcu_read_lock(); - hdr_len = sprintf(buff, - " %-14s (%s/%i) %17s [%10s]: %20s " + seq_printf(seq, " %-14s (%s/%i) %17s [%10s]: %20s " "... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR, @@ -323,9 +316,6 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, net_dev->name); rcu_read_unlock();
- if (off < hdr_len) - bytes_written = hdr_len; - spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) { @@ -338,44 +328,29 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, if (orig_node->router->tq_avg == 0) continue;
- /* estimated line length */ - if (count < bytes_written + 200) - break; - addr_to_string(orig_str, orig_node->orig); addr_to_string(router_str, orig_node->router->addr);
- tmp_len = sprintf(buff + bytes_written, - "%-17s (%3i) %17s [%10s]:", - orig_str, orig_node->router->tq_avg, - router_str, - orig_node->router->if_incoming->dev); + seq_printf(seq, "%-17s (%3i) %17s [%10s]:", + orig_str, orig_node->router->tq_avg, router_str, + orig_node->router->if_incoming->dev);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { addr_to_string(orig_str, neigh_node->addr); - tmp_len += sprintf(buff + bytes_written + tmp_len, - " %17s (%3i)", orig_str, + seq_printf(seq, " %17s (%3i)", orig_str, neigh_node->tq_avg); }
- tmp_len += sprintf(buff + bytes_written + tmp_len, "\n"); - + seq_printf(seq, "\n"); batman_count++; - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; }
spin_unlock_irqrestore(&orig_hash_lock, flags);
- if ((batman_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No batman nodes in range ...\n"); + if ((batman_count == 0)) + seq_printf(seq, "No batman nodes in range ...\n");
- return bytes_written; + return 0; }
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) diff --git a/batman-adv-kernelland/originator.h b/batman-adv-kernelland/originator.h index afbc7c0..e91e8a1 100644 --- a/batman-adv-kernelland/originator.h +++ b/batman-adv-kernelland/originator.h @@ -28,7 +28,6 @@ struct orig_node *get_orig_node(uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming); -ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int orig_seq_print_text(struct seq_file *seq, void *offset); int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); diff --git a/batman-adv-kernelland/translation-table.c b/batman-adv-kernelland/translation-table.c index 12880d5..009789e 100644 --- a/batman-adv-kernelland/translation-table.c +++ b/batman-adv-kernelland/translation-table.c @@ -161,59 +161,59 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len) return i; }
-int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_local_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_local_entry *hna_local_entry; HASHIT(hashit); - int bytes_written = 0; + HASHIT(hashit_count); unsigned long flags; - size_t hdr_len; + size_t buf_size, pos; + char *buff;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Locally retrieved addresses (from %s) " - "announced via HNA:\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Locally retrieved addresses (from %s) " + "announced via HNA:\n", + net_dev->name);
spin_lock_irqsave(&hna_local_hash_lock, flags);
+ buf_size = 1; + /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ + while (hash_iterate(hna_local_hash, &hashit_count)) + buf_size += 21; + + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + pos = 0; + while (hash_iterate(hna_local_hash, &hashit)) { - hdr_len += 21; - - if (count < bytes_written + 22) - break; - - if (off >= hdr_len) - continue; - hna_local_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 22, - " * " MAC_FMT "\n", - hna_local_entry->addr[0], - hna_local_entry->addr[1], - hna_local_entry->addr[2], - hna_local_entry->addr[3], - hna_local_entry->addr[4], - hna_local_entry->addr[5]); + pos += snprintf(buff + pos, 22, " * " MAC_FMT "\n", + hna_local_entry->addr[0], + hna_local_entry->addr[1], + hna_local_entry->addr[2], + hna_local_entry->addr[3], + hna_local_entry->addr[4], + hna_local_entry->addr[5]); }
spin_unlock_irqrestore(&hna_local_hash_lock, flags); - return bytes_written; + + seq_printf(seq, "%s", buff); + kfree(buff); + return 0; }
static void _hna_local_del(void *data) @@ -379,64 +379,65 @@ void hna_global_add_orig(struct orig_node *orig_node, spin_unlock_irqrestore(&hna_global_hash_lock, flags); }
-int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_global_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_global_entry *hna_global_entry; HASHIT(hashit); - int bytes_written = 0; + HASHIT(hashit_count); unsigned long flags; - size_t hdr_len; + size_t buf_size, pos; + char *buff;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Globally announced HNAs received via the mesh %s\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", + net_dev->name);
spin_lock_irqsave(&hna_global_hash_lock, flags);
+ buf_size = 1; + /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ + while (hash_iterate(hna_global_hash, &hashit_count)) + buf_size += 43; + + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + pos = 0; + while (hash_iterate(hna_global_hash, &hashit)) { - hdr_len += 43; - - if (count < bytes_written + 44) - break; - - if (off >= hdr_len) - continue; - hna_global_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 44, - " * " MAC_FMT " via " MAC_FMT "\n", - hna_global_entry->addr[0], - hna_global_entry->addr[1], - hna_global_entry->addr[2], - hna_global_entry->addr[3], - hna_global_entry->addr[4], - hna_global_entry->addr[5], - hna_global_entry->orig_node->orig[0], - hna_global_entry->orig_node->orig[1], - hna_global_entry->orig_node->orig[2], - hna_global_entry->orig_node->orig[3], - hna_global_entry->orig_node->orig[4], - hna_global_entry->orig_node->orig[5]); + pos += snprintf(buff + pos, 44, + " * " MAC_FMT " via " MAC_FMT "\n", + hna_global_entry->addr[0], + hna_global_entry->addr[1], + hna_global_entry->addr[2], + hna_global_entry->addr[3], + hna_global_entry->addr[4], + hna_global_entry->addr[5], + hna_global_entry->orig_node->orig[0], + hna_global_entry->orig_node->orig[1], + hna_global_entry->orig_node->orig[2], + hna_global_entry->orig_node->orig[3], + hna_global_entry->orig_node->orig[4], + hna_global_entry->orig_node->orig[5]); }
spin_unlock_irqrestore(&hna_global_hash_lock, flags); - return bytes_written; + + seq_printf(seq, "%s", buff); + kfree(buff); + return 0; }
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, diff --git a/batman-adv-kernelland/translation-table.h b/batman-adv-kernelland/translation-table.h index 8f412fc..8b3429e 100644 --- a/batman-adv-kernelland/translation-table.h +++ b/batman-adv-kernelland/translation-table.h @@ -25,15 +25,13 @@ int hna_local_init(void); void hna_local_add(uint8_t *addr); void hna_local_remove(uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); -int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_local_seq_print_text(struct seq_file *seq, void *offset); void hna_local_purge(struct work_struct *work); void hna_local_free(void); int hna_global_init(void); void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); -int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_global_seq_print_text(struct seq_file *seq, void *offset); void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, char *orig_str); void hna_global_del_orig(struct orig_node *orig_node, char *message); diff --git a/batman-adv-kernelland/vis.c b/batman-adv-kernelland/vis.c index 6b719bd..68ee903 100644 --- a/batman-adv-kernelland/vis.c +++ b/batman-adv-kernelland/vis.c @@ -116,7 +116,7 @@ static void vis_data_insert_interface(const uint8_t *interface, }
/* its a new address, add it to the list */ - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) return; memcpy(entry->addr, interface, ETH_ALEN); @@ -143,12 +143,29 @@ static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) return len; }
+static size_t vis_data_count_prim_sec(struct hlist_head *if_list) +{ + struct if_list_entry *entry; + struct hlist_node *pos; + size_t count = 0; + + hlist_for_each_entry(entry, pos, if_list, list) { + if (entry->primary) + count += 9; + else + count += 23; + } + + return count; +} + /* read an entry */ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, uint8_t *src, bool primary) { - char to[40]; + char to[18];
+ /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ addr_to_string(to, entry->dest); if (primary && entry->quality == 0) return sprintf(buff, "HNA %s, ", to); @@ -158,38 +175,74 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, return 0; }
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int vis_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + HASHIT(hashit_count); struct vis_info *info; struct vis_info_entry *entries; + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; - size_t hdr_len, tmp_len; - int i, bytes_written = 0; + int i; char tmp_addr_str[ETH_STR_LEN]; unsigned long flags; int vis_server = atomic_read(&bat_priv->vis_mode); + size_t buff_pos, buf_size; + char *buff;
if ((!bat_priv->primary_if) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) return 0;
- hdr_len = 0; - + buf_size = 1; + /* Estimate length */ spin_lock_irqsave(&vis_hash_lock, flags); + while (hash_iterate(vis_hash, &hashit_count)) { + info = hashit_count.bucket->data; + entries = (struct vis_info_entry *) + ((char *)info + sizeof(struct vis_info)); + + for (i = 0; i < info->packet.entries; i++) { + if (entries[i].quality == 0) + continue; + vis_data_insert_interface(entries[i].src, &vis_if_list, + compare_orig(entries[i].src, + info->packet.vis_orig)); + } + + hlist_for_each_entry(entry, pos, &vis_if_list, list) { + buf_size += 18 + 26 * info->packet.entries; + + /* add primary/secondary records */ + if (compare_orig(entry->addr, info->packet.vis_orig)) + buf_size += + vis_data_count_prim_sec(&vis_if_list); + + buf_size += 1; + } + + hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { + hlist_del(&entry->list); + kfree(entry); + } + } + + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&vis_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + buff_pos = 0; + while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info));
- /* estimated line length */ - if (count < bytes_written + 200) - break; - for (i = 0; i < info->packet.entries; i++) { if (entries[i].quality == 0) continue; @@ -200,30 +253,22 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
hlist_for_each_entry(entry, pos, &vis_if_list, list) { addr_to_string(tmp_addr_str, entry->addr); - tmp_len = sprintf(buff + bytes_written, - "%s,", tmp_addr_str); + buff_pos += sprintf(buff + buff_pos, "%s,", + tmp_addr_str);
for (i = 0; i < info->packet.entries; i++) - tmp_len += vis_data_read_entry( - buff + bytes_written + tmp_len, - &entries[i], entry->addr, - entry->primary); + buff_pos += vis_data_read_entry(buff + buff_pos, + &entries[i], + entry->addr, + entry->primary);
/* add primary/secondary records */ if (compare_orig(entry->addr, info->packet.vis_orig)) - tmp_len += vis_data_read_prim_sec( - buff + bytes_written + tmp_len, - &vis_if_list); + buff_pos += + vis_data_read_prim_sec(buff + buff_pos, + &vis_if_list);
- tmp_len += sprintf(buff + bytes_written + tmp_len, - "\n"); - - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; + buff_pos += sprintf(buff + buff_pos, "\n"); }
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { @@ -231,9 +276,13 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, kfree(entry); } } + spin_unlock_irqrestore(&vis_hash_lock, flags);
- return bytes_written; + seq_printf(seq, "%s", buff); + kfree(buff); + + return 0; }
/* add the info packet to the send list, if it was not diff --git a/batman-adv-kernelland/vis.h b/batman-adv-kernelland/vis.h index 9c1fd77..5dd6521 100644 --- a/batman-adv-kernelland/vis.h +++ b/batman-adv-kernelland/vis.h @@ -47,8 +47,7 @@ struct recvlist_node { extern struct hashtable_t *vis_hash; extern spinlock_t vis_hash_lock;
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int vis_seq_print_text(struct seq_file *seq, void *offset); void receive_server_sync_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, int vis_info_len);
batctl must read the tables exported by batman-adv from debugfs as the old files in /sys/class/net/bat0/mesh/ were removed to follow the sysfs guidelines.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- batctl/Makefile | 4 +- batctl/debug.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ batctl/debug.h | 34 ++++++++++++++++++ batctl/main.c | 9 +++-- batctl/sys.c | 60 -------------------------------- batctl/sys.h | 10 ----- batctl/vis.c | 20 ++++++----- 7 files changed, 155 insertions(+), 85 deletions(-) create mode 100644 batctl/debug.c create mode 100644 batctl/debug.h
diff --git a/batctl/Makefile b/batctl/Makefile index bc591da..985f1d8 100644 --- a/batctl/Makefile +++ b/batctl/Makefile @@ -39,8 +39,8 @@ SRC_FILES = "(.c)|(.h)|(Makefile)|(INSTALL)|(LIESMICH)|(README EXTRA_MODULES_C := bisect.c EXTRA_MODULES_H := bisect.h
-SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) -SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) +SRC_C = main.c bat-hosts.c functions.c sys.c debug.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) +SRC_H = main.h bat-hosts.h functions.h sys.h debug.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) SRC_O = $(SRC_C:.c=.o)
PACKAGE_NAME = batctl diff --git a/batctl/debug.c b/batctl/debug.c new file mode 100644 index 0000000..e8edb9d --- /dev/null +++ b/batctl/debug.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner lindner_marek@yahoo.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <dirent.h> + +#include "main.h" +#include "debug.h" +#include "debugfs.h" +#include "functions.h" + +void originators_usage(void) +{ + printf("Usage: batctl [options] originators \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the originator table continuously\n"); +} + +void trans_local_usage(void) +{ + printf("Usage: batctl [options] translocal \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the local translation table continuously\n"); +} + +void trans_global_usage(void) +{ + printf("Usage: batctl [options] transglobal \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the global translation table continuously\n"); +} + +void gateways_usage(void) +{ + printf("Usage: batctl [options] gateways \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the gateway server list continuously\n"); +} + +int handle_debug_table(int argc, char **argv, char *file_path, void table_usage(void)) +{ + int optchar, read_opt = USE_BAT_HOSTS; + char full_path[MAX_PATH+1]; + char *debugfs_mnt; + + while ((optchar = getopt(argc, argv, "hnw")) != -1) { + switch (optchar) { + case 'h': + table_usage(); + return EXIT_SUCCESS; + case 'n': + read_opt &= ~USE_BAT_HOSTS; + break; + case 'w': + read_opt |= CLR_CONT_READ; + break; + default: + table_usage(); + return EXIT_FAILURE; + } + } + + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + return EXIT_FAILURE; + } + + debugfs_make_path(DEBUG_BATIF_PATH "/", full_path, sizeof(full_path)); + return read_file(full_path, file_path, read_opt); +} \ No newline at end of file diff --git a/batctl/debug.h b/batctl/debug.h new file mode 100644 index 0000000..8b03b10 --- /dev/null +++ b/batctl/debug.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner lindner_marek@yahoo.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#define DEBUG_BATIF_PATH "batman_adv/bat0" +#define DEBUG_ORIGINATORS "originators" +#define DEBUG_TRANSTABLE_LOCAL "transtable_local" +#define DEBUG_TRANSTABLE_GLOBAL "transtable_global" +#define DEBUG_GATEWAYS "gateways" +#define DEBUG_VIS_DATA "vis_data" + +void originators_usage(void); +void trans_local_usage(void); +void trans_global_usage(void); +void gateways_usage(void); +int handle_debug_table(int argc, char **argv, char *file_path, void table_usage(void)); diff --git a/batctl/main.c b/batctl/main.c index 1cabcdd..19b889a 100644 --- a/batctl/main.c +++ b/batctl/main.c @@ -30,6 +30,7 @@
#include "main.h" #include "sys.h" +#include "debug.h" #include "ping.h" #include "traceroute.h" #include "tcpdump.h" @@ -102,15 +103,15 @@ int main(int argc, char **argv)
} else if ((strcmp(argv[1], "originators") == 0) || (strcmp(argv[1], "o") == 0)) {
- ret = handle_sys_table(argc - 1, argv + 1, SYS_ORIGINATORS, originators_usage); + ret = handle_debug_table(argc - 1, argv + 1, DEBUG_ORIGINATORS, originators_usage);
} else if ((strcmp(argv[1], "translocal") == 0) || (strcmp(argv[1], "tl") == 0)) {
- ret = handle_sys_table(argc - 1, argv + 1, SYS_TRANSTABLE_LOCAL, trans_local_usage); + ret = handle_debug_table(argc - 1, argv + 1, DEBUG_TRANSTABLE_LOCAL, trans_local_usage);
} else if ((strcmp(argv[1], "transglobal") == 0) || (strcmp(argv[1], "tg") == 0)) {
- ret = handle_sys_table(argc - 1, argv + 1, SYS_TRANSTABLE_GLOBAL, trans_global_usage); + ret = handle_debug_table(argc - 1, argv + 1, DEBUG_TRANSTABLE_GLOBAL, trans_global_usage);
} else if ((strcmp(argv[1], "loglevel") == 0) || (strcmp(argv[1], "ll") == 0)) {
@@ -138,7 +139,7 @@ int main(int argc, char **argv)
} else if ((strcmp(argv[1], "gateways") == 0) || (strcmp(argv[1], "gwl") == 0)) {
- ret = handle_sys_table(argc - 1, argv + 1, SYS_GATEWAYS, gateways_usage); + ret = handle_debug_table(argc - 1, argv + 1, DEBUG_GATEWAYS, gateways_usage);
} else if ((strcmp(argv[1], "aggregation") == 0) || (strcmp(argv[1], "ag") == 0)) {
diff --git a/batctl/sys.c b/batctl/sys.c index 4c4312a..a6bc781 100644 --- a/batctl/sys.c +++ b/batctl/sys.c @@ -242,66 +242,6 @@ out: return res; }
-void originators_usage(void) -{ - printf("Usage: batctl [options] originators \n"); - printf("options:\n"); - printf(" \t -h print this help\n"); - printf(" \t -n don't replace mac addresses with bat-host names\n"); - printf(" \t -w watch mode - refresh the originator table continuously\n"); -} - -void trans_local_usage(void) -{ - printf("Usage: batctl [options] translocal \n"); - printf("options:\n"); - printf(" \t -h print this help\n"); - printf(" \t -n don't replace mac addresses with bat-host names\n"); - printf(" \t -w watch mode - refresh the local translation table continuously\n"); -} - -void trans_global_usage(void) -{ - printf("Usage: batctl [options] transglobal \n"); - printf("options:\n"); - printf(" \t -h print this help\n"); - printf(" \t -n don't replace mac addresses with bat-host names\n"); - printf(" \t -w watch mode - refresh the global translation table continuously\n"); -} - -void gateways_usage(void) -{ - printf("Usage: batctl [options] gateways \n"); - printf("options:\n"); - printf(" \t -h print this help\n"); - printf(" \t -n don't replace mac addresses with bat-host names\n"); - printf(" \t -w watch mode - refresh the gateway server list continuously\n"); -} - -int handle_sys_table(int argc, char **argv, char *file_path, void table_usage(void)) -{ - int optchar, read_opt = USE_BAT_HOSTS; - - while ((optchar = getopt(argc, argv, "hnw")) != -1) { - switch (optchar) { - case 'h': - table_usage(); - return EXIT_SUCCESS; - case 'n': - read_opt &= ~USE_BAT_HOSTS; - break; - case 'w': - read_opt |= CLR_CONT_READ; - break; - default: - table_usage(); - return EXIT_FAILURE; - } - } - - return read_file(SYS_BATIF_PATH, file_path, read_opt); -} - void aggregation_usage(void) { printf("Usage: batctl [options] aggregation [0|1]\n"); diff --git a/batctl/sys.h b/batctl/sys.h index 6d78622..622f110 100644 --- a/batctl/sys.h +++ b/batctl/sys.h @@ -24,31 +24,21 @@ #define SYS_BATIF_PATH "/sys/class/net/bat0/mesh/" #define SYS_LOG_LEVEL "parameters/debug" #define SYS_LOG "log" -#define SYS_ORIGINATORS "originators" -#define SYS_TRANSTABLE_LOCAL "transtable_local" -#define SYS_TRANSTABLE_GLOBAL "transtable_global" #define SYS_AGGR "aggregate_ogm" #define SYS_BONDING "bonding" #define SYS_GW_MODE "gw_mode" -#define SYS_GATEWAYS "gateways" #define SYS_VIS_MODE "vis_mode" -#define SYS_VIS_DATA "vis_data" #define SYS_ORIG_INTERVAL "orig_interval" #define SYS_IFACE_PATH "/sys/class/net" #define SYS_MESH_IFACE_FMT SYS_IFACE_PATH"/%s/batman_adv/mesh_iface" #define SYS_IFACE_STATUS_FMT SYS_IFACE_PATH"/%s/batman_adv/iface_status"
-void originators_usage(void); -void trans_local_usage(void); -void trans_global_usage(void); void aggregation_usage(void); void bonding_usage(void); void gw_mode_usage(void); -void gateways_usage(void); void vis_mode_usage(void); void orig_interval_usage(void); int log_print(int argc, char **argv); int interface(int argc, char **argv); int handle_loglevel(int argc, char **argv); -int handle_sys_table(int argc, char **argv, char *file_path, void table_usage(void)); int handle_sys_setting(int argc, char **argv, char *file_path, void setting_usage(void)); diff --git a/batctl/vis.c b/batctl/vis.c index 9565329..c06beb1 100644 --- a/batctl/vis.c +++ b/batctl/vis.c @@ -29,7 +29,8 @@ #include "vis.h" #include "functions.h" #include "bat-hosts.h" -#include "sys.h" +#include "debug.h" +#include "debugfs.h"
#define TQ_MAX_VALUE 255
@@ -55,9 +56,9 @@ static bool with_names = true;
static void usage(void) { - printf("batctl vis dot {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); + printf("batctl vis_data dot {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); printf("or\n"); - printf("batctl vis json {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); + printf("batctl vis_data json {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); }
static void dot_print_tq(char *orig, char *from, const long tq) @@ -163,15 +164,16 @@ const struct funcs json_funcs = { json_print_tq,
static FILE *open_vis(void) { - char full_path[500]; + char full_path[MAX_PATH+1]; + char *debugfs_mnt;
- if (check_proc_dir("/proc") != EXIT_SUCCESS) + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); return NULL; + }
- strncpy(full_path, SYS_BATIF_PATH, strlen(SYS_BATIF_PATH)); - full_path[strlen(SYS_BATIF_PATH)] = '\0'; - strncat(full_path, SYS_VIS_DATA, - sizeof(full_path) - strlen(full_path)); + debugfs_make_path(DEBUG_BATIF_PATH "/" DEBUG_VIS_DATA, full_path, sizeof(full_path));
return fopen(full_path, "r"); }
Sven Eckelmann wrote:
The patches are for trunk, but I would provide backported versions when the patches are discussed and we could solve the problem in a sane way.
I've backported following patches to a version which can be applied using git-am on top of the maint branch of batctl and batman-adv:
* [PATCHv1 1/4] batman-adv: Move device for icmp injection to debugfs * [PATCHv1 2/4] batctl: Use socket in debugfs instead of batman-adv device * [PATCHv3 3/4] batman-adv: Move tables from sysfs to debugfs * [PATCHv1 4/4] batctl: Get tables from debugfs instead of sysfs
(So nearly everything in version v1 - only patch 3/4 in v3).
Best regards, Sven
batctl uses /dev/batman-adv to send special batman-adv icmp packets to other nodes in the mesh. To get it working with multiple batX devices we must ensure that every mesh device can have their own socket which is used to inject those packets in exactly one mesh.
The current implementation still doesn't allow to use complete separated meshes as we rely on structures which are not part of the private data of a batman device.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- Please apply using git-am on top of batman-adv maint branch
Makefile.kbuild | 2 +- bat_debugfs.c | 74 ++++++++++ bat_debugfs.h | 33 ++++ compat.h | 65 +++++++-- device.c | 355 --------------------------------------------- icmp_socket.c | 329 +++++++++++++++++++++++++++++++++++++++++ device.h => icmp_socket.h | 18 +-- main.c | 21 ++- routing.c | 4 +- types.h | 5 +- 10 files changed, 516 insertions(+), 390 deletions(-) create mode 100644 bat_debugfs.c create mode 100644 bat_debugfs.h delete mode 100644 device.c create mode 100644 icmp_socket.c rename device.h => icmp_socket.h (54%)
diff --git a/Makefile.kbuild b/Makefile.kbuild index 914d556..33eb961 100644 --- a/Makefile.kbuild +++ b/Makefile.kbuild @@ -32,4 +32,4 @@ EXTRA_CFLAGS += -DREVISION_VERSION="r$(REVISION)" endif
obj-m += batman-adv.o -batman-adv-objs := main.o bat_sysfs.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) +batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) diff --git a/bat_debugfs.c b/bat_debugfs.c new file mode 100644 index 0000000..32d8144 --- /dev/null +++ b/bat_debugfs.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include <linux/debugfs.h> + +#include "main.h" +#include "bat_debugfs.h" +#include "translation-table.h" +#include "originator.h" +#include "hard-interface.h" +#include "vis.h" +#include "icmp_socket.h" +#include "compat.h" + +static struct dentry *bat_debugfs; + +void debugfs_init(void) +{ + bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); +} + +void debugfs_destroy(void) +{ + if (bat_debugfs) { + debugfs_remove_recursive(bat_debugfs); + bat_debugfs = NULL; + } +} + +int debugfs_add_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (!bat_debugfs) + goto out; + + bat_priv->debug_dir = debugfs_create_dir(dev->name, bat_debugfs); + if (!bat_priv->debug_dir) + goto out; + + bat_socket_setup(bat_priv); + + return 0; +out: + return -ENOMEM; +} + +void debugfs_del_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (bat_debugfs) { + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; + } +} diff --git a/bat_debugfs.h b/bat_debugfs.h new file mode 100644 index 0000000..5cdd332 --- /dev/null +++ b/bat_debugfs.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#ifndef BAT_DEBUGFS_H +#define BAT_DEBUGFS_H + +#define DEBUGFS_BAT_SUBDIR "batman_adv" + +void debugfs_init(void); +void debugfs_destroy(void); +int debugfs_add_meshif(struct net_device *dev); +void debugfs_del_meshif(struct net_device *dev); + +#endif diff --git a/compat.h b/compat.h index 5d30976..a8b24e4 100644 --- a/compat.h +++ b/compat.h @@ -160,12 +160,6 @@ static inline char *pack_hex_byte(char *buf, u8 byte) return buf; }
-#define device_create(_cls, _parent, _devt, _device, _fmt) \ - class_device_create(_cls, _parent, _devt, _device, _fmt) - -#define device_destroy(_cls, _device) \ - class_device_destroy(_cls, _device) - #endif /* < KERNEL_VERSION(2, 6, 26) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) @@ -174,10 +168,61 @@ static inline char *pack_hex_byte(char *buf, u8 byte) #define dereference_function_descriptor(p) (p) #endif
-#ifndef device_create -#define device_create(_cls, _parent, _devt, _device, _fmt) \ - device_create_drvdata(_cls, _parent, _devt, _device, _fmt) -#endif +#include <linux/debugfs.h> + +static inline void debugfs_remove_recursive(struct dentry *dentry) +{ + struct dentry *child; + struct dentry *parent; + + if (!dentry) + return; + + parent = dentry->d_parent; + if (!parent || !parent->d_inode) + return; + + parent = dentry; + + while (1) { + /* + * When all dentries under "parent" has been removed, + * walk up the tree until we reach our starting point. + */ + if (list_empty(&parent->d_subdirs)) { + if (parent == dentry) + break; + parent = parent->d_parent; + } + child = list_entry(parent->d_subdirs.next, struct dentry, + d_u.d_child); +next_sibling: + + /* + * If "child" isn't empty, walk down the tree and + * remove all its descendants first. + */ + if (!list_empty(&child->d_subdirs)) { + parent = child; + continue; + } + debugfs_remove(child); + if (parent->d_subdirs.next == &child->d_u.d_child) { + /* + * Try the next sibling. + */ + if (child->d_u.d_child.next != &parent->d_subdirs) { + child = list_entry(child->d_u.d_child.next, + struct dentry, + d_u.d_child); + goto next_sibling; + } + break; + } + } + + debugfs_remove(dentry); +}
#endif /* < KERNEL_VERSION(2, 6, 27) */
diff --git a/device.c b/device.c deleted file mode 100644 index bbd30f2..0000000 --- a/device.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include <linux/device.h> -#include "main.h" -#include "device.h" -#include "send.h" -#include "types.h" -#include "hash.h" -#include "hard-interface.h" - -#include "compat.h" - -static struct class *batman_class; - -static int Major; /* Major number assigned to our device driver */ - -static const struct file_operations fops = { - .open = bat_device_open, - .release = bat_device_release, - .read = bat_device_read, - .write = bat_device_write, - .poll = bat_device_poll, -}; - -static struct device_client *device_client_hash[256]; - -void bat_device_init(void) -{ - memset(device_client_hash, 0, sizeof(device_client_hash)); -} - -int bat_device_setup(void) -{ - int tmp_major; - - if (Major) - return 1; - - /* register our device - kernel assigns a free major number */ - tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops); - if (tmp_major < 0) { - printk(KERN_ERR "batman-adv:" - "Registering the character device failed with %d\n", - tmp_major); - return 0; - } - - batman_class = class_create(THIS_MODULE, "batman-adv"); - - if (IS_ERR(batman_class)) { - printk(KERN_ERR "batman-adv:" - "Could not register class 'batman-adv'\n"); - return 0; - } - - device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL, - "batman-adv"); - - Major = tmp_major; - return 1; -} - -void bat_device_destroy(void) -{ - if (!Major) - return; - - device_destroy(batman_class, MKDEV(Major, 0)); - class_destroy(batman_class); - - /* Unregister the device */ - unregister_chrdev(Major, DRIVER_DEVICE); - - Major = 0; -} - -int bat_device_open(struct inode *inode, struct file *file) -{ - unsigned int i; - struct device_client *device_client; - - device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL); - - if (!device_client) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) { - if (!device_client_hash[i]) { - device_client_hash[i] = device_client; - break; - } - } - - if (i == ARRAY_SIZE(device_client_hash)) { - printk(KERN_ERR "batman-adv:" - "Error - can't add another packet client: " - "maximum number of clients reached\n"); - kfree(device_client); - return -EXFULL; - } - - INIT_LIST_HEAD(&device_client->queue_list); - device_client->queue_len = 0; - device_client->index = i; - spin_lock_init(&device_client->lock); - init_waitqueue_head(&device_client->queue_wait); - - file->private_data = device_client; - - inc_module_count(); - return 0; -} - -int bat_device_release(struct inode *inode, struct file *file) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - struct list_head *list_pos, *list_pos_tmp; - unsigned long flags; - - spin_lock_irqsave(&device_client->lock, flags); - - /* for all packets in the queue ... */ - list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) { - device_packet = list_entry(list_pos, - struct device_packet, list); - - list_del(list_pos); - kfree(device_packet); - } - - device_client_hash[device_client->index] = NULL; - spin_unlock_irqrestore(&device_client->lock, flags); - - kfree(device_client); - dec_module_count(); - - return 0; -} - -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - int error; - unsigned long flags; - - if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0)) - return -EAGAIN; - - if ((!buf) || (count < sizeof(struct icmp_packet))) - return -EINVAL; - - if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; - - error = wait_event_interruptible(device_client->queue_wait, - device_client->queue_len); - - if (error) - return error; - - spin_lock_irqsave(&device_client->lock, flags); - - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - list_del(&device_packet->list); - device_client->queue_len--; - - spin_unlock_irqrestore(&device_client->lock, flags); - - error = __copy_to_user(buf, &device_packet->icmp_packet, - sizeof(struct icmp_packet)); - - kfree(device_packet); - - if (error) - return error; - - return sizeof(struct icmp_packet); -} - -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct icmp_packet icmp_packet; - struct orig_node *orig_node; - struct batman_if *batman_if; - uint8_t dstaddr[ETH_ALEN]; - unsigned long flags; - - if (len < sizeof(struct icmp_packet)) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "invalid packet size\n"); - return -EINVAL; - } - - if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet))) - return -EFAULT; - - if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet))) - return -EFAULT; - - if (icmp_packet.packet_type != BAT_ICMP) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus packet type (expected: BAT_ICMP)\n"); - return -EINVAL; - } - - if (icmp_packet.msg_type != ECHO_REQUEST) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus message type (expected: ECHO_REQUEST)\n"); - return -EINVAL; - } - - icmp_packet.uid = device_client->index; - - if (icmp_packet.version != COMPAT_VERSION) { - icmp_packet.msg_type = PARAMETER_PROBLEM; - icmp_packet.ttl = COMPAT_VERSION; - bat_device_add_packet(device_client, &icmp_packet); - goto out; - } - - if (atomic_read(&module_state) != MODULE_ACTIVE) - goto dst_unreach; - - spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); - - if (!orig_node) - goto unlock; - - if (!orig_node->router) - goto unlock; - - batman_if = orig_node->router->if_incoming; - memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - - spin_unlock_irqrestore(&orig_hash_lock, flags); - - if (!batman_if) - goto dst_unreach; - - if (batman_if->if_status != IF_ACTIVE) - goto dst_unreach; - - memcpy(icmp_packet.orig, - batman_if->net_dev->dev_addr, - ETH_ALEN); - - send_raw_packet((unsigned char *)&icmp_packet, - sizeof(struct icmp_packet), - batman_if, dstaddr); - - goto out; - -unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); -dst_unreach: - icmp_packet.msg_type = DESTINATION_UNREACHABLE; - bat_device_add_packet(device_client, &icmp_packet); -out: - return len; -} - -unsigned int bat_device_poll(struct file *file, poll_table *wait) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - - poll_wait(file, &device_client->queue_wait, wait); - - if (device_client->queue_len > 0) - return POLLIN | POLLRDNORM; - - return 0; -} - -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet *icmp_packet) -{ - struct device_packet *device_packet; - unsigned long flags; - - device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL); - - if (!device_packet) - return; - - INIT_LIST_HEAD(&device_packet->list); - memcpy(&device_packet->icmp_packet, icmp_packet, - sizeof(struct icmp_packet)); - - spin_lock_irqsave(&device_client->lock, flags); - - /* while waiting for the lock the device_client could have been - * deleted */ - if (!device_client_hash[icmp_packet->uid]) { - spin_unlock_irqrestore(&device_client->lock, flags); - kfree(device_packet); - return; - } - - list_add_tail(&device_packet->list, &device_client->queue_list); - device_client->queue_len++; - - if (device_client->queue_len > 100) { - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - - list_del(&device_packet->list); - kfree(device_packet); - device_client->queue_len--; - } - - spin_unlock_irqrestore(&device_client->lock, flags); - - wake_up(&device_client->queue_wait); -} - -void bat_device_receive_packet(struct icmp_packet *icmp_packet) -{ - struct device_client *hash = device_client_hash[icmp_packet->uid]; - - if (hash) - bat_device_add_packet(hash, icmp_packet); -} diff --git a/icmp_socket.c b/icmp_socket.c new file mode 100644 index 0000000..eba8aa2 --- /dev/null +++ b/icmp_socket.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include <linux/debugfs.h> +#include "main.h" +#include "icmp_socket.h" +#include "send.h" +#include "types.h" +#include "hash.h" +#include "hard-interface.h" + +#include "compat.h" + + +static struct socket_client *socket_client_hash[256]; + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet *icmp_packet); + +void bat_socket_init(void) +{ + memset(socket_client_hash, 0, sizeof(socket_client_hash)); +} + +static int bat_socket_open(struct inode *inode, struct file *file) +{ + unsigned int i; + struct socket_client *socket_client; + + socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL); + + if (!socket_client) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(socket_client_hash); i++) { + if (!socket_client_hash[i]) { + socket_client_hash[i] = socket_client; + break; + } + } + + if (i == ARRAY_SIZE(socket_client_hash)) { + printk(KERN_ERR "batman-adv:" + "Error - can't add another packet client: " + "maximum number of clients reached\n"); + kfree(socket_client); + return -EXFULL; + } + + INIT_LIST_HEAD(&socket_client->queue_list); + socket_client->queue_len = 0; + socket_client->index = i; + spin_lock_init(&socket_client->lock); + init_waitqueue_head(&socket_client->queue_wait); + + file->private_data = socket_client; + + inc_module_count(); + return 0; +} + +static int bat_socket_release(struct inode *inode, struct file *file) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + struct list_head *list_pos, *list_pos_tmp; + unsigned long flags; + + spin_lock_irqsave(&socket_client->lock, flags); + + /* for all packets in the queue ... */ + list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) { + socket_packet = list_entry(list_pos, + struct socket_packet, list); + + list_del(list_pos); + kfree(socket_packet); + } + + socket_client_hash[socket_client->index] = NULL; + spin_unlock_irqrestore(&socket_client->lock, flags); + + kfree(socket_client); + dec_module_count(); + + return 0; +} + +static ssize_t bat_socket_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + int error; + unsigned long flags; + + if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0)) + return -EAGAIN; + + if ((!buf) || (count < sizeof(struct icmp_packet))) + return -EINVAL; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + error = wait_event_interruptible(socket_client->queue_wait, + socket_client->queue_len); + + if (error) + return error; + + spin_lock_irqsave(&socket_client->lock, flags); + + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + list_del(&socket_packet->list); + socket_client->queue_len--; + + spin_unlock_irqrestore(&socket_client->lock, flags); + + error = __copy_to_user(buf, &socket_packet->icmp_packet, + sizeof(struct icmp_packet)); + + kfree(socket_packet); + + if (error) + return error; + + return sizeof(struct icmp_packet); +} + +static ssize_t bat_socket_write(struct file *file, const char __user *buff, + size_t len, loff_t *off) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct icmp_packet icmp_packet; + struct orig_node *orig_node; + struct batman_if *batman_if; + uint8_t dstaddr[ETH_ALEN]; + unsigned long flags; + + if (len < sizeof(struct icmp_packet)) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "invalid packet size\n"); + return -EINVAL; + } + + if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet))) + return -EFAULT; + + if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet))) + return -EFAULT; + + if (icmp_packet.packet_type != BAT_ICMP) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus packet type (expected: BAT_ICMP)\n"); + return -EINVAL; + } + + if (icmp_packet.msg_type != ECHO_REQUEST) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus message type (expected: ECHO_REQUEST)\n"); + return -EINVAL; + } + + icmp_packet.uid = socket_client->index; + + if (icmp_packet.version != COMPAT_VERSION) { + icmp_packet.msg_type = PARAMETER_PROBLEM; + icmp_packet.ttl = COMPAT_VERSION; + bat_socket_add_packet(socket_client, &icmp_packet); + goto out; + } + + if (atomic_read(&module_state) != MODULE_ACTIVE) + goto dst_unreach; + + spin_lock_irqsave(&orig_hash_lock, flags); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); + + if (!orig_node) + goto unlock; + + if (!orig_node->router) + goto unlock; + + batman_if = orig_node->router->if_incoming; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + + spin_unlock_irqrestore(&orig_hash_lock, flags); + + if (!batman_if) + goto dst_unreach; + + if (batman_if->if_status != IF_ACTIVE) + goto dst_unreach; + + memcpy(icmp_packet.orig, + batman_if->net_dev->dev_addr, + ETH_ALEN); + + send_raw_packet((unsigned char *)&icmp_packet, + sizeof(struct icmp_packet), + batman_if, dstaddr); + + goto out; + +unlock: + spin_unlock_irqrestore(&orig_hash_lock, flags); +dst_unreach: + icmp_packet.msg_type = DESTINATION_UNREACHABLE; + bat_socket_add_packet(socket_client, &icmp_packet); +out: + return len; +} + +static unsigned int bat_socket_poll(struct file *file, poll_table *wait) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + + poll_wait(file, &socket_client->queue_wait, wait); + + if (socket_client->queue_len > 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .open = bat_socket_open, + .release = bat_socket_release, + .read = bat_socket_read, + .write = bat_socket_write, + .poll = bat_socket_poll, +}; + +int bat_socket_setup(struct bat_priv *bat_priv) +{ + struct dentry *d; + + if (!bat_priv->debug_dir) + goto err; + + d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR, + bat_priv->debug_dir, NULL, &fops); + if (d) + goto err; + + return 0; + +err: + return 1; +} + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet *icmp_packet) +{ + struct socket_packet *socket_packet; + unsigned long flags; + + socket_packet = kmalloc(sizeof(struct socket_packet), GFP_KERNEL); + + if (!socket_packet) + return; + + INIT_LIST_HEAD(&socket_packet->list); + memcpy(&socket_packet->icmp_packet, icmp_packet, + sizeof(struct icmp_packet)); + + spin_lock_irqsave(&socket_client->lock, flags); + + /* while waiting for the lock the socket_client could have been + * deleted */ + if (!socket_client_hash[icmp_packet->uid]) { + spin_unlock_irqrestore(&socket_client->lock, flags); + kfree(socket_packet); + return; + } + + list_add_tail(&socket_packet->list, &socket_client->queue_list); + socket_client->queue_len++; + + if (socket_client->queue_len > 100) { + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + + list_del(&socket_packet->list); + kfree(socket_packet); + socket_client->queue_len--; + } + + spin_unlock_irqrestore(&socket_client->lock, flags); + + wake_up(&socket_client->queue_wait); +} + +void bat_socket_receive_packet(struct icmp_packet *icmp_packet) +{ + struct socket_client *hash = socket_client_hash[icmp_packet->uid]; + + if (hash) + bat_socket_add_packet(hash, icmp_packet); +} diff --git a/device.h b/icmp_socket.h similarity index 54% rename from device.h rename to icmp_socket.h index eb14b37..5ad73da 100644 --- a/device.h +++ b/icmp_socket.h @@ -21,16 +21,8 @@
#include "types.h"
-void bat_device_init(void); -int bat_device_setup(void); -void bat_device_destroy(void); -int bat_device_open(struct inode *inode, struct file *file); -int bat_device_release(struct inode *inode, struct file *file); -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos); -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off); -unsigned int bat_device_poll(struct file *file, poll_table *wait); -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet *icmp_packet); -void bat_device_receive_packet(struct icmp_packet *icmp_packet); +#define ICMP_SOCKET "socket" + +void bat_socket_init(void); +int bat_socket_setup(struct bat_priv *bat_priv); +void bat_socket_receive_packet(struct icmp_packet *icmp_packet); diff --git a/main.c b/main.c index 6c39990..770625f 100644 --- a/main.c +++ b/main.c @@ -21,11 +21,12 @@
#include "main.h" #include "bat_sysfs.h" +#include "bat_debugfs.h" #include "routing.h" #include "send.h" #include "originator.h" #include "soft-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "hard-interface.h" #include "types.h" @@ -93,7 +94,8 @@ int init_module(void) if (!bat_event_workqueue) return -ENOMEM;
- bat_device_init(); + bat_socket_init(); + debugfs_init();
/* initialize layer 2 interface */ soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", @@ -118,6 +120,11 @@ int init_module(void) if (retval < 0) goto unreg_soft_device;
+ retval = debugfs_add_meshif(soft_device); + + if (retval < 0) + goto unreg_sysfs; + register_netdevice_notifier(&hard_if_notifier); dev_add_pack(&batman_adv_packet_type);
@@ -127,6 +134,8 @@ int init_module(void)
return 0;
+unreg_sysfs: + sysfs_del_meshif(soft_device); unreg_soft_device: unregister_netdevice(soft_device); free_soft_device: @@ -144,6 +153,7 @@ void cleanup_module(void) hardif_remove_interfaces();
if (soft_device) { + debugfs_del_meshif(soft_device); sysfs_del_meshif(soft_device); unregister_netdev(soft_device); soft_device = NULL; @@ -155,7 +165,7 @@ void cleanup_module(void) bat_event_workqueue = NULL; }
-/* activates the module, creates bat device, starts timer ... */ +/* activates the module, starts timer ... */ void activate_module(void) { if (originator_init() < 1) @@ -169,9 +179,6 @@ void activate_module(void)
hna_local_add(soft_device->dev_addr);
- if (bat_device_setup() < 1) - goto end; - if (vis_init() < 1) goto err;
@@ -206,7 +213,7 @@ void deactivate_module(void) hna_global_free();
synchronize_net(); - bat_device_destroy(); + debugfs_destroy();
synchronize_rcu(); atomic_set(&module_state, MODULE_INACTIVE); diff --git a/routing.c b/routing.c index 13d2dc5..e9b0377 100644 --- a/routing.c +++ b/routing.c @@ -25,7 +25,7 @@ #include "hash.h" #include "soft-interface.h" #include "hard-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "originator.h" #include "types.h" @@ -669,7 +669,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
/* add data to device queue */ if (icmp_packet->msg_type != ECHO_REQUEST) { - bat_device_receive_packet(icmp_packet); + bat_socket_receive_packet(icmp_packet); return NET_RX_DROP; }
diff --git a/types.h b/types.h index 86007c7..751cd63 100644 --- a/types.h +++ b/types.h @@ -106,9 +106,10 @@ struct bat_priv { char num_ifaces; struct batman_if *primary_if; struct kobject *mesh_obj; + struct dentry *debug_dir; };
-struct device_client { +struct socket_client { struct list_head queue_list; unsigned int queue_len; unsigned char index; @@ -116,7 +117,7 @@ struct device_client { wait_queue_head_t queue_wait; };
-struct device_packet { +struct socket_packet { struct list_head list; struct icmp_packet icmp_packet; };
The batman-adv device which was only usable for a single batX net device was replaced with a file in debugfs which can be used the same way as /dev/batman-adv before.
It seems that the debugfs has no 100% common mount path in current distributions and maybe isn't mounted at all. So before we try to access a batman file in debugfs, we have to search for the mountpoint in /proc/mounts and maybe mount it manually in /sys/kernel/debug.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- Please apply on top of batctl-0.2.x branch.
Makefile | 4 +- debugfs.c | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debugfs.h | 46 ++++++++++ main.h | 2 +- ping.c | 21 ++++- traceroute.c | 21 ++++- 6 files changed, 350 insertions(+), 13 deletions(-) create mode 100644 debugfs.c create mode 100644 debugfs.h
diff --git a/Makefile b/Makefile index 8a3021c..ff877ea 100644 --- a/Makefile +++ b/Makefile @@ -39,8 +39,8 @@ SRC_FILES = "(.c)|(.h)|(Makefile)|(INSTALL)|(LIESMICH)|(README EXTRA_MODULES_C := bisect.c EXTRA_MODULES_H := bisect.h
-SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c $(EXTRA_MODULES_C) -SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h $(EXTRA_MODULES_H) +SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) +SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) SRC_O = $(SRC_C:.c=.o)
PACKAGE_NAME = batctl diff --git a/debugfs.c b/debugfs.c new file mode 100644 index 0000000..cfe1254 --- /dev/null +++ b/debugfs.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2009 Clark Williams williams@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@cn.fujitsu.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "debugfs.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <linux/magic.h> +#include <sys/vfs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef DEBUGFS_MAGIC +#define DEBUGFS_MAGIC 0x64626720 +#endif + +static int debugfs_premounted; +static char debugfs_mountpoint[MAX_PATH+1]; + +static const char *debugfs_known_mountpoints[] = { + "/sys/kernel/debug/", + "/debug/", + 0, +}; + +/* use this to force a umount */ +void debugfs_force_cleanup(void) +{ + debugfs_find_mountpoint(); + debugfs_premounted = 0; + debugfs_umount(); +} + +/* construct a full path to a debugfs element */ +int debugfs_make_path(const char *element, char *buffer, int size) +{ + int len; + + if (strlen(debugfs_mountpoint) == 0) { + buffer[0] = '\0'; + return -1; + } + + len = strlen(debugfs_mountpoint) + strlen(element) + 1; + if (len >= size) + return len+1; + + snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element); + return 0; +} + +static int debugfs_found; + +/* find the path to the mounted debugfs */ +const char *debugfs_find_mountpoint(void) +{ + const char **ptr; + char type[100]; + FILE *fp; + + if (debugfs_found) + return (const char *) debugfs_mountpoint; + + ptr = debugfs_known_mountpoints; + while (*ptr) { + if (debugfs_valid_mountpoint(*ptr) == 0) { + debugfs_found = 1; + strcpy(debugfs_mountpoint, *ptr); + return debugfs_mountpoint; + } + ptr++; + } + + /* give up and parse /proc/mounts */ + fp = fopen("/proc/mounts", "r"); + if (fp == NULL) { + printf("Error - can't open /proc/mounts for read: %s\n", + strerror(errno)); + return NULL; + } + + while (fscanf(fp, "%*s %" + STR(MAX_PATH) + "s %99s %*s %*d %*d\n", + debugfs_mountpoint, type) == 2) { + if (strcmp(type, "debugfs") == 0) + break; + } + fclose(fp); + + if (strcmp(type, "debugfs") != 0) + return NULL; + + debugfs_found = 1; + + return debugfs_mountpoint; +} + +/* verify that a mountpoint is actually a debugfs instance */ + +int debugfs_valid_mountpoint(const char *debugfs) +{ + struct statfs st_fs; + + if (statfs(debugfs, &st_fs) < 0) + return -ENOENT; + else if (st_fs.f_type != (long) DEBUGFS_MAGIC) + return -ENOENT; + + return 0; +} + + +int debugfs_valid_entry(const char *path) +{ + struct stat st; + + if (stat(path, &st)) + return -errno; + + return 0; +} + +/* mount the debugfs somewhere if it's not mounted */ + +char *debugfs_mount(const char *mountpoint) +{ + /* see if it's already mounted */ + if (debugfs_find_mountpoint()) { + debugfs_premounted = 1; + return debugfs_mountpoint; + } + + /* if not mounted and no argument */ + if (mountpoint == NULL) + mountpoint = "/sys/kernel/debug"; + + if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) + return NULL; + + /* save the mountpoint */ + strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint)); + debugfs_found = 1; + + return debugfs_mountpoint; +} + +/* umount the debugfs */ + +int debugfs_umount(void) +{ + char umountcmd[128]; + int ret; + + /* if it was already mounted, leave it */ + if (debugfs_premounted) + return 0; + + /* make sure it's a valid mount point */ + ret = debugfs_valid_mountpoint(debugfs_mountpoint); + if (ret) + return ret; + + snprintf(umountcmd, sizeof(umountcmd), + "/bin/umount %s", debugfs_mountpoint); + return system(umountcmd); +} + +int debugfs_write(const char *entry, const char *value) +{ + char path[MAX_PATH+1]; + int ret, count; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* get how many chars we're going to write */ + count = strlen(value); + + /* open the debugfs entry */ + fd = open(path, O_RDWR); + if (fd < 0) + return -errno; + + while (count > 0) { + /* write it */ + ret = write(fd, value, count); + if (ret <= 0) { + if (ret == EAGAIN) + continue; + close(fd); + return -errno; + } + count -= ret; + } + + /* close it */ + close(fd); + + /* return success */ + return 0; +} + +/* + * read a debugfs entry + * returns the number of chars read or a negative errno + */ +int debugfs_read(const char *entry, char *buffer, size_t size) +{ + char path[MAX_PATH+1]; + int ret; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* open the debugfs entry */ + fd = open(path, O_RDONLY); + if (fd < 0) + return -errno; + + do { + /* read it */ + ret = read(fd, buffer, size); + if (ret == 0) { + close(fd); + return EOF; + } + } while (ret < 0 && errno == EAGAIN); + + /* close it */ + close(fd); + + /* make *sure* there's a null character at the end */ + buffer[ret] = '\0'; + + /* return the number of chars read */ + return ret; +} diff --git a/debugfs.h b/debugfs.h new file mode 100644 index 0000000..45f6339 --- /dev/null +++ b/debugfs.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 Clark Williams williams@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@cn.fujitsu.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#ifndef __DEBUGFS_H__ +#define __DEBUGFS_H__ + +#include <sys/mount.h> +#include <string.h> + +#ifndef MAX_PATH +# define MAX_PATH 256 +#endif + +#ifndef STR +# define _STR(x) #x +# define STR(x) _STR(x) +#endif + +extern const char *debugfs_find_mountpoint(void); +extern int debugfs_valid_mountpoint(const char *debugfs); +extern int debugfs_valid_entry(const char *path); +extern char *debugfs_mount(const char *mountpoint); +extern int debugfs_umount(void); +extern int debugfs_write(const char *entry, const char *value); +extern int debugfs_read(const char *entry, char *buffer, size_t size); +extern void debugfs_force_cleanup(void); +extern int debugfs_make_path(const char *element, char *buffer, int size); + +#endif /* __DEBUGFS_H__ */ diff --git a/main.h b/main.h index 14aecc5..9f0b52d 100644 --- a/main.h +++ b/main.h @@ -23,4 +23,4 @@
#define SOURCE_VERSION "0.2.2-beta" /*put exactly one distinct word inside the string like "0.3-pre-alpha" or "0.3-rc1" or "0.3" */
-#define BAT_DEVICE "/dev/batman-adv" +#define SOCKET_PATH "batman_adv/bat0/socket" diff --git a/ping.c b/ping.c index e423f9b..df1ad0c 100644 --- a/ping.c +++ b/ping.c @@ -35,6 +35,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
char is_aborted = 0; @@ -76,6 +77,8 @@ int ping(int argc, char **argv) char *dst_string, *mac_string; double time_delta; float min = 0.0, max = 0.0, avg = 0.0; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hc:i:t:")) != -1) { switch (optchar) { @@ -132,11 +135,19 @@ int ping(int argc, char **argv) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler);
- ping_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + ping_fd = open(icmp_socket, O_RDWR);
if (ping_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -161,7 +172,7 @@ int ping(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(ping_fd, (char *)&icmp_packet_out, sizeof(icmp_packet_out)) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
@@ -191,7 +202,7 @@ int ping(int argc, char **argv) read_len = read(ping_fd, (char *)&icmp_packet_in, sizeof(icmp_packet_in));
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
diff --git a/traceroute.c b/traceroute.c index 4115e6b..f5b63f9 100644 --- a/traceroute.c +++ b/traceroute.c @@ -34,6 +34,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
#define TTL_MAX 50 @@ -59,6 +60,8 @@ int traceroute(int argc, char **argv) int ret = EXIT_FAILURE, res, trace_fd = 0, i; int found_args = 1, optchar, seq_counter = 0, read_opt = USE_BAT_HOSTS; double time_delta; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hn")) != -1) { switch (optchar) { @@ -99,11 +102,19 @@ int traceroute(int argc, char **argv)
mac_string = ether_ntoa_long(dst_mac);
- trace_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + trace_fd = open(icmp_socket, O_RDWR);
if (trace_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -123,7 +134,7 @@ int traceroute(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(trace_fd, (char *)&icmp_packet_out, sizeof(icmp_packet_out)) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }
@@ -149,7 +160,7 @@ int traceroute(int argc, char **argv) read_len = read(trace_fd, (char *)&icmp_packet_in, sizeof(icmp_packet_in));
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }
Files which represent more than a single attribute aren't allowed in sysfs. As we have some files which aren't essential and are lists or tables aggregated from data from different places inside batman-adv, we must place them in a filesystem without such a restriction.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- Please apply using git-am on top of batman-adv maint branch after * batman-adv: Move device for icmp injection to debugfs
bat_debugfs.c | 71 ++++++++++++++++++++++++ bat_sysfs.c | 79 -------------------------- main.h | 1 + originator.c | 61 ++++++-------------- originator.h | 3 +- translation-table.c | 153 ++++++++++++++++++++++++++------------------------- translation-table.h | 6 +- vis.c | 111 ++++++++++++++++++++++++++---------- vis.h | 3 +- 9 files changed, 251 insertions(+), 237 deletions(-)
diff --git a/bat_debugfs.c b/bat_debugfs.c index 32d8144..39cc6de 100644 --- a/bat_debugfs.c +++ b/bat_debugfs.c @@ -32,6 +32,60 @@
static struct dentry *bat_debugfs;
+static int originators_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, orig_seq_print_text, net_dev); +} + +static int transtable_global_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_global_seq_print_text, net_dev); +} + +static int transtable_local_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_local_seq_print_text, net_dev); +} + +static int vis_data_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, vis_seq_print_text, net_dev); +} + +struct bat_debuginfo { + struct attribute attr; + const struct file_operations fops; +}; + +#define BAT_DEBUGINFO(_name, _mode, _open) \ +struct bat_debuginfo bat_debuginfo_##_name = { \ + .attr = { .name = __stringify(_name), \ + .mode = _mode, }, \ + .fops = { .owner = THIS_MODULE, \ + .open = _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } \ +}; + +static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); +static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); +static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); +static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); + +static struct bat_debuginfo *mesh_debuginfos[] = { + &bat_debuginfo_originators, + &bat_debuginfo_transtable_global, + &bat_debuginfo_transtable_local, + &bat_debuginfo_vis_data, + NULL, +}; + void debugfs_init(void) { bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); @@ -48,6 +102,8 @@ void debugfs_destroy(void) int debugfs_add_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); + struct bat_debuginfo **bat_debug; + struct dentry *file;
if (!bat_debugfs) goto out; @@ -58,7 +114,22 @@ int debugfs_add_meshif(struct net_device *dev)
bat_socket_setup(bat_priv);
+ for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) { + file = debugfs_create_file(((*bat_debug)->attr).name, + S_IFREG | ((*bat_debug)->attr).mode, + bat_priv->debug_dir, + dev, &(*bat_debug)->fops); + if (!file) { + printk(KERN_ERR "batman-adv:Can't add debugfs file: " + "%s/%s\n", dev->name, ((*bat_debug)->attr).name); + goto rem_attr; + } + } + return 0; +rem_attr: + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; out: return -ENOMEM; } diff --git a/bat_sysfs.c b/bat_sysfs.c index afaa490..ab5e398 100644 --- a/bat_sysfs.c +++ b/bat_sysfs.c @@ -37,14 +37,6 @@ struct bat_attribute bat_attr_##_name = { \ .store = _store, \ };
-#define BAT_BIN_ATTR(_name, _mode, _read, _write) \ -struct bin_attribute bat_attr_##_name = { \ - .attr = { .name = __stringify(_name), \ - .mode = _mode, }, \ - .read = _read, \ - .write = _write, \ -}; - static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -202,65 +194,11 @@ static struct bat_attribute *mesh_attrs[] = { NULL, };
-static ssize_t transtable_local_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_local_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t transtable_global_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_global_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t originators_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return orig_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t vis_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return vis_fill_buffer_text(net_dev, buff, count, off); -} - -static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL); -static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL); -static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL); -static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL); - -static struct bin_attribute *mesh_bin_attrs[] = { - &bat_attr_transtable_local, - &bat_attr_transtable_global, - &bat_attr_originators, - &bat_attr_vis_data, - NULL, -}; - int sysfs_add_meshif(struct net_device *dev) { struct kobject *batif_kobject = &dev->dev.kobj; struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; int err;
/* FIXME: should be done in the general mesh setup @@ -290,21 +228,8 @@ int sysfs_add_meshif(struct net_device *dev) } }
- for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) { - err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr)); - if (err) { - printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", - dev->name, SYSFS_IF_MESH_SUBDIR, - ((*bin_attr)->attr).name); - goto rem_bin_attr; - } - } - return 0;
-rem_bin_attr: - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr)); rem_attr: for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); @@ -319,10 +244,6 @@ void sysfs_del_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; - - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); diff --git a/main.h b/main.h index 8d6c1a0..b3f035b 100644 --- a/main.h +++ b/main.h @@ -116,6 +116,7 @@ extern int bat_debug_type(int type); #include <linux/workqueue.h> /* workqueue */ #include <net/sock.h> /* struct sock */ #include <linux/jiffies.h> +#include <linux/seq_file.h> #include "types.h"
#ifndef REVISION_VERSION diff --git a/originator.c b/originator.c index 5435bd6..183b7a1 100644 --- a/originator.c +++ b/originator.c @@ -272,38 +272,31 @@ void purge_orig(struct work_struct *work) start_purge_timer(); }
-ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int orig_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct orig_node *orig_node; struct neigh_node *neigh_node; - size_t hdr_len, tmp_len; - int batman_count = 0, bytes_written = 0; + int batman_count = 0; unsigned long flags; char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
if ((!bat_priv->primary_if) || (bat_priv->primary_if->if_status != IF_ACTIVE)) { - if (off > 0) - return 0; - if (!bat_priv->primary_if) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name);
- return sprintf(buff, - "BATMAN mesh %s " - "disabled - primary interface not active\n", - net_dev->name); + return seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); }
rcu_read_lock(); - hdr_len = sprintf(buff, - " %-14s (%s/%i) %17s [%10s]: %20s " + seq_printf(seq, " %-14s (%s/%i) %17s [%10s]: %20s " "... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR, @@ -311,9 +304,6 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, net_dev->name); rcu_read_unlock();
- if (off < hdr_len) - bytes_written = hdr_len; - spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) { @@ -326,44 +316,29 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, if (orig_node->router->tq_avg == 0) continue;
- /* estimated line length */ - if (count < bytes_written + 200) - break; - addr_to_string(orig_str, orig_node->orig); addr_to_string(router_str, orig_node->router->addr);
- tmp_len = sprintf(buff + bytes_written, - "%-17s (%3i) %17s [%10s]:", - orig_str, orig_node->router->tq_avg, - router_str, - orig_node->router->if_incoming->dev); + seq_printf(seq, "%-17s (%3i) %17s [%10s]:", + orig_str, orig_node->router->tq_avg, router_str, + orig_node->router->if_incoming->dev);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { addr_to_string(orig_str, neigh_node->addr); - tmp_len += sprintf(buff + bytes_written + tmp_len, - " %17s (%3i)", orig_str, + seq_printf(seq, " %17s (%3i)", orig_str, neigh_node->tq_avg); }
- tmp_len += sprintf(buff + bytes_written + tmp_len, "\n"); - + seq_printf(seq, "\n"); batman_count++; - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; }
spin_unlock_irqrestore(&orig_hash_lock, flags);
- if ((batman_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No batman nodes in range ...\n"); + if ((batman_count == 0)) + seq_printf(seq, "No batman nodes in range ...\n");
- return bytes_written; + return 0; }
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) diff --git a/originator.h b/originator.h index afbc7c0..e91e8a1 100644 --- a/originator.h +++ b/originator.h @@ -28,7 +28,6 @@ struct orig_node *get_orig_node(uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming); -ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int orig_seq_print_text(struct seq_file *seq, void *offset); int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); diff --git a/translation-table.c b/translation-table.c index a60bc7e..60d9315 100644 --- a/translation-table.c +++ b/translation-table.c @@ -161,59 +161,59 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len) return i; }
-int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_local_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_local_entry *hna_local_entry; HASHIT(hashit); - int bytes_written = 0; + HASHIT(hashit_count); unsigned long flags; - size_t hdr_len; + size_t buf_size, pos; + char *buff;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Locally retrieved addresses (from %s) " - "announced via HNA:\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Locally retrieved addresses (from %s) " + "announced via HNA:\n", + net_dev->name);
spin_lock_irqsave(&hna_local_hash_lock, flags);
+ buf_size = 1; + /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ + while (hash_iterate(hna_local_hash, &hashit_count)) + buf_size += 21; + + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + pos = 0; + while (hash_iterate(hna_local_hash, &hashit)) { - hdr_len += 21; - - if (count < bytes_written + 22) - break; - - if (off >= hdr_len) - continue; - hna_local_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 22, - " * " MAC_FMT "\n", - hna_local_entry->addr[0], - hna_local_entry->addr[1], - hna_local_entry->addr[2], - hna_local_entry->addr[3], - hna_local_entry->addr[4], - hna_local_entry->addr[5]); + pos += snprintf(buff + pos, 22, " * " MAC_FMT "\n", + hna_local_entry->addr[0], + hna_local_entry->addr[1], + hna_local_entry->addr[2], + hna_local_entry->addr[3], + hna_local_entry->addr[4], + hna_local_entry->addr[5]); }
spin_unlock_irqrestore(&hna_local_hash_lock, flags); - return bytes_written; + + seq_printf(seq, "%s", buff); + kfree(buff); + return 0; }
static void _hna_local_del(void *data) @@ -379,65 +379,66 @@ void hna_global_add_orig(struct orig_node *orig_node, spin_unlock_irqrestore(&hna_global_hash_lock, flags); }
-int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_global_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_global_entry *hna_global_entry; HASHIT(hashit); - int bytes_written = 0; + HASHIT(hashit_count); unsigned long flags; - size_t hdr_len; + size_t buf_size, pos; + char *buff;
if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); }
- hdr_len = sprintf(buff, - "Globally announced HNAs received via the mesh %s " - "(translation table):\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Globally announced HNAs received via the mesh %s " + "(translation table):\n", + net_dev->name);
spin_lock_irqsave(&hna_global_hash_lock, flags);
+ buf_size = 1; + /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ + while (hash_iterate(hna_global_hash, &hashit_count)) + buf_size += 43; + + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + pos = 0; + while (hash_iterate(hna_global_hash, &hashit)) { - hdr_len += 43; - - if (count < bytes_written + 44) - break; - - if (off >= hdr_len) - continue; - hna_global_entry = hashit.bucket->data;
- bytes_written += snprintf(buff + bytes_written, 44, - " * " MAC_FMT " via " MAC_FMT "\n", - hna_global_entry->addr[0], - hna_global_entry->addr[1], - hna_global_entry->addr[2], - hna_global_entry->addr[3], - hna_global_entry->addr[4], - hna_global_entry->addr[5], - hna_global_entry->orig_node->orig[0], - hna_global_entry->orig_node->orig[1], - hna_global_entry->orig_node->orig[2], - hna_global_entry->orig_node->orig[3], - hna_global_entry->orig_node->orig[4], - hna_global_entry->orig_node->orig[5]); + pos += snprintf(buff + pos, 44, + " * " MAC_FMT " via " MAC_FMT "\n", + hna_global_entry->addr[0], + hna_global_entry->addr[1], + hna_global_entry->addr[2], + hna_global_entry->addr[3], + hna_global_entry->addr[4], + hna_global_entry->addr[5], + hna_global_entry->orig_node->orig[0], + hna_global_entry->orig_node->orig[1], + hna_global_entry->orig_node->orig[2], + hna_global_entry->orig_node->orig[3], + hna_global_entry->orig_node->orig[4], + hna_global_entry->orig_node->orig[5]); }
spin_unlock_irqrestore(&hna_global_hash_lock, flags); - return bytes_written; + + seq_printf(seq, "%s", buff); + kfree(buff); + return 0; }
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, diff --git a/translation-table.h b/translation-table.h index 8f412fc..8b3429e 100644 --- a/translation-table.h +++ b/translation-table.h @@ -25,15 +25,13 @@ int hna_local_init(void); void hna_local_add(uint8_t *addr); void hna_local_remove(uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); -int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_local_seq_print_text(struct seq_file *seq, void *offset); void hna_local_purge(struct work_struct *work); void hna_local_free(void); int hna_global_init(void); void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); -int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_global_seq_print_text(struct seq_file *seq, void *offset); void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, char *orig_str); void hna_global_del_orig(struct orig_node *orig_node, char *message); diff --git a/vis.c b/vis.c index da565f7..7b2c1e6 100644 --- a/vis.c +++ b/vis.c @@ -116,7 +116,7 @@ static void vis_data_insert_interface(const uint8_t *interface, }
/* its a new address, add it to the list */ - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) return; memcpy(entry->addr, interface, ETH_ALEN); @@ -143,12 +143,29 @@ static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) return len; }
+static size_t vis_data_count_prim_sec(struct hlist_head *if_list) +{ + struct if_list_entry *entry; + struct hlist_node *pos; + size_t count = 0; + + hlist_for_each_entry(entry, pos, if_list, list) { + if (entry->primary) + count += 9; + else + count += 23; + } + + return count; +} + /* read an entry */ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, uint8_t *src, bool primary) { - char to[40]; + char to[18];
+ /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ addr_to_string(to, entry->dest); if (primary && entry->quality == 0) return sprintf(buff, "HNA %s, ", to); @@ -158,38 +175,74 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, return 0; }
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int vis_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + HASHIT(hashit_count); struct vis_info *info; struct vis_info_entry *entries; + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; - size_t hdr_len, tmp_len; - int i, bytes_written = 0; + int i; char tmp_addr_str[ETH_STR_LEN]; unsigned long flags; int vis_server = atomic_read(&bat_priv->vis_mode); + size_t buff_pos, buf_size; + char *buff;
if ((!bat_priv->primary_if) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) return 0;
- hdr_len = 0; - + buf_size = 1; + /* Estimate length */ spin_lock_irqsave(&vis_hash_lock, flags); + while (hash_iterate(vis_hash, &hashit_count)) { + info = hashit_count.bucket->data; + entries = (struct vis_info_entry *) + ((char *)info + sizeof(struct vis_info)); + + for (i = 0; i < info->packet.entries; i++) { + if (entries[i].quality == 0) + continue; + vis_data_insert_interface(entries[i].src, &vis_if_list, + compare_orig(entries[i].src, + info->packet.vis_orig)); + } + + hlist_for_each_entry(entry, pos, &vis_if_list, list) { + buf_size += 18 + 26 * info->packet.entries; + + /* add primary/secondary records */ + if (compare_orig(entry->addr, info->packet.vis_orig)) + buf_size += + vis_data_count_prim_sec(&vis_if_list); + + buf_size += 1; + } + + hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { + hlist_del(&entry->list); + kfree(entry); + } + } + + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&vis_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + buff_pos = 0; + while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info));
- /* estimated line length */ - if (count < bytes_written + 200) - break; - for (i = 0; i < info->packet.entries; i++) { if (entries[i].quality == 0) continue; @@ -200,30 +253,22 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
hlist_for_each_entry(entry, pos, &vis_if_list, list) { addr_to_string(tmp_addr_str, entry->addr); - tmp_len = sprintf(buff + bytes_written, - "%s,", tmp_addr_str); + buff_pos += sprintf(buff + buff_pos, "%s,", + tmp_addr_str);
for (i = 0; i < info->packet.entries; i++) - tmp_len += vis_data_read_entry( - buff + bytes_written + tmp_len, - &entries[i], entry->addr, - entry->primary); + buff_pos += vis_data_read_entry(buff + buff_pos, + &entries[i], + entry->addr, + entry->primary);
/* add primary/secondary records */ if (compare_orig(entry->addr, info->packet.vis_orig)) - tmp_len += vis_data_read_prim_sec( - buff + bytes_written + tmp_len, - &vis_if_list); + buff_pos += + vis_data_read_prim_sec(buff + buff_pos, + &vis_if_list);
- tmp_len += sprintf(buff + bytes_written + tmp_len, - "\n"); - - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; + buff_pos += sprintf(buff + buff_pos, "\n"); }
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { @@ -231,9 +276,13 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, kfree(entry); } } + spin_unlock_irqrestore(&vis_hash_lock, flags);
- return bytes_written; + seq_printf(seq, "%s", buff); + kfree(buff); + + return 0; }
/* add the info packet to the send list, if it was not diff --git a/vis.h b/vis.h index 9c1fd77..5dd6521 100644 --- a/vis.h +++ b/vis.h @@ -47,8 +47,7 @@ struct recvlist_node { extern struct hashtable_t *vis_hash; extern spinlock_t vis_hash_lock;
-ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int vis_seq_print_text(struct seq_file *seq, void *offset); void receive_server_sync_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, int vis_info_len);
batctl must read the tables exported by batman-adv from debugfs as the old files in /sys/class/net/bat0/mesh/ were removed to follow the sysfs guidelines.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- Please apply on top of batctl-0.2.x branch.
Makefile | 4 +- debug.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debug.h | 32 +++++++++++++++++++ main.c | 7 ++-- sys.c | 51 ------------------------------ sys.h | 8 ----- vis.c | 20 ++++++----- 7 files changed, 152 insertions(+), 73 deletions(-) create mode 100644 debug.c create mode 100644 debug.h
diff --git a/Makefile b/Makefile index ff877ea..4071af1 100644 --- a/Makefile +++ b/Makefile @@ -39,8 +39,8 @@ SRC_FILES = "(.c)|(.h)|(Makefile)|(INSTALL)|(LIESMICH)|(README EXTRA_MODULES_C := bisect.c EXTRA_MODULES_H := bisect.h
-SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) -SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) +SRC_C = main.c bat-hosts.c functions.c sys.c debug.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) +SRC_H = main.h bat-hosts.h functions.h sys.h debug.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) SRC_O = $(SRC_C:.c=.o)
PACKAGE_NAME = batctl diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..e8edb9d --- /dev/null +++ b/debug.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner lindner_marek@yahoo.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <dirent.h> + +#include "main.h" +#include "debug.h" +#include "debugfs.h" +#include "functions.h" + +void originators_usage(void) +{ + printf("Usage: batctl [options] originators \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the originator table continuously\n"); +} + +void trans_local_usage(void) +{ + printf("Usage: batctl [options] translocal \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the local translation table continuously\n"); +} + +void trans_global_usage(void) +{ + printf("Usage: batctl [options] transglobal \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the global translation table continuously\n"); +} + +void gateways_usage(void) +{ + printf("Usage: batctl [options] gateways \n"); + printf("options:\n"); + printf(" \t -h print this help\n"); + printf(" \t -n don't replace mac addresses with bat-host names\n"); + printf(" \t -w watch mode - refresh the gateway server list continuously\n"); +} + +int handle_debug_table(int argc, char **argv, char *file_path, void table_usage(void)) +{ + int optchar, read_opt = USE_BAT_HOSTS; + char full_path[MAX_PATH+1]; + char *debugfs_mnt; + + while ((optchar = getopt(argc, argv, "hnw")) != -1) { + switch (optchar) { + case 'h': + table_usage(); + return EXIT_SUCCESS; + case 'n': + read_opt &= ~USE_BAT_HOSTS; + break; + case 'w': + read_opt |= CLR_CONT_READ; + break; + default: + table_usage(); + return EXIT_FAILURE; + } + } + + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + return EXIT_FAILURE; + } + + debugfs_make_path(DEBUG_BATIF_PATH "/", full_path, sizeof(full_path)); + return read_file(full_path, file_path, read_opt); +} \ No newline at end of file diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..2c6e228 --- /dev/null +++ b/debug.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner lindner_marek@yahoo.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#define DEBUG_BATIF_PATH "batman_adv/bat0" +#define DEBUG_ORIGINATORS "originators" +#define DEBUG_TRANSTABLE_LOCAL "transtable_local" +#define DEBUG_TRANSTABLE_GLOBAL "transtable_global" +#define DEBUG_VIS_DATA "vis_data" + +void originators_usage(void); +void trans_local_usage(void); +void trans_global_usage(void); +int handle_debug_table(int argc, char **argv, char *file_path, void table_usage(void)); diff --git a/main.c b/main.c index 87bd853..55a59db 100644 --- a/main.c +++ b/main.c @@ -30,6 +30,7 @@
#include "main.h" #include "sys.h" +#include "debug.h" #include "ping.h" #include "traceroute.h" #include "tcpdump.h" @@ -99,15 +100,15 @@ int main(int argc, char **argv)
} else if ((strcmp(argv[1], "originators") == 0) || (strcmp(argv[1], "o") == 0)) {
- ret = handle_sys_table(argc - 1, argv + 1, SYS_ORIGINATORS, originators_usage); + ret = handle_debug_table(argc - 1, argv + 1, DEBUG_ORIGINATORS, originators_usage);
} else if ((strcmp(argv[1], "translocal") == 0) || (strcmp(argv[1], "tl") == 0)) {
- ret = handle_sys_table(argc - 1, argv + 1, SYS_TRANSTABLE_LOCAL, trans_local_usage); + ret = handle_debug_table(argc - 1, argv + 1, DEBUG_TRANSTABLE_LOCAL, trans_local_usage);
} else if ((strcmp(argv[1], "transglobal") == 0) || (strcmp(argv[1], "tg") == 0)) {
- ret = handle_sys_table(argc - 1, argv + 1, SYS_TRANSTABLE_GLOBAL, trans_global_usage); + ret = handle_debug_table(argc - 1, argv + 1, DEBUG_TRANSTABLE_GLOBAL, trans_global_usage);
} else if ((strcmp(argv[1], "loglevel") == 0) || (strcmp(argv[1], "ll") == 0)) {
diff --git a/sys.c b/sys.c index c8a7c26..2de9c4a 100644 --- a/sys.c +++ b/sys.c @@ -242,57 +242,6 @@ out: return res; }
-void originators_usage(void) -{ - printf("Usage: batctl [options] originators \n"); - printf("options:\n"); - printf(" \t -h print this help\n"); - printf(" \t -n don't replace mac addresses with bat-host names\n"); - printf(" \t -w watch mode - refresh the originator table continuously\n"); -} - -void trans_local_usage(void) -{ - printf("Usage: batctl [options] translocal \n"); - printf("options:\n"); - printf(" \t -h print this help\n"); - printf(" \t -n don't replace mac addresses with bat-host names\n"); - printf(" \t -w watch mode - refresh the local translation table continuously\n"); -} - -void trans_global_usage(void) -{ - printf("Usage: batctl [options] transglobal \n"); - printf("options:\n"); - printf(" \t -h print this help\n"); - printf(" \t -n don't replace mac addresses with bat-host names\n"); - printf(" \t -w watch mode - refresh the global translation table continuously\n"); -} - -int handle_sys_table(int argc, char **argv, char *file_path, void table_usage(void)) -{ - int optchar, read_opt = USE_BAT_HOSTS; - - while ((optchar = getopt(argc, argv, "hnw")) != -1) { - switch (optchar) { - case 'h': - table_usage(); - return EXIT_SUCCESS; - case 'n': - read_opt &= ~USE_BAT_HOSTS; - break; - case 'w': - read_opt |= CLR_CONT_READ; - break; - default: - table_usage(); - return EXIT_FAILURE; - } - } - - return read_file(SYS_BATIF_PATH, file_path, read_opt); -} - void aggregation_usage(void) { printf("Usage: batctl [options] aggregation [0|1]\n"); diff --git a/sys.h b/sys.h index 01f9b95..4736f71 100644 --- a/sys.h +++ b/sys.h @@ -24,25 +24,17 @@ #define SYS_BATIF_PATH "/sys/class/net/bat0/mesh/" #define SYS_LOG_LEVEL "parameters/debug" #define SYS_LOG "log" -#define SYS_ORIGINATORS "originators" -#define SYS_TRANSTABLE_LOCAL "transtable_local" -#define SYS_TRANSTABLE_GLOBAL "transtable_global" #define SYS_AGGR "aggregate_ogm" #define SYS_VIS_MODE "vis_mode" -#define SYS_VIS_DATA "vis_data" #define SYS_ORIG_INTERVAL "orig_interval" #define SYS_IFACE_PATH "/sys/class/net" #define SYS_MESH_IFACE_FMT SYS_IFACE_PATH"/%s/batman_adv/mesh_iface" #define SYS_IFACE_STATUS_FMT SYS_IFACE_PATH"/%s/batman_adv/iface_status"
-void originators_usage(void); -void trans_local_usage(void); -void trans_global_usage(void); void aggregation_usage(void); void vis_mode_usage(void); void orig_interval_usage(void); int log_print(int argc, char **argv); int interface(int argc, char **argv); int handle_loglevel(int argc, char **argv); -int handle_sys_table(int argc, char **argv, char *file_path, void table_usage(void)); int handle_sys_setting(int argc, char **argv, char *file_path, void setting_usage(void)); diff --git a/vis.c b/vis.c index d09b8db..36152cf 100644 --- a/vis.c +++ b/vis.c @@ -31,7 +31,8 @@ #include "vis.h" #include "functions.h" #include "bat-hosts.h" -#include "sys.h" +#include "debug.h" +#include "debugfs.h"
#define TQ_MAX_VALUE 255
@@ -57,9 +58,9 @@ static bool with_names = true;
static void usage(void) { - printf("batctl vis dot {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); + printf("batctl vis_data dot {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); printf("or\n"); - printf("batctl vis json {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); + printf("batctl vis_data json {-h}{--no-HNA|-H} {--no-2nd|-2} {--numbers|-n}\n"); }
static void dot_print_tq(char *orig, char *from, const long tq) @@ -165,15 +166,16 @@ const struct funcs json_funcs = { json_print_tq,
static FILE *open_vis(void) { - char full_path[500]; + char full_path[MAX_PATH+1]; + char *debugfs_mnt;
- if (check_proc_dir("/proc") != EXIT_SUCCESS) + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); return NULL; + }
- strncpy(full_path, SYS_BATIF_PATH, strlen(SYS_BATIF_PATH)); - full_path[strlen(SYS_BATIF_PATH)] = '\0'; - strncat(full_path, SYS_VIS_DATA, - sizeof(full_path) - strlen(full_path)); + debugfs_make_path(DEBUG_BATIF_PATH "/" DEBUG_VIS_DATA, full_path, sizeof(full_path));
return fopen(full_path, "r"); }
b.a.t.m.a.n@lists.open-mesh.org