linux/net/core/net-sysfs.c
<<
>>
Prefs
   1/*
   2 * net-sysfs.c - network device class and attributes
   3 *
   4 * Copyright (c) 2003 Stephen Hemminger <shemminger@osdl.org>
   5 *
   6 *      This program is free software; you can redistribute it and/or
   7 *      modify it under the terms of the GNU General Public License
   8 *      as published by the Free Software Foundation; either version
   9 *      2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/capability.h>
  13#include <linux/kernel.h>
  14#include <linux/netdevice.h>
  15#include <linux/if_arp.h>
  16#include <net/sock.h>
  17#include <linux/rtnetlink.h>
  18#include <linux/wireless.h>
  19#include <net/iw_handler.h>
  20
  21#include "net-sysfs.h"
  22
  23#ifdef CONFIG_SYSFS
  24static const char fmt_hex[] = "%#x\n";
  25static const char fmt_long_hex[] = "%#lx\n";
  26static const char fmt_dec[] = "%d\n";
  27static const char fmt_ulong[] = "%lu\n";
  28
  29static inline int dev_isalive(const struct net_device *dev)
  30{
  31        return dev->reg_state <= NETREG_REGISTERED;
  32}
  33
  34/* use same locking rules as GIF* ioctl's */
  35static ssize_t netdev_show(const struct device *dev,
  36                           struct device_attribute *attr, char *buf,
  37                           ssize_t (*format)(const struct net_device *, char *))
  38{
  39        struct net_device *net = to_net_dev(dev);
  40        ssize_t ret = -EINVAL;
  41
  42        read_lock(&dev_base_lock);
  43        if (dev_isalive(net))
  44                ret = (*format)(net, buf);
  45        read_unlock(&dev_base_lock);
  46
  47        return ret;
  48}
  49
  50/* generate a show function for simple field */
  51#define NETDEVICE_SHOW(field, format_string)                            \
  52static ssize_t format_##field(const struct net_device *net, char *buf)  \
  53{                                                                       \
  54        return sprintf(buf, format_string, net->field);                 \
  55}                                                                       \
  56static ssize_t show_##field(struct device *dev,                         \
  57                            struct device_attribute *attr, char *buf)   \
  58{                                                                       \
  59        return netdev_show(dev, attr, buf, format_##field);             \
  60}
  61
  62
  63/* use same locking and permission rules as SIF* ioctl's */
  64static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
  65                            const char *buf, size_t len,
  66                            int (*set)(struct net_device *, unsigned long))
  67{
  68        struct net_device *net = to_net_dev(dev);
  69        char *endp;
  70        unsigned long new;
  71        int ret = -EINVAL;
  72
  73        if (!capable(CAP_NET_ADMIN))
  74                return -EPERM;
  75
  76        new = simple_strtoul(buf, &endp, 0);
  77        if (endp == buf)
  78                goto err;
  79
  80        if (!rtnl_trylock())
  81                return -ERESTARTSYS;
  82
  83        if (dev_isalive(net)) {
  84                if ((ret = (*set)(net, new)) == 0)
  85                        ret = len;
  86        }
  87        rtnl_unlock();
  88 err:
  89        return ret;
  90}
  91
  92NETDEVICE_SHOW(dev_id, fmt_hex);
  93NETDEVICE_SHOW(addr_len, fmt_dec);
  94NETDEVICE_SHOW(iflink, fmt_dec);
  95NETDEVICE_SHOW(ifindex, fmt_dec);
  96NETDEVICE_SHOW(features, fmt_long_hex);
  97NETDEVICE_SHOW(type, fmt_dec);
  98NETDEVICE_SHOW(link_mode, fmt_dec);
  99
 100/* use same locking rules as GIFHWADDR ioctl's */
 101static ssize_t show_address(struct device *dev, struct device_attribute *attr,
 102                            char *buf)
 103{
 104        struct net_device *net = to_net_dev(dev);
 105        ssize_t ret = -EINVAL;
 106
 107        read_lock(&dev_base_lock);
 108        if (dev_isalive(net))
 109                ret = sysfs_format_mac(buf, net->dev_addr, net->addr_len);
 110        read_unlock(&dev_base_lock);
 111        return ret;
 112}
 113
 114static ssize_t show_broadcast(struct device *dev,
 115                            struct device_attribute *attr, char *buf)
 116{
 117        struct net_device *net = to_net_dev(dev);
 118        if (dev_isalive(net))
 119                return sysfs_format_mac(buf, net->broadcast, net->addr_len);
 120        return -EINVAL;
 121}
 122
 123static ssize_t show_carrier(struct device *dev,
 124                            struct device_attribute *attr, char *buf)
 125{
 126        struct net_device *netdev = to_net_dev(dev);
 127        if (netif_running(netdev)) {
 128                return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev));
 129        }
 130        return -EINVAL;
 131}
 132
 133static ssize_t show_dormant(struct device *dev,
 134                            struct device_attribute *attr, char *buf)
 135{
 136        struct net_device *netdev = to_net_dev(dev);
 137
 138        if (netif_running(netdev))
 139                return sprintf(buf, fmt_dec, !!netif_dormant(netdev));
 140
 141        return -EINVAL;
 142}
 143
 144static const char *operstates[] = {
 145        "unknown",
 146        "notpresent", /* currently unused */
 147        "down",
 148        "lowerlayerdown",
 149        "testing", /* currently unused */
 150        "dormant",
 151        "up"
 152};
 153
 154static ssize_t show_operstate(struct device *dev,
 155                              struct device_attribute *attr, char *buf)
 156{
 157        const struct net_device *netdev = to_net_dev(dev);
 158        unsigned char operstate;
 159
 160        read_lock(&dev_base_lock);
 161        operstate = netdev->operstate;
 162        if (!netif_running(netdev))
 163                operstate = IF_OPER_DOWN;
 164        read_unlock(&dev_base_lock);
 165
 166        if (operstate >= ARRAY_SIZE(operstates))
 167                return -EINVAL; /* should not happen */
 168
 169        return sprintf(buf, "%s\n", operstates[operstate]);
 170}
 171
 172/* read-write attributes */
 173NETDEVICE_SHOW(mtu, fmt_dec);
 174
 175static int change_mtu(struct net_device *net, unsigned long new_mtu)
 176{
 177        return dev_set_mtu(net, (int) new_mtu);
 178}
 179
 180static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
 181                         const char *buf, size_t len)
 182{
 183        return netdev_store(dev, attr, buf, len, change_mtu);
 184}
 185
 186NETDEVICE_SHOW(flags, fmt_hex);
 187
 188static int change_flags(struct net_device *net, unsigned long new_flags)
 189{
 190        return dev_change_flags(net, (unsigned) new_flags);
 191}
 192
 193static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
 194                           const char *buf, size_t len)
 195{
 196        return netdev_store(dev, attr, buf, len, change_flags);
 197}
 198
 199NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
 200
 201static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
 202{
 203        net->tx_queue_len = new_len;
 204        return 0;
 205}
 206
 207static ssize_t store_tx_queue_len(struct device *dev,
 208                                  struct device_attribute *attr,
 209                                  const char *buf, size_t len)
 210{
 211        return netdev_store(dev, attr, buf, len, change_tx_queue_len);
 212}
 213
 214static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
 215                             const char *buf, size_t len)
 216{
 217        struct net_device *netdev = to_net_dev(dev);
 218        size_t count = len;
 219        ssize_t ret;
 220
 221        if (!capable(CAP_NET_ADMIN))
 222                return -EPERM;
 223
 224        /* ignore trailing newline */
 225        if (len >  0 && buf[len - 1] == '\n')
 226                --count;
 227
 228        rtnl_lock();
 229        ret = dev_set_alias(netdev, buf, count);
 230        rtnl_unlock();
 231
 232        return ret < 0 ? ret : len;
 233}
 234
 235static ssize_t show_ifalias(struct device *dev,
 236                            struct device_attribute *attr, char *buf)
 237{
 238        const struct net_device *netdev = to_net_dev(dev);
 239        ssize_t ret = 0;
 240
 241        rtnl_lock();
 242        if (netdev->ifalias)
 243                ret = sprintf(buf, "%s\n", netdev->ifalias);
 244        rtnl_unlock();
 245        return ret;
 246}
 247
 248static struct device_attribute net_class_attributes[] = {
 249        __ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
 250        __ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
 251        __ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias),
 252        __ATTR(iflink, S_IRUGO, show_iflink, NULL),
 253        __ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
 254        __ATTR(features, S_IRUGO, show_features, NULL),
 255        __ATTR(type, S_IRUGO, show_type, NULL),
 256        __ATTR(link_mode, S_IRUGO, show_link_mode, NULL),
 257        __ATTR(address, S_IRUGO, show_address, NULL),
 258        __ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
 259        __ATTR(carrier, S_IRUGO, show_carrier, NULL),
 260        __ATTR(dormant, S_IRUGO, show_dormant, NULL),
 261        __ATTR(operstate, S_IRUGO, show_operstate, NULL),
 262        __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
 263        __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
 264        __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
 265               store_tx_queue_len),
 266        {}
 267};
 268
 269/* Show a given an attribute in the statistics group */
 270static ssize_t netstat_show(const struct device *d,
 271                            struct device_attribute *attr, char *buf,
 272                            unsigned long offset)
 273{
 274        struct net_device *dev = to_net_dev(d);
 275        ssize_t ret = -EINVAL;
 276
 277        WARN_ON(offset > sizeof(struct net_device_stats) ||
 278                        offset % sizeof(unsigned long) != 0);
 279
 280        read_lock(&dev_base_lock);
 281        if (dev_isalive(dev)) {
 282                const struct net_device_stats *stats = dev_get_stats(dev);
 283                ret = sprintf(buf, fmt_ulong,
 284                              *(unsigned long *)(((u8 *) stats) + offset));
 285        }
 286        read_unlock(&dev_base_lock);
 287        return ret;
 288}
 289
 290/* generate a read-only statistics attribute */
 291#define NETSTAT_ENTRY(name)                                             \
 292static ssize_t show_##name(struct device *d,                            \
 293                           struct device_attribute *attr, char *buf)    \
 294{                                                                       \
 295        return netstat_show(d, attr, buf,                               \
 296                            offsetof(struct net_device_stats, name));   \
 297}                                                                       \
 298static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 299
 300NETSTAT_ENTRY(rx_packets);
 301NETSTAT_ENTRY(tx_packets);
 302NETSTAT_ENTRY(rx_bytes);
 303NETSTAT_ENTRY(tx_bytes);
 304NETSTAT_ENTRY(rx_errors);
 305NETSTAT_ENTRY(tx_errors);
 306NETSTAT_ENTRY(rx_dropped);
 307NETSTAT_ENTRY(tx_dropped);
 308NETSTAT_ENTRY(multicast);
 309NETSTAT_ENTRY(collisions);
 310NETSTAT_ENTRY(rx_length_errors);
 311NETSTAT_ENTRY(rx_over_errors);
 312NETSTAT_ENTRY(rx_crc_errors);
 313NETSTAT_ENTRY(rx_frame_errors);
 314NETSTAT_ENTRY(rx_fifo_errors);
 315NETSTAT_ENTRY(rx_missed_errors);
 316NETSTAT_ENTRY(tx_aborted_errors);
 317NETSTAT_ENTRY(tx_carrier_errors);
 318NETSTAT_ENTRY(tx_fifo_errors);
 319NETSTAT_ENTRY(tx_heartbeat_errors);
 320NETSTAT_ENTRY(tx_window_errors);
 321NETSTAT_ENTRY(rx_compressed);
 322NETSTAT_ENTRY(tx_compressed);
 323
 324static struct attribute *netstat_attrs[] = {
 325        &dev_attr_rx_packets.attr,
 326        &dev_attr_tx_packets.attr,
 327        &dev_attr_rx_bytes.attr,
 328        &dev_attr_tx_bytes.attr,
 329        &dev_attr_rx_errors.attr,
 330        &dev_attr_tx_errors.attr,
 331        &dev_attr_rx_dropped.attr,
 332        &dev_attr_tx_dropped.attr,
 333        &dev_attr_multicast.attr,
 334        &dev_attr_collisions.attr,
 335        &dev_attr_rx_length_errors.attr,
 336        &dev_attr_rx_over_errors.attr,
 337        &dev_attr_rx_crc_errors.attr,
 338        &dev_attr_rx_frame_errors.attr,
 339        &dev_attr_rx_fifo_errors.attr,
 340        &dev_attr_rx_missed_errors.attr,
 341        &dev_attr_tx_aborted_errors.attr,
 342        &dev_attr_tx_carrier_errors.attr,
 343        &dev_attr_tx_fifo_errors.attr,
 344        &dev_attr_tx_heartbeat_errors.attr,
 345        &dev_attr_tx_window_errors.attr,
 346        &dev_attr_rx_compressed.attr,
 347        &dev_attr_tx_compressed.attr,
 348        NULL
 349};
 350
 351
 352static struct attribute_group netstat_group = {
 353        .name  = "statistics",
 354        .attrs  = netstat_attrs,
 355};
 356
 357#ifdef CONFIG_WIRELESS_EXT_SYSFS
 358/* helper function that does all the locking etc for wireless stats */
 359static ssize_t wireless_show(struct device *d, char *buf,
 360                             ssize_t (*format)(const struct iw_statistics *,
 361                                               char *))
 362{
 363        struct net_device *dev = to_net_dev(d);
 364        const struct iw_statistics *iw = NULL;
 365        ssize_t ret = -EINVAL;
 366
 367        read_lock(&dev_base_lock);
 368        if (dev_isalive(dev)) {
 369                if (dev->wireless_handlers &&
 370                    dev->wireless_handlers->get_wireless_stats)
 371                        iw = dev->wireless_handlers->get_wireless_stats(dev);
 372                if (iw != NULL)
 373                        ret = (*format)(iw, buf);
 374        }
 375        read_unlock(&dev_base_lock);
 376
 377        return ret;
 378}
 379
 380/* show function template for wireless fields */
 381#define WIRELESS_SHOW(name, field, format_string)                       \
 382static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \
 383{                                                                       \
 384        return sprintf(buf, format_string, iw->field);                  \
 385}                                                                       \
 386static ssize_t show_iw_##name(struct device *d,                         \
 387                              struct device_attribute *attr, char *buf) \
 388{                                                                       \
 389        return wireless_show(d, buf, format_iw_##name);                 \
 390}                                                                       \
 391static DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL)
 392
 393WIRELESS_SHOW(status, status, fmt_hex);
 394WIRELESS_SHOW(link, qual.qual, fmt_dec);
 395WIRELESS_SHOW(level, qual.level, fmt_dec);
 396WIRELESS_SHOW(noise, qual.noise, fmt_dec);
 397WIRELESS_SHOW(nwid, discard.nwid, fmt_dec);
 398WIRELESS_SHOW(crypt, discard.code, fmt_dec);
 399WIRELESS_SHOW(fragment, discard.fragment, fmt_dec);
 400WIRELESS_SHOW(misc, discard.misc, fmt_dec);
 401WIRELESS_SHOW(retries, discard.retries, fmt_dec);
 402WIRELESS_SHOW(beacon, miss.beacon, fmt_dec);
 403
 404static struct attribute *wireless_attrs[] = {
 405        &dev_attr_status.attr,
 406        &dev_attr_link.attr,
 407        &dev_attr_level.attr,
 408        &dev_attr_noise.attr,
 409        &dev_attr_nwid.attr,
 410        &dev_attr_crypt.attr,
 411        &dev_attr_fragment.attr,
 412        &dev_attr_retries.attr,
 413        &dev_attr_misc.attr,
 414        &dev_attr_beacon.attr,
 415        NULL
 416};
 417
 418static struct attribute_group wireless_group = {
 419        .name = "wireless",
 420        .attrs = wireless_attrs,
 421};
 422#endif
 423
 424#endif /* CONFIG_SYSFS */
 425
 426#ifdef CONFIG_HOTPLUG
 427static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
 428{
 429        struct net_device *dev = to_net_dev(d);
 430        int retval;
 431
 432        if (!net_eq(dev_net(dev), &init_net))
 433                return 0;
 434
 435        /* pass interface to uevent. */
 436        retval = add_uevent_var(env, "INTERFACE=%s", dev->name);
 437        if (retval)
 438                goto exit;
 439
 440        /* pass ifindex to uevent.
 441         * ifindex is useful as it won't change (interface name may change)
 442         * and is what RtNetlink uses natively. */
 443        retval = add_uevent_var(env, "IFINDEX=%d", dev->ifindex);
 444
 445exit:
 446        return retval;
 447}
 448#endif
 449
 450/*
 451 *      netdev_release -- destroy and free a dead device.
 452 *      Called when last reference to device kobject is gone.
 453 */
 454static void netdev_release(struct device *d)
 455{
 456        struct net_device *dev = to_net_dev(d);
 457
 458        BUG_ON(dev->reg_state != NETREG_RELEASED);
 459
 460        kfree(dev->ifalias);
 461        kfree((char *)dev - dev->padded);
 462}
 463
 464static struct class net_class = {
 465        .name = "net",
 466        .dev_release = netdev_release,
 467#ifdef CONFIG_SYSFS
 468        .dev_attrs = net_class_attributes,
 469#endif /* CONFIG_SYSFS */
 470#ifdef CONFIG_HOTPLUG
 471        .dev_uevent = netdev_uevent,
 472#endif
 473};
 474
 475/* Delete sysfs entries but hold kobject reference until after all
 476 * netdev references are gone.
 477 */
 478void netdev_unregister_kobject(struct net_device * net)
 479{
 480        struct device *dev = &(net->dev);
 481
 482        kobject_get(&dev->kobj);
 483
 484        if (dev_net(net) != &init_net)
 485                return;
 486
 487        device_del(dev);
 488}
 489
 490/* Create sysfs entries for network device. */
 491int netdev_register_kobject(struct net_device *net)
 492{
 493        struct device *dev = &(net->dev);
 494        struct attribute_group **groups = net->sysfs_groups;
 495
 496        dev->class = &net_class;
 497        dev->platform_data = net;
 498        dev->groups = groups;
 499
 500        BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
 501        dev_set_name(dev, "%s", net->name);
 502
 503#ifdef CONFIG_SYSFS
 504        *groups++ = &netstat_group;
 505
 506#ifdef CONFIG_WIRELESS_EXT_SYSFS
 507        if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
 508                *groups++ = &wireless_group;
 509#endif
 510#endif /* CONFIG_SYSFS */
 511
 512        if (dev_net(net) != &init_net)
 513                return 0;
 514
 515        return device_add(dev);
 516}
 517
 518int netdev_class_create_file(struct class_attribute *class_attr)
 519{
 520        return class_create_file(&net_class, class_attr);
 521}
 522
 523void netdev_class_remove_file(struct class_attribute *class_attr)
 524{
 525        class_remove_file(&net_class, class_attr);
 526}
 527
 528EXPORT_SYMBOL(netdev_class_create_file);
 529EXPORT_SYMBOL(netdev_class_remove_file);
 530
 531void netdev_initialize_kobject(struct net_device *net)
 532{
 533        struct device *device = &(net->dev);
 534        device_initialize(device);
 535}
 536
 537int netdev_kobject_init(void)
 538{
 539        return class_register(&net_class);
 540}
 541