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