11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * net-sysfs.c - network device class and attributes 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (c) 2003 Stephen Hemminger <shemminger@osdl.org> 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include <linux/config.h> 131da177e4SLinus Torvalds #include <linux/kernel.h> 141da177e4SLinus Torvalds #include <linux/netdevice.h> 151da177e4SLinus Torvalds #include <linux/if_arp.h> 161da177e4SLinus Torvalds #include <net/sock.h> 171da177e4SLinus Torvalds #include <linux/rtnetlink.h> 181da177e4SLinus Torvalds #include <linux/wireless.h> 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #define to_class_dev(obj) container_of(obj,struct class_device,kobj) 211da177e4SLinus Torvalds #define to_net_dev(class) container_of(class, struct net_device, class_dev) 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds static const char fmt_hex[] = "%#x\n"; 24d1102b59SDavid S. Miller static const char fmt_long_hex[] = "%#lx\n"; 251da177e4SLinus Torvalds static const char fmt_dec[] = "%d\n"; 261da177e4SLinus Torvalds static const char fmt_ulong[] = "%lu\n"; 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds static inline int dev_isalive(const struct net_device *dev) 291da177e4SLinus Torvalds { 301da177e4SLinus Torvalds return dev->reg_state == NETREG_REGISTERED; 311da177e4SLinus Torvalds } 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds /* use same locking rules as GIF* ioctl's */ 341da177e4SLinus Torvalds static ssize_t netdev_show(const struct class_device *cd, char *buf, 351da177e4SLinus Torvalds ssize_t (*format)(const struct net_device *, char *)) 361da177e4SLinus Torvalds { 371da177e4SLinus Torvalds struct net_device *net = to_net_dev(cd); 381da177e4SLinus Torvalds ssize_t ret = -EINVAL; 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds read_lock(&dev_base_lock); 411da177e4SLinus Torvalds if (dev_isalive(net)) 421da177e4SLinus Torvalds ret = (*format)(net, buf); 431da177e4SLinus Torvalds read_unlock(&dev_base_lock); 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds return ret; 461da177e4SLinus Torvalds } 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds /* generate a show function for simple field */ 491da177e4SLinus Torvalds #define NETDEVICE_SHOW(field, format_string) \ 501da177e4SLinus Torvalds static ssize_t format_##field(const struct net_device *net, char *buf) \ 511da177e4SLinus Torvalds { \ 521da177e4SLinus Torvalds return sprintf(buf, format_string, net->field); \ 531da177e4SLinus Torvalds } \ 541da177e4SLinus Torvalds static ssize_t show_##field(struct class_device *cd, char *buf) \ 551da177e4SLinus Torvalds { \ 561da177e4SLinus Torvalds return netdev_show(cd, buf, format_##field); \ 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds /* use same locking and permission rules as SIF* ioctl's */ 611da177e4SLinus Torvalds static ssize_t netdev_store(struct class_device *dev, 621da177e4SLinus Torvalds const char *buf, size_t len, 631da177e4SLinus Torvalds int (*set)(struct net_device *, unsigned long)) 641da177e4SLinus Torvalds { 651da177e4SLinus Torvalds struct net_device *net = to_net_dev(dev); 661da177e4SLinus Torvalds char *endp; 671da177e4SLinus Torvalds unsigned long new; 681da177e4SLinus Torvalds int ret = -EINVAL; 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 711da177e4SLinus Torvalds return -EPERM; 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds new = simple_strtoul(buf, &endp, 0); 741da177e4SLinus Torvalds if (endp == buf) 751da177e4SLinus Torvalds goto err; 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds rtnl_lock(); 781da177e4SLinus Torvalds if (dev_isalive(net)) { 791da177e4SLinus Torvalds if ((ret = (*set)(net, new)) == 0) 801da177e4SLinus Torvalds ret = len; 811da177e4SLinus Torvalds } 821da177e4SLinus Torvalds rtnl_unlock(); 831da177e4SLinus Torvalds err: 841da177e4SLinus Torvalds return ret; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds 87*fd586bacSKay Sievers NETDEVICE_SHOW(addr_len, fmt_dec); 88*fd586bacSKay Sievers NETDEVICE_SHOW(iflink, fmt_dec); 89*fd586bacSKay Sievers NETDEVICE_SHOW(ifindex, fmt_dec); 90*fd586bacSKay Sievers NETDEVICE_SHOW(features, fmt_long_hex); 91*fd586bacSKay Sievers NETDEVICE_SHOW(type, fmt_dec); 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds /* use same locking rules as GIFHWADDR ioctl's */ 941da177e4SLinus Torvalds static ssize_t format_addr(char *buf, const unsigned char *addr, int len) 951da177e4SLinus Torvalds { 961da177e4SLinus Torvalds int i; 971da177e4SLinus Torvalds char *cp = buf; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds for (i = 0; i < len; i++) 1001da177e4SLinus Torvalds cp += sprintf(cp, "%02x%c", addr[i], 1011da177e4SLinus Torvalds i == (len - 1) ? '\n' : ':'); 1021da177e4SLinus Torvalds return cp - buf; 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds static ssize_t show_address(struct class_device *dev, char *buf) 1061da177e4SLinus Torvalds { 1071da177e4SLinus Torvalds struct net_device *net = to_net_dev(dev); 1081da177e4SLinus Torvalds ssize_t ret = -EINVAL; 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds read_lock(&dev_base_lock); 1111da177e4SLinus Torvalds if (dev_isalive(net)) 1121da177e4SLinus Torvalds ret = format_addr(buf, net->dev_addr, net->addr_len); 1131da177e4SLinus Torvalds read_unlock(&dev_base_lock); 1141da177e4SLinus Torvalds return ret; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds static ssize_t show_broadcast(struct class_device *dev, char *buf) 1181da177e4SLinus Torvalds { 1191da177e4SLinus Torvalds struct net_device *net = to_net_dev(dev); 1201da177e4SLinus Torvalds if (dev_isalive(net)) 1211da177e4SLinus Torvalds return format_addr(buf, net->broadcast, net->addr_len); 1221da177e4SLinus Torvalds return -EINVAL; 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds static ssize_t show_carrier(struct class_device *dev, char *buf) 1261da177e4SLinus Torvalds { 1271da177e4SLinus Torvalds struct net_device *netdev = to_net_dev(dev); 1281da177e4SLinus Torvalds if (netif_running(netdev)) { 1291da177e4SLinus Torvalds return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev)); 1301da177e4SLinus Torvalds } 1311da177e4SLinus Torvalds return -EINVAL; 1321da177e4SLinus Torvalds } 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds /* read-write attributes */ 1351da177e4SLinus Torvalds NETDEVICE_SHOW(mtu, fmt_dec); 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds static int change_mtu(struct net_device *net, unsigned long new_mtu) 1381da177e4SLinus Torvalds { 1391da177e4SLinus Torvalds return dev_set_mtu(net, (int) new_mtu); 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len) 1431da177e4SLinus Torvalds { 1441da177e4SLinus Torvalds return netdev_store(dev, buf, len, change_mtu); 1451da177e4SLinus Torvalds } 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds NETDEVICE_SHOW(flags, fmt_hex); 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds static int change_flags(struct net_device *net, unsigned long new_flags) 1501da177e4SLinus Torvalds { 1511da177e4SLinus Torvalds return dev_change_flags(net, (unsigned) new_flags); 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len) 1551da177e4SLinus Torvalds { 1561da177e4SLinus Torvalds return netdev_store(dev, buf, len, change_flags); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds NETDEVICE_SHOW(tx_queue_len, fmt_ulong); 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds static int change_tx_queue_len(struct net_device *net, unsigned long new_len) 1621da177e4SLinus Torvalds { 1631da177e4SLinus Torvalds net->tx_queue_len = new_len; 1641da177e4SLinus Torvalds return 0; 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len) 1681da177e4SLinus Torvalds { 1691da177e4SLinus Torvalds return netdev_store(dev, buf, len, change_tx_queue_len); 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 172699a4114SStephen Hemminger NETDEVICE_SHOW(weight, fmt_dec); 173699a4114SStephen Hemminger 174699a4114SStephen Hemminger static int change_weight(struct net_device *net, unsigned long new_weight) 175699a4114SStephen Hemminger { 176699a4114SStephen Hemminger net->weight = new_weight; 177699a4114SStephen Hemminger return 0; 178699a4114SStephen Hemminger } 179699a4114SStephen Hemminger 180699a4114SStephen Hemminger static ssize_t store_weight(struct class_device *dev, const char *buf, size_t len) 181699a4114SStephen Hemminger { 182699a4114SStephen Hemminger return netdev_store(dev, buf, len, change_weight); 183699a4114SStephen Hemminger } 184699a4114SStephen Hemminger 185*fd586bacSKay Sievers static struct class_device_attribute net_class_attributes[] = { 186*fd586bacSKay Sievers __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), 187*fd586bacSKay Sievers __ATTR(iflink, S_IRUGO, show_iflink, NULL), 188*fd586bacSKay Sievers __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), 189*fd586bacSKay Sievers __ATTR(features, S_IRUGO, show_features, NULL), 190*fd586bacSKay Sievers __ATTR(type, S_IRUGO, show_type, NULL), 191*fd586bacSKay Sievers __ATTR(address, S_IRUGO, show_address, NULL), 192*fd586bacSKay Sievers __ATTR(broadcast, S_IRUGO, show_broadcast, NULL), 193*fd586bacSKay Sievers __ATTR(carrier, S_IRUGO, show_carrier, NULL), 194*fd586bacSKay Sievers __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu), 195*fd586bacSKay Sievers __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags), 196*fd586bacSKay Sievers __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, 197*fd586bacSKay Sievers store_tx_queue_len), 198*fd586bacSKay Sievers __ATTR(weight, S_IRUGO | S_IWUSR, show_weight, store_weight), 199*fd586bacSKay Sievers {} 2001da177e4SLinus Torvalds }; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds /* Show a given an attribute in the statistics group */ 2031da177e4SLinus Torvalds static ssize_t netstat_show(const struct class_device *cd, char *buf, 2041da177e4SLinus Torvalds unsigned long offset) 2051da177e4SLinus Torvalds { 2061da177e4SLinus Torvalds struct net_device *dev = to_net_dev(cd); 2071da177e4SLinus Torvalds struct net_device_stats *stats; 2081da177e4SLinus Torvalds ssize_t ret = -EINVAL; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds if (offset > sizeof(struct net_device_stats) || 2111da177e4SLinus Torvalds offset % sizeof(unsigned long) != 0) 2121da177e4SLinus Torvalds WARN_ON(1); 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds read_lock(&dev_base_lock); 2151da177e4SLinus Torvalds if (dev_isalive(dev) && dev->get_stats && 2161da177e4SLinus Torvalds (stats = (*dev->get_stats)(dev))) 2171da177e4SLinus Torvalds ret = sprintf(buf, fmt_ulong, 2181da177e4SLinus Torvalds *(unsigned long *)(((u8 *) stats) + offset)); 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds read_unlock(&dev_base_lock); 2211da177e4SLinus Torvalds return ret; 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds /* generate a read-only statistics attribute */ 2251da177e4SLinus Torvalds #define NETSTAT_ENTRY(name) \ 2261da177e4SLinus Torvalds static ssize_t show_##name(struct class_device *cd, char *buf) \ 2271da177e4SLinus Torvalds { \ 2281da177e4SLinus Torvalds return netstat_show(cd, buf, \ 2291da177e4SLinus Torvalds offsetof(struct net_device_stats, name)); \ 2301da177e4SLinus Torvalds } \ 2311da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds NETSTAT_ENTRY(rx_packets); 2341da177e4SLinus Torvalds NETSTAT_ENTRY(tx_packets); 2351da177e4SLinus Torvalds NETSTAT_ENTRY(rx_bytes); 2361da177e4SLinus Torvalds NETSTAT_ENTRY(tx_bytes); 2371da177e4SLinus Torvalds NETSTAT_ENTRY(rx_errors); 2381da177e4SLinus Torvalds NETSTAT_ENTRY(tx_errors); 2391da177e4SLinus Torvalds NETSTAT_ENTRY(rx_dropped); 2401da177e4SLinus Torvalds NETSTAT_ENTRY(tx_dropped); 2411da177e4SLinus Torvalds NETSTAT_ENTRY(multicast); 2421da177e4SLinus Torvalds NETSTAT_ENTRY(collisions); 2431da177e4SLinus Torvalds NETSTAT_ENTRY(rx_length_errors); 2441da177e4SLinus Torvalds NETSTAT_ENTRY(rx_over_errors); 2451da177e4SLinus Torvalds NETSTAT_ENTRY(rx_crc_errors); 2461da177e4SLinus Torvalds NETSTAT_ENTRY(rx_frame_errors); 2471da177e4SLinus Torvalds NETSTAT_ENTRY(rx_fifo_errors); 2481da177e4SLinus Torvalds NETSTAT_ENTRY(rx_missed_errors); 2491da177e4SLinus Torvalds NETSTAT_ENTRY(tx_aborted_errors); 2501da177e4SLinus Torvalds NETSTAT_ENTRY(tx_carrier_errors); 2511da177e4SLinus Torvalds NETSTAT_ENTRY(tx_fifo_errors); 2521da177e4SLinus Torvalds NETSTAT_ENTRY(tx_heartbeat_errors); 2531da177e4SLinus Torvalds NETSTAT_ENTRY(tx_window_errors); 2541da177e4SLinus Torvalds NETSTAT_ENTRY(rx_compressed); 2551da177e4SLinus Torvalds NETSTAT_ENTRY(tx_compressed); 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds static struct attribute *netstat_attrs[] = { 2581da177e4SLinus Torvalds &class_device_attr_rx_packets.attr, 2591da177e4SLinus Torvalds &class_device_attr_tx_packets.attr, 2601da177e4SLinus Torvalds &class_device_attr_rx_bytes.attr, 2611da177e4SLinus Torvalds &class_device_attr_tx_bytes.attr, 2621da177e4SLinus Torvalds &class_device_attr_rx_errors.attr, 2631da177e4SLinus Torvalds &class_device_attr_tx_errors.attr, 2641da177e4SLinus Torvalds &class_device_attr_rx_dropped.attr, 2651da177e4SLinus Torvalds &class_device_attr_tx_dropped.attr, 2661da177e4SLinus Torvalds &class_device_attr_multicast.attr, 2671da177e4SLinus Torvalds &class_device_attr_collisions.attr, 2681da177e4SLinus Torvalds &class_device_attr_rx_length_errors.attr, 2691da177e4SLinus Torvalds &class_device_attr_rx_over_errors.attr, 2701da177e4SLinus Torvalds &class_device_attr_rx_crc_errors.attr, 2711da177e4SLinus Torvalds &class_device_attr_rx_frame_errors.attr, 2721da177e4SLinus Torvalds &class_device_attr_rx_fifo_errors.attr, 2731da177e4SLinus Torvalds &class_device_attr_rx_missed_errors.attr, 2741da177e4SLinus Torvalds &class_device_attr_tx_aborted_errors.attr, 2751da177e4SLinus Torvalds &class_device_attr_tx_carrier_errors.attr, 2761da177e4SLinus Torvalds &class_device_attr_tx_fifo_errors.attr, 2771da177e4SLinus Torvalds &class_device_attr_tx_heartbeat_errors.attr, 2781da177e4SLinus Torvalds &class_device_attr_tx_window_errors.attr, 2791da177e4SLinus Torvalds &class_device_attr_rx_compressed.attr, 2801da177e4SLinus Torvalds &class_device_attr_tx_compressed.attr, 2811da177e4SLinus Torvalds NULL 2821da177e4SLinus Torvalds }; 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds static struct attribute_group netstat_group = { 2861da177e4SLinus Torvalds .name = "statistics", 2871da177e4SLinus Torvalds .attrs = netstat_attrs, 2881da177e4SLinus Torvalds }; 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds #ifdef WIRELESS_EXT 2911da177e4SLinus Torvalds /* helper function that does all the locking etc for wireless stats */ 2921da177e4SLinus Torvalds static ssize_t wireless_show(struct class_device *cd, char *buf, 2931da177e4SLinus Torvalds ssize_t (*format)(const struct iw_statistics *, 2941da177e4SLinus Torvalds char *)) 2951da177e4SLinus Torvalds { 2961da177e4SLinus Torvalds struct net_device *dev = to_net_dev(cd); 2971da177e4SLinus Torvalds const struct iw_statistics *iw; 2981da177e4SLinus Torvalds ssize_t ret = -EINVAL; 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds read_lock(&dev_base_lock); 3011da177e4SLinus Torvalds if (dev_isalive(dev) && dev->get_wireless_stats 3021da177e4SLinus Torvalds && (iw = dev->get_wireless_stats(dev)) != NULL) 3031da177e4SLinus Torvalds ret = (*format)(iw, buf); 3041da177e4SLinus Torvalds read_unlock(&dev_base_lock); 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds return ret; 3071da177e4SLinus Torvalds } 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds /* show function template for wireless fields */ 3101da177e4SLinus Torvalds #define WIRELESS_SHOW(name, field, format_string) \ 3111da177e4SLinus Torvalds static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \ 3121da177e4SLinus Torvalds { \ 3131da177e4SLinus Torvalds return sprintf(buf, format_string, iw->field); \ 3141da177e4SLinus Torvalds } \ 3151da177e4SLinus Torvalds static ssize_t show_iw_##name(struct class_device *cd, char *buf) \ 3161da177e4SLinus Torvalds { \ 3171da177e4SLinus Torvalds return wireless_show(cd, buf, format_iw_##name); \ 3181da177e4SLinus Torvalds } \ 3191da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL) 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds WIRELESS_SHOW(status, status, fmt_hex); 3221da177e4SLinus Torvalds WIRELESS_SHOW(link, qual.qual, fmt_dec); 3231da177e4SLinus Torvalds WIRELESS_SHOW(level, qual.level, fmt_dec); 3241da177e4SLinus Torvalds WIRELESS_SHOW(noise, qual.noise, fmt_dec); 3251da177e4SLinus Torvalds WIRELESS_SHOW(nwid, discard.nwid, fmt_dec); 3261da177e4SLinus Torvalds WIRELESS_SHOW(crypt, discard.code, fmt_dec); 3271da177e4SLinus Torvalds WIRELESS_SHOW(fragment, discard.fragment, fmt_dec); 3281da177e4SLinus Torvalds WIRELESS_SHOW(misc, discard.misc, fmt_dec); 3291da177e4SLinus Torvalds WIRELESS_SHOW(retries, discard.retries, fmt_dec); 3301da177e4SLinus Torvalds WIRELESS_SHOW(beacon, miss.beacon, fmt_dec); 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds static struct attribute *wireless_attrs[] = { 3331da177e4SLinus Torvalds &class_device_attr_status.attr, 3341da177e4SLinus Torvalds &class_device_attr_link.attr, 3351da177e4SLinus Torvalds &class_device_attr_level.attr, 3361da177e4SLinus Torvalds &class_device_attr_noise.attr, 3371da177e4SLinus Torvalds &class_device_attr_nwid.attr, 3381da177e4SLinus Torvalds &class_device_attr_crypt.attr, 3391da177e4SLinus Torvalds &class_device_attr_fragment.attr, 3401da177e4SLinus Torvalds &class_device_attr_retries.attr, 3411da177e4SLinus Torvalds &class_device_attr_misc.attr, 3421da177e4SLinus Torvalds &class_device_attr_beacon.attr, 3431da177e4SLinus Torvalds NULL 3441da177e4SLinus Torvalds }; 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds static struct attribute_group wireless_group = { 3471da177e4SLinus Torvalds .name = "wireless", 3481da177e4SLinus Torvalds .attrs = wireless_attrs, 3491da177e4SLinus Torvalds }; 3501da177e4SLinus Torvalds #endif 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds #ifdef CONFIG_HOTPLUG 353312c004dSKay Sievers static int netdev_uevent(struct class_device *cd, char **envp, 3541da177e4SLinus Torvalds int num_envp, char *buf, int size) 3551da177e4SLinus Torvalds { 3561da177e4SLinus Torvalds struct net_device *dev = to_net_dev(cd); 3571da177e4SLinus Torvalds int i = 0; 3581da177e4SLinus Torvalds int n; 3591da177e4SLinus Torvalds 360312c004dSKay Sievers /* pass interface to uevent. */ 3611da177e4SLinus Torvalds envp[i++] = buf; 3621da177e4SLinus Torvalds n = snprintf(buf, size, "INTERFACE=%s", dev->name) + 1; 3631da177e4SLinus Torvalds buf += n; 3641da177e4SLinus Torvalds size -= n; 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds if ((size <= 0) || (i >= num_envp)) 3671da177e4SLinus Torvalds return -ENOMEM; 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds envp[i] = NULL; 3701da177e4SLinus Torvalds return 0; 3711da177e4SLinus Torvalds } 3721da177e4SLinus Torvalds #endif 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds /* 3751da177e4SLinus Torvalds * netdev_release -- destroy and free a dead device. 3761da177e4SLinus Torvalds * Called when last reference to class_device kobject is gone. 3771da177e4SLinus Torvalds */ 3781da177e4SLinus Torvalds static void netdev_release(struct class_device *cd) 3791da177e4SLinus Torvalds { 3801da177e4SLinus Torvalds struct net_device *dev 3811da177e4SLinus Torvalds = container_of(cd, struct net_device, class_dev); 3821da177e4SLinus Torvalds 3831da177e4SLinus Torvalds BUG_ON(dev->reg_state != NETREG_RELEASED); 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds kfree((char *)dev - dev->padded); 3861da177e4SLinus Torvalds } 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds static struct class net_class = { 3891da177e4SLinus Torvalds .name = "net", 3901da177e4SLinus Torvalds .release = netdev_release, 391*fd586bacSKay Sievers .class_dev_attrs = net_class_attributes, 3921da177e4SLinus Torvalds #ifdef CONFIG_HOTPLUG 393312c004dSKay Sievers .uevent = netdev_uevent, 3941da177e4SLinus Torvalds #endif 3951da177e4SLinus Torvalds }; 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds void netdev_unregister_sysfs(struct net_device * net) 3981da177e4SLinus Torvalds { 3991da177e4SLinus Torvalds struct class_device * class_dev = &(net->class_dev); 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds if (net->get_stats) 4021da177e4SLinus Torvalds sysfs_remove_group(&class_dev->kobj, &netstat_group); 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds #ifdef WIRELESS_EXT 4051da177e4SLinus Torvalds if (net->get_wireless_stats) 4061da177e4SLinus Torvalds sysfs_remove_group(&class_dev->kobj, &wireless_group); 4071da177e4SLinus Torvalds #endif 4081da177e4SLinus Torvalds class_device_del(class_dev); 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds } 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds /* Create sysfs entries for network device. */ 4131da177e4SLinus Torvalds int netdev_register_sysfs(struct net_device *net) 4141da177e4SLinus Torvalds { 4151da177e4SLinus Torvalds struct class_device *class_dev = &(net->class_dev); 4161da177e4SLinus Torvalds int ret; 4171da177e4SLinus Torvalds 4181da177e4SLinus Torvalds class_dev->class = &net_class; 4191da177e4SLinus Torvalds class_dev->class_data = net; 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE); 4221da177e4SLinus Torvalds if ((ret = class_device_register(class_dev))) 4231da177e4SLinus Torvalds goto out; 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds if (net->get_stats && 4261da177e4SLinus Torvalds (ret = sysfs_create_group(&class_dev->kobj, &netstat_group))) 4271da177e4SLinus Torvalds goto out_unreg; 4281da177e4SLinus Torvalds 4291da177e4SLinus Torvalds #ifdef WIRELESS_EXT 4301da177e4SLinus Torvalds if (net->get_wireless_stats && 4311da177e4SLinus Torvalds (ret = sysfs_create_group(&class_dev->kobj, &wireless_group))) 4321da177e4SLinus Torvalds goto out_cleanup; 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds return 0; 4351da177e4SLinus Torvalds out_cleanup: 4361da177e4SLinus Torvalds if (net->get_stats) 4371da177e4SLinus Torvalds sysfs_remove_group(&class_dev->kobj, &netstat_group); 4381da177e4SLinus Torvalds #else 4391da177e4SLinus Torvalds return 0; 4401da177e4SLinus Torvalds #endif 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds out_unreg: 4431da177e4SLinus Torvalds printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n", 4441da177e4SLinus Torvalds net->name, ret); 4451da177e4SLinus Torvalds class_device_unregister(class_dev); 4461da177e4SLinus Torvalds out: 4471da177e4SLinus Torvalds return ret; 4481da177e4SLinus Torvalds } 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds int netdev_sysfs_init(void) 4511da177e4SLinus Torvalds { 4521da177e4SLinus Torvalds return class_register(&net_class); 4531da177e4SLinus Torvalds } 454