Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758129AbXFMK2k (ORCPT ); Wed, 13 Jun 2007 06:28:40 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757251AbXFMK2b (ORCPT ); Wed, 13 Jun 2007 06:28:31 -0400 Received: from TYO201.gate.nec.co.jp ([202.32.8.193]:56362 "EHLO tyo201.gate.nec.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756558AbXFMK23 (ORCPT ); Wed, 13 Jun 2007 06:28:29 -0400 Message-ID: <466FC6BB.4040105@bx.jp.nec.com> Date: Wed, 13 Jun 2007 19:28:11 +0900 From: Keiichi KII User-Agent: Thunderbird 2.0.0.0 (Windows/20070326) MIME-Version: 1.0 To: Matt Mackall CC: Andrew Morton , David Miller , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC][PATCH -mm take5 3/7] add interface for netconsole using sysfs References: <466FC455.5060001@bx.jp.nec.com> In-Reply-To: <466FC455.5060001@bx.jp.nec.com> Content-Type: text/plain; charset=ISO-2022-JP Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8581 Lines: 295 From: Keiichi KII This patch contains the following changes. create a sysfs entry for netconsole in /sys/class/misc. This entry has elements related to netconsole as follows. You can change configuration of netconsole(writable attributes such as IP address, port number and so on) and check current configuration of netconsole. -+- /sys/class/misc/ |-+- netconsole/ |-+- port1/ | |--- id [r--r--r--] unique port id | |--- local_ip [rw-r--r--] source IP to use, writable | |--- local_mac [r--r--r--] source MAC address | |--- local_port [rw-r--r--] source port number for UDP packets, writable | |--- remote_ip [rw-r--r--] port number for logging agent, writable | |--- remote_mac [rw-r--r--] MAC address for logging agent, writable | ---- remote_port [rw-r--r--] IP address for logging agent, writable |--- port2/ |--- port3/ ... Signed-off-by: Keiichi KII Signed-off-by: Takayoshi Kochi --- Index: trunk/drivers/net/netconsole.c =================================================================== --- trunk.orig/drivers/net/netconsole.c +++ trunk/drivers/net/netconsole.c @@ -45,6 +45,8 @@ #include #include #include +#include +#include MODULE_AUTHOR("Maintainer: Matt Mackall "); MODULE_DESCRIPTION("Console driver for network interfaces"); @@ -67,6 +69,7 @@ static struct netpoll np = { #ifdef CONFIG_NETCONSOLE_DYNCON struct netconsole_target { struct list_head list; + struct kobject obj; int id; struct netpoll np; }; @@ -74,6 +77,164 @@ struct netconsole_target { static LIST_HEAD(target_list); static DEFINE_SPINLOCK(target_list_lock); +static int miscdev_configured; + +static ssize_t show_id(struct netconsole_target *nt, char *buf) +{ + return sprintf(buf, "%d\n", nt->id); +} + +static ssize_t show_local_port(struct netconsole_target *nt, char *buf) +{ + return sprintf(buf, "%d\n", nt->np.local_port); +} + +static ssize_t show_remote_port(struct netconsole_target *nt, char *buf) +{ + return sprintf(buf, "%d\n", nt->np.remote_port); +} + +static ssize_t show_local_ip(struct netconsole_target *nt, char *buf) +{ + return sprintf(buf, "%d.%d.%d.%d\n", HIPQUAD(nt->np.local_ip)); +} + +static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf) +{ + return sprintf(buf, "%d.%d.%d.%d\n", HIPQUAD(nt->np.remote_ip)); +} + +static ssize_t show_local_mac(struct netconsole_target *nt, char *buf) +{ + return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", + nt->np.local_mac[0], nt->np.local_mac[1], + nt->np.local_mac[2], nt->np.local_mac[3], + nt->np.local_mac[4], nt->np.local_mac[5]); +} + +static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf) +{ + return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", + nt->np.remote_mac[0], nt->np.remote_mac[1], + nt->np.remote_mac[2], nt->np.remote_mac[3], + nt->np.remote_mac[4], nt->np.remote_mac[5]); +} + +static ssize_t store_local_port(struct netconsole_target *nt, const char *buf, + size_t count) +{ + nt->np.local_port = simple_strtol(buf, NULL, 10); + + return count; +} + +static ssize_t store_remote_port(struct netconsole_target *nt, const char *buf, + size_t count) +{ + nt->np.remote_port = simple_strtol(buf, NULL, 10); + + return count; +} + +static ssize_t store_local_ip(struct netconsole_target *nt, const char *buf, + size_t count) +{ + nt->np.local_ip = ntohl(in_aton(buf)); + + return count; +} + +static ssize_t store_remote_ip(struct netconsole_target *nt, const char *buf, + size_t count) +{ + nt->np.remote_ip = ntohl(in_aton(buf)); + + return count; +} + +static ssize_t store_remote_mac(struct netconsole_target *nt, const char *buf, + size_t count) +{ + unsigned char input_mac[ETH_ALEN] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const char *cur = buf; + int i = 0; + + input_mac[i++] = simple_strtol(cur, NULL, 16); + while ((cur = strchr(cur, ':')) != NULL) { + cur++; + input_mac[i++] = simple_strtol(cur, NULL, 16); + } + if (i != ETH_ALEN) + return -EINVAL; + memcpy(nt->np.remote_mac, input_mac, ETH_ALEN); + + return count; +} + +struct target_attr { + struct attribute attr; + ssize_t (*show)(struct netconsole_target*, char*); + ssize_t (*store)(struct netconsole_target*, const char*, + size_t count); +}; + +#define NETCON_CLASS_ATTR(_name, _mode, _show, _store) \ +struct target_attr target_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) + +static NETCON_CLASS_ATTR(id, S_IRUGO, show_id, NULL); +static NETCON_CLASS_ATTR(local_port, S_IRUGO | S_IWUSR, + show_local_port, store_local_port); +static NETCON_CLASS_ATTR(remote_port, S_IRUGO | S_IWUSR, + show_remote_port, store_remote_port); +static NETCON_CLASS_ATTR(local_ip, S_IRUGO | S_IWUSR, + show_local_ip, store_local_ip); +static NETCON_CLASS_ATTR(remote_ip, S_IRUGO | S_IWUSR, + show_remote_ip, store_remote_ip); +static NETCON_CLASS_ATTR(local_mac, S_IRUGO, show_local_mac, NULL); +static NETCON_CLASS_ATTR(remote_mac, S_IRUGO | S_IWUSR, + show_remote_mac, store_remote_mac); + +static struct attribute *target_attrs[] = { + &target_attr_id.attr, + &target_attr_local_port.attr, + &target_attr_remote_port.attr, + &target_attr_local_ip.attr, + &target_attr_remote_ip.attr, + &target_attr_local_mac.attr, + &target_attr_remote_mac.attr, + NULL +}; + +static ssize_t show_target_attr(struct kobject *kobj, + struct attribute *attr, + char *buffer) +{ + struct target_attr *na = + container_of(attr, struct target_attr, attr); + struct netconsole_target * nt = + container_of(kobj, struct netconsole_target, obj); + if (na->show) + return na->show(nt, buffer); + else + return -EIO; +} + +static ssize_t store_target_attr(struct kobject *kobj, + struct attribute *attr, + const char *buffer, size_t count) +{ + struct target_attr *na = + container_of(attr, struct target_attr, attr); + struct netconsole_target *nt = + container_of(kobj, struct netconsole_target, obj); + if (na->store) + return na->store(nt, buffer, count); + else + return -EIO; +} + static void remove_target(struct netconsole_target *nt) { unsigned long flags; @@ -86,6 +247,38 @@ static void remove_target(struct netcons kfree(nt); } +static void release_target(struct kobject *kobj) +{ + struct netconsole_target *nt = + container_of(kobj, struct netconsole_target, obj); + + remove_target(nt); +} + +static struct sysfs_ops target_sysfs_ops = { + .show = show_target_attr, + .store = store_target_attr +}; + +static struct miscdevice netconsole_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "netconsole", +}; + +static struct kobj_type target_ktype = { + .release = release_target, + .sysfs_ops = &target_sysfs_ops, + .default_attrs = target_attrs, +}; + +static int setup_target_sysfs(struct netconsole_target *nt) +{ + kobject_set_name(&nt->obj, "port%d", nt->id); + nt->obj.parent = &netconsole_miscdev.this_device->kobj; + nt->obj.ktype = &target_ktype; + return kobject_register(&nt->obj); +} + static int add_target(char* target_config) { int retval = 0; @@ -126,6 +319,7 @@ static int add_target(char* target_confi list_add(&new_target->list, &target_list); spin_unlock_irqrestore(&target_list_lock, flags); + retval = setup_target_sysfs(new_target); out: return retval; } @@ -192,7 +386,9 @@ static void cleanup_netconsole(void) unregister_console(&netconsole); list_for_each_entry_safe(nt, tmp, &target_list, list) - remove_target(nt); + kobject_unregister(&nt->obj); + if (miscdev_configured) + misc_deregister(&netconsole_miscdev); #else unregister_console(&netconsole); netpoll_cleanup(&np); @@ -205,6 +401,15 @@ static int __init init_netconsole(void) #ifdef CONFIG_NETCONSOLE_DYNCON char *p; + if (misc_register(&netconsole_miscdev)) { + printk(KERN_ERR + "netconsole: failed to register misc device for " + "name = %s, id = %d\n", + netconsole_miscdev.name, netconsole_miscdev.minor); + return -EIO; + } else + miscdev_configured = 1; + register_console(&netconsole); if (!strlen(config)) { printk(KERN_ERR "netconsole: not configured\n"); -- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/