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