1 /* 2 * Sysfs attributes of bridge ports 3 * Linux ethernet bridge 4 * 5 * Authors: 6 * Stephen Hemminger <shemminger@osdl.org> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 11 * 2 of the License, or (at your option) any later version. 12 */ 13 14 #include <linux/capability.h> 15 #include <linux/kernel.h> 16 #include <linux/netdevice.h> 17 #include <linux/if_bridge.h> 18 #include <linux/rtnetlink.h> 19 #include <linux/spinlock.h> 20 #include <linux/times.h> 21 22 #include "br_private.h" 23 24 #define to_dev(obj) container_of(obj, struct device, kobj) 25 #define to_bridge(cd) ((struct net_bridge *)(to_net_dev(cd)->priv)) 26 27 /* 28 * Common code for storing bridge parameters. 29 */ 30 static ssize_t store_bridge_parm(struct device *d, 31 const char *buf, size_t len, 32 void (*set)(struct net_bridge *, unsigned long)) 33 { 34 struct net_bridge *br = to_bridge(d); 35 char *endp; 36 unsigned long val; 37 38 if (!capable(CAP_NET_ADMIN)) 39 return -EPERM; 40 41 val = simple_strtoul(buf, &endp, 0); 42 if (endp == buf) 43 return -EINVAL; 44 45 spin_lock_bh(&br->lock); 46 (*set)(br, val); 47 spin_unlock_bh(&br->lock); 48 return len; 49 } 50 51 52 static ssize_t show_forward_delay(struct device *d, 53 struct device_attribute *attr, char *buf) 54 { 55 struct net_bridge *br = to_bridge(d); 56 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); 57 } 58 59 static void set_forward_delay(struct net_bridge *br, unsigned long val) 60 { 61 unsigned long delay = clock_t_to_jiffies(val); 62 br->forward_delay = delay; 63 if (br_is_root_bridge(br)) 64 br->bridge_forward_delay = delay; 65 } 66 67 static ssize_t store_forward_delay(struct device *d, 68 struct device_attribute *attr, 69 const char *buf, size_t len) 70 { 71 return store_bridge_parm(d, buf, len, set_forward_delay); 72 } 73 static DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR, 74 show_forward_delay, store_forward_delay); 75 76 static ssize_t show_hello_time(struct device *d, struct device_attribute *attr, 77 char *buf) 78 { 79 return sprintf(buf, "%lu\n", 80 jiffies_to_clock_t(to_bridge(d)->hello_time)); 81 } 82 83 static void set_hello_time(struct net_bridge *br, unsigned long val) 84 { 85 unsigned long t = clock_t_to_jiffies(val); 86 br->hello_time = t; 87 if (br_is_root_bridge(br)) 88 br->bridge_hello_time = t; 89 } 90 91 static ssize_t store_hello_time(struct device *d, 92 struct device_attribute *attr, const char *buf, 93 size_t len) 94 { 95 return store_bridge_parm(d, buf, len, set_hello_time); 96 } 97 static DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time, 98 store_hello_time); 99 100 static ssize_t show_max_age(struct device *d, struct device_attribute *attr, 101 char *buf) 102 { 103 return sprintf(buf, "%lu\n", 104 jiffies_to_clock_t(to_bridge(d)->max_age)); 105 } 106 107 static void set_max_age(struct net_bridge *br, unsigned long val) 108 { 109 unsigned long t = clock_t_to_jiffies(val); 110 br->max_age = t; 111 if (br_is_root_bridge(br)) 112 br->bridge_max_age = t; 113 } 114 115 static ssize_t store_max_age(struct device *d, struct device_attribute *attr, 116 const char *buf, size_t len) 117 { 118 return store_bridge_parm(d, buf, len, set_max_age); 119 } 120 static DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age); 121 122 static ssize_t show_ageing_time(struct device *d, 123 struct device_attribute *attr, char *buf) 124 { 125 struct net_bridge *br = to_bridge(d); 126 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time)); 127 } 128 129 static void set_ageing_time(struct net_bridge *br, unsigned long val) 130 { 131 br->ageing_time = clock_t_to_jiffies(val); 132 } 133 134 static ssize_t store_ageing_time(struct device *d, 135 struct device_attribute *attr, 136 const char *buf, size_t len) 137 { 138 return store_bridge_parm(d, buf, len, set_ageing_time); 139 } 140 static DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time, 141 store_ageing_time); 142 143 static ssize_t show_stp_state(struct device *d, 144 struct device_attribute *attr, char *buf) 145 { 146 struct net_bridge *br = to_bridge(d); 147 return sprintf(buf, "%d\n", br->stp_enabled); 148 } 149 150 151 static ssize_t store_stp_state(struct device *d, 152 struct device_attribute *attr, const char *buf, 153 size_t len) 154 { 155 struct net_bridge *br = to_bridge(d); 156 char *endp; 157 unsigned long val; 158 159 if (!capable(CAP_NET_ADMIN)) 160 return -EPERM; 161 162 val = simple_strtoul(buf, &endp, 0); 163 if (endp == buf) 164 return -EINVAL; 165 166 rtnl_lock(); 167 br_stp_set_enabled(br, val); 168 rtnl_unlock(); 169 170 return len; 171 } 172 static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state, 173 store_stp_state); 174 175 static ssize_t show_priority(struct device *d, struct device_attribute *attr, 176 char *buf) 177 { 178 struct net_bridge *br = to_bridge(d); 179 return sprintf(buf, "%d\n", 180 (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]); 181 } 182 183 static void set_priority(struct net_bridge *br, unsigned long val) 184 { 185 br_stp_set_bridge_priority(br, (u16) val); 186 } 187 188 static ssize_t store_priority(struct device *d, struct device_attribute *attr, 189 const char *buf, size_t len) 190 { 191 return store_bridge_parm(d, buf, len, set_priority); 192 } 193 static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority); 194 195 static ssize_t show_root_id(struct device *d, struct device_attribute *attr, 196 char *buf) 197 { 198 return br_show_bridge_id(buf, &to_bridge(d)->designated_root); 199 } 200 static DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL); 201 202 static ssize_t show_bridge_id(struct device *d, struct device_attribute *attr, 203 char *buf) 204 { 205 return br_show_bridge_id(buf, &to_bridge(d)->bridge_id); 206 } 207 static DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL); 208 209 static ssize_t show_root_port(struct device *d, struct device_attribute *attr, 210 char *buf) 211 { 212 return sprintf(buf, "%d\n", to_bridge(d)->root_port); 213 } 214 static DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL); 215 216 static ssize_t show_root_path_cost(struct device *d, 217 struct device_attribute *attr, char *buf) 218 { 219 return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost); 220 } 221 static DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL); 222 223 static ssize_t show_topology_change(struct device *d, 224 struct device_attribute *attr, char *buf) 225 { 226 return sprintf(buf, "%d\n", to_bridge(d)->topology_change); 227 } 228 static DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL); 229 230 static ssize_t show_topology_change_detected(struct device *d, 231 struct device_attribute *attr, 232 char *buf) 233 { 234 struct net_bridge *br = to_bridge(d); 235 return sprintf(buf, "%d\n", br->topology_change_detected); 236 } 237 static DEVICE_ATTR(topology_change_detected, S_IRUGO, 238 show_topology_change_detected, NULL); 239 240 static ssize_t show_hello_timer(struct device *d, 241 struct device_attribute *attr, char *buf) 242 { 243 struct net_bridge *br = to_bridge(d); 244 return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer)); 245 } 246 static DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL); 247 248 static ssize_t show_tcn_timer(struct device *d, struct device_attribute *attr, 249 char *buf) 250 { 251 struct net_bridge *br = to_bridge(d); 252 return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer)); 253 } 254 static DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL); 255 256 static ssize_t show_topology_change_timer(struct device *d, 257 struct device_attribute *attr, 258 char *buf) 259 { 260 struct net_bridge *br = to_bridge(d); 261 return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer)); 262 } 263 static DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer, 264 NULL); 265 266 static ssize_t show_gc_timer(struct device *d, struct device_attribute *attr, 267 char *buf) 268 { 269 struct net_bridge *br = to_bridge(d); 270 return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer)); 271 } 272 static DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL); 273 274 static ssize_t show_group_addr(struct device *d, 275 struct device_attribute *attr, char *buf) 276 { 277 struct net_bridge *br = to_bridge(d); 278 return sprintf(buf, "%x:%x:%x:%x:%x:%x\n", 279 br->group_addr[0], br->group_addr[1], 280 br->group_addr[2], br->group_addr[3], 281 br->group_addr[4], br->group_addr[5]); 282 } 283 284 static ssize_t store_group_addr(struct device *d, 285 struct device_attribute *attr, 286 const char *buf, size_t len) 287 { 288 struct net_bridge *br = to_bridge(d); 289 unsigned new_addr[6]; 290 int i; 291 292 if (!capable(CAP_NET_ADMIN)) 293 return -EPERM; 294 295 if (sscanf(buf, "%x:%x:%x:%x:%x:%x", 296 &new_addr[0], &new_addr[1], &new_addr[2], 297 &new_addr[3], &new_addr[4], &new_addr[5]) != 6) 298 return -EINVAL; 299 300 /* Must be 01:80:c2:00:00:0X */ 301 for (i = 0; i < 5; i++) 302 if (new_addr[i] != br_group_address[i]) 303 return -EINVAL; 304 305 if (new_addr[5] & ~0xf) 306 return -EINVAL; 307 308 if (new_addr[5] == 1 /* 802.3x Pause address */ 309 || new_addr[5] == 2 /* 802.3ad Slow protocols */ 310 || new_addr[5] == 3) /* 802.1X PAE address */ 311 return -EINVAL; 312 313 spin_lock_bh(&br->lock); 314 for (i = 0; i < 6; i++) 315 br->group_addr[i] = new_addr[i]; 316 spin_unlock_bh(&br->lock); 317 return len; 318 } 319 320 static DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR, 321 show_group_addr, store_group_addr); 322 323 static ssize_t store_flush(struct device *d, 324 struct device_attribute *attr, 325 const char *buf, size_t len) 326 { 327 struct net_bridge *br = to_bridge(d); 328 329 if (!capable(CAP_NET_ADMIN)) 330 return -EPERM; 331 332 br_fdb_flush(br); 333 return len; 334 } 335 static DEVICE_ATTR(flush, S_IWUSR, NULL, store_flush); 336 337 static struct attribute *bridge_attrs[] = { 338 &dev_attr_forward_delay.attr, 339 &dev_attr_hello_time.attr, 340 &dev_attr_max_age.attr, 341 &dev_attr_ageing_time.attr, 342 &dev_attr_stp_state.attr, 343 &dev_attr_priority.attr, 344 &dev_attr_bridge_id.attr, 345 &dev_attr_root_id.attr, 346 &dev_attr_root_path_cost.attr, 347 &dev_attr_root_port.attr, 348 &dev_attr_topology_change.attr, 349 &dev_attr_topology_change_detected.attr, 350 &dev_attr_hello_timer.attr, 351 &dev_attr_tcn_timer.attr, 352 &dev_attr_topology_change_timer.attr, 353 &dev_attr_gc_timer.attr, 354 &dev_attr_group_addr.attr, 355 &dev_attr_flush.attr, 356 NULL 357 }; 358 359 static struct attribute_group bridge_group = { 360 .name = SYSFS_BRIDGE_ATTR, 361 .attrs = bridge_attrs, 362 }; 363 364 /* 365 * Export the forwarding information table as a binary file 366 * The records are struct __fdb_entry. 367 * 368 * Returns the number of bytes read. 369 */ 370 static ssize_t brforward_read(struct kobject *kobj, 371 struct bin_attribute *bin_attr, 372 char *buf, loff_t off, size_t count) 373 { 374 struct device *dev = to_dev(kobj); 375 struct net_bridge *br = to_bridge(dev); 376 int n; 377 378 /* must read whole records */ 379 if (off % sizeof(struct __fdb_entry) != 0) 380 return -EINVAL; 381 382 n = br_fdb_fillbuf(br, buf, 383 count / sizeof(struct __fdb_entry), 384 off / sizeof(struct __fdb_entry)); 385 386 if (n > 0) 387 n *= sizeof(struct __fdb_entry); 388 389 return n; 390 } 391 392 static struct bin_attribute bridge_forward = { 393 .attr = { .name = SYSFS_BRIDGE_FDB, 394 .mode = S_IRUGO, }, 395 .read = brforward_read, 396 }; 397 398 /* 399 * Add entries in sysfs onto the existing network class device 400 * for the bridge. 401 * Adds a attribute group "bridge" containing tuning parameters. 402 * Binary attribute containing the forward table 403 * Sub directory to hold links to interfaces. 404 * 405 * Note: the ifobj exists only to be a subdirectory 406 * to hold links. The ifobj exists in same data structure 407 * as it's parent the bridge so reference counting works. 408 */ 409 int br_sysfs_addbr(struct net_device *dev) 410 { 411 struct kobject *brobj = &dev->dev.kobj; 412 struct net_bridge *br = netdev_priv(dev); 413 int err; 414 415 err = sysfs_create_group(brobj, &bridge_group); 416 if (err) { 417 pr_info("%s: can't create group %s/%s\n", 418 __func__, dev->name, bridge_group.name); 419 goto out1; 420 } 421 422 err = sysfs_create_bin_file(brobj, &bridge_forward); 423 if (err) { 424 pr_info("%s: can't create attribute file %s/%s\n", 425 __func__, dev->name, bridge_forward.attr.name); 426 goto out2; 427 } 428 429 br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, brobj); 430 if (!br->ifobj) { 431 pr_info("%s: can't add kobject (directory) %s/%s\n", 432 __func__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR); 433 goto out3; 434 } 435 return 0; 436 out3: 437 sysfs_remove_bin_file(&dev->dev.kobj, &bridge_forward); 438 out2: 439 sysfs_remove_group(&dev->dev.kobj, &bridge_group); 440 out1: 441 return err; 442 443 } 444 445 void br_sysfs_delbr(struct net_device *dev) 446 { 447 struct kobject *kobj = &dev->dev.kobj; 448 struct net_bridge *br = netdev_priv(dev); 449 450 kobject_put(br->ifobj); 451 sysfs_remove_bin_file(kobj, &bridge_forward); 452 sysfs_remove_group(kobj, &bridge_group); 453 } 454