11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Sysfs attributes of bridge ports 31da177e4SLinus Torvalds * Linux ethernet bridge 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Authors: 61da177e4SLinus Torvalds * Stephen Hemminger <shemminger@osdl.org> 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 91da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 101da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 111da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 14*4fc268d2SRandy Dunlap #include <linux/capability.h> 151da177e4SLinus Torvalds #include <linux/kernel.h> 161da177e4SLinus Torvalds #include <linux/netdevice.h> 171da177e4SLinus Torvalds #include <linux/if_bridge.h> 181da177e4SLinus Torvalds #include <linux/rtnetlink.h> 191da177e4SLinus Torvalds #include <linux/spinlock.h> 201da177e4SLinus Torvalds #include <linux/times.h> 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #include "br_private.h" 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds #define to_class_dev(obj) container_of(obj,struct class_device,kobj) 251da177e4SLinus Torvalds #define to_net_dev(class) container_of(class, struct net_device, class_dev) 261da177e4SLinus Torvalds #define to_bridge(cd) ((struct net_bridge *)(to_net_dev(cd)->priv)) 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds /* 291da177e4SLinus Torvalds * Common code for storing bridge parameters. 301da177e4SLinus Torvalds */ 311da177e4SLinus Torvalds static ssize_t store_bridge_parm(struct class_device *cd, 321da177e4SLinus Torvalds const char *buf, size_t len, 331da177e4SLinus Torvalds void (*set)(struct net_bridge *, unsigned long)) 341da177e4SLinus Torvalds { 351da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 361da177e4SLinus Torvalds char *endp; 371da177e4SLinus Torvalds unsigned long val; 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 401da177e4SLinus Torvalds return -EPERM; 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds val = simple_strtoul(buf, &endp, 0); 431da177e4SLinus Torvalds if (endp == buf) 441da177e4SLinus Torvalds return -EINVAL; 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds spin_lock_bh(&br->lock); 471da177e4SLinus Torvalds (*set)(br, val); 481da177e4SLinus Torvalds spin_unlock_bh(&br->lock); 491da177e4SLinus Torvalds return len; 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds static ssize_t show_forward_delay(struct class_device *cd, char *buf) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 561da177e4SLinus Torvalds return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds static void set_forward_delay(struct net_bridge *br, unsigned long val) 601da177e4SLinus Torvalds { 611da177e4SLinus Torvalds unsigned long delay = clock_t_to_jiffies(val); 621da177e4SLinus Torvalds br->forward_delay = delay; 631da177e4SLinus Torvalds if (br_is_root_bridge(br)) 641da177e4SLinus Torvalds br->bridge_forward_delay = delay; 651da177e4SLinus Torvalds } 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds static ssize_t store_forward_delay(struct class_device *cd, const char *buf, 681da177e4SLinus Torvalds size_t len) 691da177e4SLinus Torvalds { 701da177e4SLinus Torvalds return store_bridge_parm(cd, buf, len, set_forward_delay); 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR, 731da177e4SLinus Torvalds show_forward_delay, store_forward_delay); 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds static ssize_t show_hello_time(struct class_device *cd, char *buf) 761da177e4SLinus Torvalds { 771da177e4SLinus Torvalds return sprintf(buf, "%lu\n", 781da177e4SLinus Torvalds jiffies_to_clock_t(to_bridge(cd)->hello_time)); 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds static void set_hello_time(struct net_bridge *br, unsigned long val) 821da177e4SLinus Torvalds { 831da177e4SLinus Torvalds unsigned long t = clock_t_to_jiffies(val); 841da177e4SLinus Torvalds br->hello_time = t; 851da177e4SLinus Torvalds if (br_is_root_bridge(br)) 861da177e4SLinus Torvalds br->bridge_hello_time = t; 871da177e4SLinus Torvalds } 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds static ssize_t store_hello_time(struct class_device *cd, const char *buf, 901da177e4SLinus Torvalds size_t len) 911da177e4SLinus Torvalds { 921da177e4SLinus Torvalds return store_bridge_parm(cd, buf, len, set_hello_time); 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time, 961da177e4SLinus Torvalds store_hello_time); 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds static ssize_t show_max_age(struct class_device *cd, char *buf) 991da177e4SLinus Torvalds { 1001da177e4SLinus Torvalds return sprintf(buf, "%lu\n", 1011da177e4SLinus Torvalds jiffies_to_clock_t(to_bridge(cd)->max_age)); 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds static void set_max_age(struct net_bridge *br, unsigned long val) 1051da177e4SLinus Torvalds { 1061da177e4SLinus Torvalds unsigned long t = clock_t_to_jiffies(val); 1071da177e4SLinus Torvalds br->max_age = t; 1081da177e4SLinus Torvalds if (br_is_root_bridge(br)) 1091da177e4SLinus Torvalds br->bridge_max_age = t; 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds static ssize_t store_max_age(struct class_device *cd, const char *buf, 1131da177e4SLinus Torvalds size_t len) 1141da177e4SLinus Torvalds { 1151da177e4SLinus Torvalds return store_bridge_parm(cd, buf, len, set_max_age); 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, 1191da177e4SLinus Torvalds store_max_age); 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds static ssize_t show_ageing_time(struct class_device *cd, char *buf) 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 1241da177e4SLinus Torvalds return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time)); 1251da177e4SLinus Torvalds } 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds static void set_ageing_time(struct net_bridge *br, unsigned long val) 1281da177e4SLinus Torvalds { 1291da177e4SLinus Torvalds br->ageing_time = clock_t_to_jiffies(val); 1301da177e4SLinus Torvalds } 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds static ssize_t store_ageing_time(struct class_device *cd, const char *buf, 1331da177e4SLinus Torvalds size_t len) 1341da177e4SLinus Torvalds { 1351da177e4SLinus Torvalds return store_bridge_parm(cd, buf, len, set_ageing_time); 1361da177e4SLinus Torvalds } 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time, 1391da177e4SLinus Torvalds store_ageing_time); 1401da177e4SLinus Torvalds static ssize_t show_stp_state(struct class_device *cd, char *buf) 1411da177e4SLinus Torvalds { 1421da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 1431da177e4SLinus Torvalds return sprintf(buf, "%d\n", br->stp_enabled); 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds static void set_stp_state(struct net_bridge *br, unsigned long val) 1471da177e4SLinus Torvalds { 1481da177e4SLinus Torvalds br->stp_enabled = val; 1491da177e4SLinus Torvalds } 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds static ssize_t store_stp_state(struct class_device *cd, 1521da177e4SLinus Torvalds const char *buf, size_t len) 1531da177e4SLinus Torvalds { 1541da177e4SLinus Torvalds return store_bridge_parm(cd, buf, len, set_stp_state); 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state, 1581da177e4SLinus Torvalds store_stp_state); 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds static ssize_t show_priority(struct class_device *cd, char *buf) 1611da177e4SLinus Torvalds { 1621da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 1631da177e4SLinus Torvalds return sprintf(buf, "%d\n", 1641da177e4SLinus Torvalds (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]); 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds static void set_priority(struct net_bridge *br, unsigned long val) 1681da177e4SLinus Torvalds { 1691da177e4SLinus Torvalds br_stp_set_bridge_priority(br, (u16) val); 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds static ssize_t store_priority(struct class_device *cd, 1731da177e4SLinus Torvalds const char *buf, size_t len) 1741da177e4SLinus Torvalds { 1751da177e4SLinus Torvalds return store_bridge_parm(cd, buf, len, set_priority); 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, 1781da177e4SLinus Torvalds store_priority); 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds static ssize_t show_root_id(struct class_device *cd, char *buf) 1811da177e4SLinus Torvalds { 1821da177e4SLinus Torvalds return br_show_bridge_id(buf, &to_bridge(cd)->designated_root); 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL); 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds static ssize_t show_bridge_id(struct class_device *cd, char *buf) 1871da177e4SLinus Torvalds { 1881da177e4SLinus Torvalds return br_show_bridge_id(buf, &to_bridge(cd)->bridge_id); 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL); 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds static ssize_t show_root_port(struct class_device *cd, char *buf) 1931da177e4SLinus Torvalds { 1941da177e4SLinus Torvalds return sprintf(buf, "%d\n", to_bridge(cd)->root_port); 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL); 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds static ssize_t show_root_path_cost(struct class_device *cd, char *buf) 1991da177e4SLinus Torvalds { 2001da177e4SLinus Torvalds return sprintf(buf, "%d\n", to_bridge(cd)->root_path_cost); 2011da177e4SLinus Torvalds } 2021da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL); 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds static ssize_t show_topology_change(struct class_device *cd, char *buf) 2051da177e4SLinus Torvalds { 2061da177e4SLinus Torvalds return sprintf(buf, "%d\n", to_bridge(cd)->topology_change); 2071da177e4SLinus Torvalds } 2081da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL); 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds static ssize_t show_topology_change_detected(struct class_device *cd, char *buf) 2111da177e4SLinus Torvalds { 2121da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 2131da177e4SLinus Torvalds return sprintf(buf, "%d\n", br->topology_change_detected); 2141da177e4SLinus Torvalds } 2151da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(topology_change_detected, S_IRUGO, show_topology_change_detected, NULL); 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds static ssize_t show_hello_timer(struct class_device *cd, char *buf) 2181da177e4SLinus Torvalds { 2191da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 2201da177e4SLinus Torvalds return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer)); 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL); 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds static ssize_t show_tcn_timer(struct class_device *cd, char *buf) 2251da177e4SLinus Torvalds { 2261da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 2271da177e4SLinus Torvalds return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer)); 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL); 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds static ssize_t show_topology_change_timer(struct class_device *cd, char *buf) 2321da177e4SLinus Torvalds { 2331da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 2341da177e4SLinus Torvalds return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer)); 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer, NULL); 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds static ssize_t show_gc_timer(struct class_device *cd, char *buf) 2391da177e4SLinus Torvalds { 2401da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cd); 2411da177e4SLinus Torvalds return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer)); 2421da177e4SLinus Torvalds } 2431da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL); 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds static struct attribute *bridge_attrs[] = { 2461da177e4SLinus Torvalds &class_device_attr_forward_delay.attr, 2471da177e4SLinus Torvalds &class_device_attr_hello_time.attr, 2481da177e4SLinus Torvalds &class_device_attr_max_age.attr, 2491da177e4SLinus Torvalds &class_device_attr_ageing_time.attr, 2501da177e4SLinus Torvalds &class_device_attr_stp_state.attr, 2511da177e4SLinus Torvalds &class_device_attr_priority.attr, 2521da177e4SLinus Torvalds &class_device_attr_bridge_id.attr, 2531da177e4SLinus Torvalds &class_device_attr_root_id.attr, 2541da177e4SLinus Torvalds &class_device_attr_root_path_cost.attr, 2551da177e4SLinus Torvalds &class_device_attr_root_port.attr, 2561da177e4SLinus Torvalds &class_device_attr_topology_change.attr, 2571da177e4SLinus Torvalds &class_device_attr_topology_change_detected.attr, 2581da177e4SLinus Torvalds &class_device_attr_hello_timer.attr, 2591da177e4SLinus Torvalds &class_device_attr_tcn_timer.attr, 2601da177e4SLinus Torvalds &class_device_attr_topology_change_timer.attr, 2611da177e4SLinus Torvalds &class_device_attr_gc_timer.attr, 2621da177e4SLinus Torvalds NULL 2631da177e4SLinus Torvalds }; 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvalds static struct attribute_group bridge_group = { 2661da177e4SLinus Torvalds .name = SYSFS_BRIDGE_ATTR, 2671da177e4SLinus Torvalds .attrs = bridge_attrs, 2681da177e4SLinus Torvalds }; 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds /* 2711da177e4SLinus Torvalds * Export the forwarding information table as a binary file 2721da177e4SLinus Torvalds * The records are struct __fdb_entry. 2731da177e4SLinus Torvalds * 2741da177e4SLinus Torvalds * Returns the number of bytes read. 2751da177e4SLinus Torvalds */ 2761da177e4SLinus Torvalds static ssize_t brforward_read(struct kobject *kobj, char *buf, 2771da177e4SLinus Torvalds loff_t off, size_t count) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds struct class_device *cdev = to_class_dev(kobj); 2801da177e4SLinus Torvalds struct net_bridge *br = to_bridge(cdev); 2811da177e4SLinus Torvalds int n; 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds /* must read whole records */ 2841da177e4SLinus Torvalds if (off % sizeof(struct __fdb_entry) != 0) 2851da177e4SLinus Torvalds return -EINVAL; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds n = br_fdb_fillbuf(br, buf, 2881da177e4SLinus Torvalds count / sizeof(struct __fdb_entry), 2891da177e4SLinus Torvalds off / sizeof(struct __fdb_entry)); 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds if (n > 0) 2921da177e4SLinus Torvalds n *= sizeof(struct __fdb_entry); 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds return n; 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds static struct bin_attribute bridge_forward = { 2981da177e4SLinus Torvalds .attr = { .name = SYSFS_BRIDGE_FDB, 2991da177e4SLinus Torvalds .mode = S_IRUGO, 3001da177e4SLinus Torvalds .owner = THIS_MODULE, }, 3011da177e4SLinus Torvalds .read = brforward_read, 3021da177e4SLinus Torvalds }; 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds /* 3051da177e4SLinus Torvalds * Add entries in sysfs onto the existing network class device 3061da177e4SLinus Torvalds * for the bridge. 3071da177e4SLinus Torvalds * Adds a attribute group "bridge" containing tuning parameters. 3081da177e4SLinus Torvalds * Binary attribute containing the forward table 3091da177e4SLinus Torvalds * Sub directory to hold links to interfaces. 3101da177e4SLinus Torvalds * 3111da177e4SLinus Torvalds * Note: the ifobj exists only to be a subdirectory 3121da177e4SLinus Torvalds * to hold links. The ifobj exists in same data structure 3131da177e4SLinus Torvalds * as it's parent the bridge so reference counting works. 3141da177e4SLinus Torvalds */ 3151da177e4SLinus Torvalds int br_sysfs_addbr(struct net_device *dev) 3161da177e4SLinus Torvalds { 3171da177e4SLinus Torvalds struct kobject *brobj = &dev->class_dev.kobj; 3181da177e4SLinus Torvalds struct net_bridge *br = netdev_priv(dev); 3191da177e4SLinus Torvalds int err; 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds err = sysfs_create_group(brobj, &bridge_group); 3221da177e4SLinus Torvalds if (err) { 3231da177e4SLinus Torvalds pr_info("%s: can't create group %s/%s\n", 3241da177e4SLinus Torvalds __FUNCTION__, dev->name, bridge_group.name); 3251da177e4SLinus Torvalds goto out1; 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds err = sysfs_create_bin_file(brobj, &bridge_forward); 3291da177e4SLinus Torvalds if (err) { 3301da177e4SLinus Torvalds pr_info("%s: can't create attribue file %s/%s\n", 3311da177e4SLinus Torvalds __FUNCTION__, dev->name, bridge_forward.attr.name); 3321da177e4SLinus Torvalds goto out2; 3331da177e4SLinus Torvalds } 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds kobject_set_name(&br->ifobj, SYSFS_BRIDGE_PORT_SUBDIR); 3371da177e4SLinus Torvalds br->ifobj.ktype = NULL; 3381da177e4SLinus Torvalds br->ifobj.kset = NULL; 3391da177e4SLinus Torvalds br->ifobj.parent = brobj; 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds err = kobject_register(&br->ifobj); 3421da177e4SLinus Torvalds if (err) { 3431da177e4SLinus Torvalds pr_info("%s: can't add kobject (directory) %s/%s\n", 3441da177e4SLinus Torvalds __FUNCTION__, dev->name, br->ifobj.name); 3451da177e4SLinus Torvalds goto out3; 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds return 0; 3481da177e4SLinus Torvalds out3: 3491da177e4SLinus Torvalds sysfs_remove_bin_file(&dev->class_dev.kobj, &bridge_forward); 3501da177e4SLinus Torvalds out2: 3511da177e4SLinus Torvalds sysfs_remove_group(&dev->class_dev.kobj, &bridge_group); 3521da177e4SLinus Torvalds out1: 3531da177e4SLinus Torvalds return err; 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds } 3561da177e4SLinus Torvalds 3571da177e4SLinus Torvalds void br_sysfs_delbr(struct net_device *dev) 3581da177e4SLinus Torvalds { 3591da177e4SLinus Torvalds struct kobject *kobj = &dev->class_dev.kobj; 3601da177e4SLinus Torvalds struct net_bridge *br = netdev_priv(dev); 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds kobject_unregister(&br->ifobj); 3631da177e4SLinus Torvalds sysfs_remove_bin_file(kobj, &bridge_forward); 3641da177e4SLinus Torvalds sysfs_remove_group(kobj, &bridge_group); 3651da177e4SLinus Torvalds } 366