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/config.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 20 #define to_class_dev(obj) container_of(obj,struct class_device,kobj) 21 #define to_net_dev(class) container_of(class, struct net_device, class_dev) 22 23 static const char fmt_hex[] = "%#x\n"; 24 static const char fmt_long_hex[] = "%#lx\n"; 25 static const char fmt_dec[] = "%d\n"; 26 static const char fmt_ulong[] = "%lu\n"; 27 28 static inline int dev_isalive(const struct net_device *dev) 29 { 30 return dev->reg_state == NETREG_REGISTERED; 31 } 32 33 /* use same locking rules as GIF* ioctl's */ 34 static ssize_t netdev_show(const struct class_device *cd, char *buf, 35 ssize_t (*format)(const struct net_device *, char *)) 36 { 37 struct net_device *net = to_net_dev(cd); 38 ssize_t ret = -EINVAL; 39 40 read_lock(&dev_base_lock); 41 if (dev_isalive(net)) 42 ret = (*format)(net, buf); 43 read_unlock(&dev_base_lock); 44 45 return ret; 46 } 47 48 /* generate a show function for simple field */ 49 #define NETDEVICE_SHOW(field, format_string) \ 50 static ssize_t format_##field(const struct net_device *net, char *buf) \ 51 { \ 52 return sprintf(buf, format_string, net->field); \ 53 } \ 54 static ssize_t show_##field(struct class_device *cd, char *buf) \ 55 { \ 56 return netdev_show(cd, buf, format_##field); \ 57 } 58 59 60 /* use same locking and permission rules as SIF* ioctl's */ 61 static ssize_t netdev_store(struct class_device *dev, 62 const char *buf, size_t len, 63 int (*set)(struct net_device *, unsigned long)) 64 { 65 struct net_device *net = to_net_dev(dev); 66 char *endp; 67 unsigned long new; 68 int ret = -EINVAL; 69 70 if (!capable(CAP_NET_ADMIN)) 71 return -EPERM; 72 73 new = simple_strtoul(buf, &endp, 0); 74 if (endp == buf) 75 goto err; 76 77 rtnl_lock(); 78 if (dev_isalive(net)) { 79 if ((ret = (*set)(net, new)) == 0) 80 ret = len; 81 } 82 rtnl_unlock(); 83 err: 84 return ret; 85 } 86 87 /* generate a read-only network device class attribute */ 88 #define NETDEVICE_ATTR(field, format_string) \ 89 NETDEVICE_SHOW(field, format_string) \ 90 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) \ 91 92 NETDEVICE_ATTR(addr_len, fmt_dec); 93 NETDEVICE_ATTR(iflink, fmt_dec); 94 NETDEVICE_ATTR(ifindex, fmt_dec); 95 NETDEVICE_ATTR(features, fmt_long_hex); 96 NETDEVICE_ATTR(type, fmt_dec); 97 98 /* use same locking rules as GIFHWADDR ioctl's */ 99 static ssize_t format_addr(char *buf, const unsigned char *addr, int len) 100 { 101 int i; 102 char *cp = buf; 103 104 for (i = 0; i < len; i++) 105 cp += sprintf(cp, "%02x%c", addr[i], 106 i == (len - 1) ? '\n' : ':'); 107 return cp - buf; 108 } 109 110 static ssize_t show_address(struct class_device *dev, char *buf) 111 { 112 struct net_device *net = to_net_dev(dev); 113 ssize_t ret = -EINVAL; 114 115 read_lock(&dev_base_lock); 116 if (dev_isalive(net)) 117 ret = format_addr(buf, net->dev_addr, net->addr_len); 118 read_unlock(&dev_base_lock); 119 return ret; 120 } 121 122 static ssize_t show_broadcast(struct class_device *dev, char *buf) 123 { 124 struct net_device *net = to_net_dev(dev); 125 if (dev_isalive(net)) 126 return format_addr(buf, net->broadcast, net->addr_len); 127 return -EINVAL; 128 } 129 130 static ssize_t show_carrier(struct class_device *dev, char *buf) 131 { 132 struct net_device *netdev = to_net_dev(dev); 133 if (netif_running(netdev)) { 134 return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev)); 135 } 136 return -EINVAL; 137 } 138 139 static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL); 140 static CLASS_DEVICE_ATTR(broadcast, S_IRUGO, show_broadcast, NULL); 141 static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL); 142 143 /* read-write attributes */ 144 NETDEVICE_SHOW(mtu, fmt_dec); 145 146 static int change_mtu(struct net_device *net, unsigned long new_mtu) 147 { 148 return dev_set_mtu(net, (int) new_mtu); 149 } 150 151 static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len) 152 { 153 return netdev_store(dev, buf, len, change_mtu); 154 } 155 156 static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu); 157 158 NETDEVICE_SHOW(flags, fmt_hex); 159 160 static int change_flags(struct net_device *net, unsigned long new_flags) 161 { 162 return dev_change_flags(net, (unsigned) new_flags); 163 } 164 165 static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len) 166 { 167 return netdev_store(dev, buf, len, change_flags); 168 } 169 170 static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags); 171 172 NETDEVICE_SHOW(tx_queue_len, fmt_ulong); 173 174 static int change_tx_queue_len(struct net_device *net, unsigned long new_len) 175 { 176 net->tx_queue_len = new_len; 177 return 0; 178 } 179 180 static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len) 181 { 182 return netdev_store(dev, buf, len, change_tx_queue_len); 183 } 184 185 static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, 186 store_tx_queue_len); 187 188 NETDEVICE_SHOW(weight, fmt_dec); 189 190 static int change_weight(struct net_device *net, unsigned long new_weight) 191 { 192 net->weight = new_weight; 193 return 0; 194 } 195 196 static ssize_t store_weight(struct class_device *dev, const char *buf, size_t len) 197 { 198 return netdev_store(dev, buf, len, change_weight); 199 } 200 201 static CLASS_DEVICE_ATTR(weight, S_IRUGO | S_IWUSR, show_weight, 202 store_weight); 203 204 205 static struct class_device_attribute *net_class_attributes[] = { 206 &class_device_attr_ifindex, 207 &class_device_attr_iflink, 208 &class_device_attr_addr_len, 209 &class_device_attr_tx_queue_len, 210 &class_device_attr_features, 211 &class_device_attr_mtu, 212 &class_device_attr_flags, 213 &class_device_attr_weight, 214 &class_device_attr_type, 215 &class_device_attr_address, 216 &class_device_attr_broadcast, 217 &class_device_attr_carrier, 218 NULL 219 }; 220 221 /* Show a given an attribute in the statistics group */ 222 static ssize_t netstat_show(const struct class_device *cd, char *buf, 223 unsigned long offset) 224 { 225 struct net_device *dev = to_net_dev(cd); 226 struct net_device_stats *stats; 227 ssize_t ret = -EINVAL; 228 229 if (offset > sizeof(struct net_device_stats) || 230 offset % sizeof(unsigned long) != 0) 231 WARN_ON(1); 232 233 read_lock(&dev_base_lock); 234 if (dev_isalive(dev) && dev->get_stats && 235 (stats = (*dev->get_stats)(dev))) 236 ret = sprintf(buf, fmt_ulong, 237 *(unsigned long *)(((u8 *) stats) + offset)); 238 239 read_unlock(&dev_base_lock); 240 return ret; 241 } 242 243 /* generate a read-only statistics attribute */ 244 #define NETSTAT_ENTRY(name) \ 245 static ssize_t show_##name(struct class_device *cd, char *buf) \ 246 { \ 247 return netstat_show(cd, buf, \ 248 offsetof(struct net_device_stats, name)); \ 249 } \ 250 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) 251 252 NETSTAT_ENTRY(rx_packets); 253 NETSTAT_ENTRY(tx_packets); 254 NETSTAT_ENTRY(rx_bytes); 255 NETSTAT_ENTRY(tx_bytes); 256 NETSTAT_ENTRY(rx_errors); 257 NETSTAT_ENTRY(tx_errors); 258 NETSTAT_ENTRY(rx_dropped); 259 NETSTAT_ENTRY(tx_dropped); 260 NETSTAT_ENTRY(multicast); 261 NETSTAT_ENTRY(collisions); 262 NETSTAT_ENTRY(rx_length_errors); 263 NETSTAT_ENTRY(rx_over_errors); 264 NETSTAT_ENTRY(rx_crc_errors); 265 NETSTAT_ENTRY(rx_frame_errors); 266 NETSTAT_ENTRY(rx_fifo_errors); 267 NETSTAT_ENTRY(rx_missed_errors); 268 NETSTAT_ENTRY(tx_aborted_errors); 269 NETSTAT_ENTRY(tx_carrier_errors); 270 NETSTAT_ENTRY(tx_fifo_errors); 271 NETSTAT_ENTRY(tx_heartbeat_errors); 272 NETSTAT_ENTRY(tx_window_errors); 273 NETSTAT_ENTRY(rx_compressed); 274 NETSTAT_ENTRY(tx_compressed); 275 276 static struct attribute *netstat_attrs[] = { 277 &class_device_attr_rx_packets.attr, 278 &class_device_attr_tx_packets.attr, 279 &class_device_attr_rx_bytes.attr, 280 &class_device_attr_tx_bytes.attr, 281 &class_device_attr_rx_errors.attr, 282 &class_device_attr_tx_errors.attr, 283 &class_device_attr_rx_dropped.attr, 284 &class_device_attr_tx_dropped.attr, 285 &class_device_attr_multicast.attr, 286 &class_device_attr_collisions.attr, 287 &class_device_attr_rx_length_errors.attr, 288 &class_device_attr_rx_over_errors.attr, 289 &class_device_attr_rx_crc_errors.attr, 290 &class_device_attr_rx_frame_errors.attr, 291 &class_device_attr_rx_fifo_errors.attr, 292 &class_device_attr_rx_missed_errors.attr, 293 &class_device_attr_tx_aborted_errors.attr, 294 &class_device_attr_tx_carrier_errors.attr, 295 &class_device_attr_tx_fifo_errors.attr, 296 &class_device_attr_tx_heartbeat_errors.attr, 297 &class_device_attr_tx_window_errors.attr, 298 &class_device_attr_rx_compressed.attr, 299 &class_device_attr_tx_compressed.attr, 300 NULL 301 }; 302 303 304 static struct attribute_group netstat_group = { 305 .name = "statistics", 306 .attrs = netstat_attrs, 307 }; 308 309 #ifdef WIRELESS_EXT 310 /* helper function that does all the locking etc for wireless stats */ 311 static ssize_t wireless_show(struct class_device *cd, char *buf, 312 ssize_t (*format)(const struct iw_statistics *, 313 char *)) 314 { 315 struct net_device *dev = to_net_dev(cd); 316 const struct iw_statistics *iw; 317 ssize_t ret = -EINVAL; 318 319 read_lock(&dev_base_lock); 320 if (dev_isalive(dev) && dev->get_wireless_stats 321 && (iw = dev->get_wireless_stats(dev)) != NULL) 322 ret = (*format)(iw, buf); 323 read_unlock(&dev_base_lock); 324 325 return ret; 326 } 327 328 /* show function template for wireless fields */ 329 #define WIRELESS_SHOW(name, field, format_string) \ 330 static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \ 331 { \ 332 return sprintf(buf, format_string, iw->field); \ 333 } \ 334 static ssize_t show_iw_##name(struct class_device *cd, char *buf) \ 335 { \ 336 return wireless_show(cd, buf, format_iw_##name); \ 337 } \ 338 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL) 339 340 WIRELESS_SHOW(status, status, fmt_hex); 341 WIRELESS_SHOW(link, qual.qual, fmt_dec); 342 WIRELESS_SHOW(level, qual.level, fmt_dec); 343 WIRELESS_SHOW(noise, qual.noise, fmt_dec); 344 WIRELESS_SHOW(nwid, discard.nwid, fmt_dec); 345 WIRELESS_SHOW(crypt, discard.code, fmt_dec); 346 WIRELESS_SHOW(fragment, discard.fragment, fmt_dec); 347 WIRELESS_SHOW(misc, discard.misc, fmt_dec); 348 WIRELESS_SHOW(retries, discard.retries, fmt_dec); 349 WIRELESS_SHOW(beacon, miss.beacon, fmt_dec); 350 351 static struct attribute *wireless_attrs[] = { 352 &class_device_attr_status.attr, 353 &class_device_attr_link.attr, 354 &class_device_attr_level.attr, 355 &class_device_attr_noise.attr, 356 &class_device_attr_nwid.attr, 357 &class_device_attr_crypt.attr, 358 &class_device_attr_fragment.attr, 359 &class_device_attr_retries.attr, 360 &class_device_attr_misc.attr, 361 &class_device_attr_beacon.attr, 362 NULL 363 }; 364 365 static struct attribute_group wireless_group = { 366 .name = "wireless", 367 .attrs = wireless_attrs, 368 }; 369 #endif 370 371 #ifdef CONFIG_HOTPLUG 372 static int netdev_hotplug(struct class_device *cd, char **envp, 373 int num_envp, char *buf, int size) 374 { 375 struct net_device *dev = to_net_dev(cd); 376 int i = 0; 377 int n; 378 379 /* pass interface in env to hotplug. */ 380 envp[i++] = buf; 381 n = snprintf(buf, size, "INTERFACE=%s", dev->name) + 1; 382 buf += n; 383 size -= n; 384 385 if ((size <= 0) || (i >= num_envp)) 386 return -ENOMEM; 387 388 envp[i] = NULL; 389 return 0; 390 } 391 #endif 392 393 /* 394 * netdev_release -- destroy and free a dead device. 395 * Called when last reference to class_device kobject is gone. 396 */ 397 static void netdev_release(struct class_device *cd) 398 { 399 struct net_device *dev 400 = container_of(cd, struct net_device, class_dev); 401 402 BUG_ON(dev->reg_state != NETREG_RELEASED); 403 404 kfree((char *)dev - dev->padded); 405 } 406 407 static struct class net_class = { 408 .name = "net", 409 .release = netdev_release, 410 #ifdef CONFIG_HOTPLUG 411 .hotplug = netdev_hotplug, 412 #endif 413 }; 414 415 void netdev_unregister_sysfs(struct net_device * net) 416 { 417 struct class_device * class_dev = &(net->class_dev); 418 419 if (net->get_stats) 420 sysfs_remove_group(&class_dev->kobj, &netstat_group); 421 422 #ifdef WIRELESS_EXT 423 if (net->get_wireless_stats) 424 sysfs_remove_group(&class_dev->kobj, &wireless_group); 425 #endif 426 class_device_del(class_dev); 427 428 } 429 430 /* Create sysfs entries for network device. */ 431 int netdev_register_sysfs(struct net_device *net) 432 { 433 struct class_device *class_dev = &(net->class_dev); 434 int i; 435 struct class_device_attribute *attr; 436 int ret; 437 438 class_dev->class = &net_class; 439 class_dev->class_data = net; 440 441 strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE); 442 if ((ret = class_device_register(class_dev))) 443 goto out; 444 445 for (i = 0; (attr = net_class_attributes[i]) != NULL; i++) { 446 if ((ret = class_device_create_file(class_dev, attr))) 447 goto out_unreg; 448 } 449 450 451 if (net->get_stats && 452 (ret = sysfs_create_group(&class_dev->kobj, &netstat_group))) 453 goto out_unreg; 454 455 #ifdef WIRELESS_EXT 456 if (net->get_wireless_stats && 457 (ret = sysfs_create_group(&class_dev->kobj, &wireless_group))) 458 goto out_cleanup; 459 460 return 0; 461 out_cleanup: 462 if (net->get_stats) 463 sysfs_remove_group(&class_dev->kobj, &netstat_group); 464 #else 465 return 0; 466 #endif 467 468 out_unreg: 469 printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n", 470 net->name, ret); 471 class_device_unregister(class_dev); 472 out: 473 return ret; 474 } 475 476 int netdev_sysfs_init(void) 477 { 478 return class_register(&net_class); 479 } 480