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 21 #include "br_private.h" 22 23 struct brport_attribute { 24 struct attribute attr; 25 ssize_t (*show)(struct net_bridge_port *, char *); 26 ssize_t (*store)(struct net_bridge_port *, unsigned long); 27 }; 28 29 #define BRPORT_ATTR(_name,_mode,_show,_store) \ 30 struct brport_attribute brport_attr_##_name = { \ 31 .attr = {.name = __stringify(_name), \ 32 .mode = _mode, \ 33 .owner = THIS_MODULE, }, \ 34 .show = _show, \ 35 .store = _store, \ 36 }; 37 38 static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) 39 { 40 return sprintf(buf, "%d\n", p->path_cost); 41 } 42 static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v) 43 { 44 br_stp_set_path_cost(p, v); 45 return 0; 46 } 47 static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, 48 show_path_cost, store_path_cost); 49 50 static ssize_t show_priority(struct net_bridge_port *p, char *buf) 51 { 52 return sprintf(buf, "%d\n", p->priority); 53 } 54 static ssize_t store_priority(struct net_bridge_port *p, unsigned long v) 55 { 56 if (v >= (1<<(16-BR_PORT_BITS))) 57 return -ERANGE; 58 br_stp_set_port_priority(p, v); 59 return 0; 60 } 61 static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, 62 show_priority, store_priority); 63 64 static ssize_t show_designated_root(struct net_bridge_port *p, char *buf) 65 { 66 return br_show_bridge_id(buf, &p->designated_root); 67 } 68 static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL); 69 70 static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf) 71 { 72 return br_show_bridge_id(buf, &p->designated_bridge); 73 } 74 static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL); 75 76 static ssize_t show_designated_port(struct net_bridge_port *p, char *buf) 77 { 78 return sprintf(buf, "%d\n", p->designated_port); 79 } 80 static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL); 81 82 static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf) 83 { 84 return sprintf(buf, "%d\n", p->designated_cost); 85 } 86 static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL); 87 88 static ssize_t show_port_id(struct net_bridge_port *p, char *buf) 89 { 90 return sprintf(buf, "0x%x\n", p->port_id); 91 } 92 static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL); 93 94 static ssize_t show_port_no(struct net_bridge_port *p, char *buf) 95 { 96 return sprintf(buf, "0x%x\n", p->port_no); 97 } 98 99 static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL); 100 101 static ssize_t show_change_ack(struct net_bridge_port *p, char *buf) 102 { 103 return sprintf(buf, "%d\n", p->topology_change_ack); 104 } 105 static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL); 106 107 static ssize_t show_config_pending(struct net_bridge_port *p, char *buf) 108 { 109 return sprintf(buf, "%d\n", p->config_pending); 110 } 111 static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL); 112 113 static ssize_t show_port_state(struct net_bridge_port *p, char *buf) 114 { 115 return sprintf(buf, "%d\n", p->state); 116 } 117 static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL); 118 119 static ssize_t show_message_age_timer(struct net_bridge_port *p, 120 char *buf) 121 { 122 return sprintf(buf, "%ld\n", br_timer_value(&p->message_age_timer)); 123 } 124 static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL); 125 126 static ssize_t show_forward_delay_timer(struct net_bridge_port *p, 127 char *buf) 128 { 129 return sprintf(buf, "%ld\n", br_timer_value(&p->forward_delay_timer)); 130 } 131 static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL); 132 133 static ssize_t show_hold_timer(struct net_bridge_port *p, 134 char *buf) 135 { 136 return sprintf(buf, "%ld\n", br_timer_value(&p->hold_timer)); 137 } 138 static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); 139 140 static ssize_t store_flush(struct net_bridge_port *p, unsigned long v) 141 { 142 br_fdb_delete_by_port(p->br, p, 0); // Don't delete local entry 143 return 0; 144 } 145 static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); 146 147 static struct brport_attribute *brport_attrs[] = { 148 &brport_attr_path_cost, 149 &brport_attr_priority, 150 &brport_attr_port_id, 151 &brport_attr_port_no, 152 &brport_attr_designated_root, 153 &brport_attr_designated_bridge, 154 &brport_attr_designated_port, 155 &brport_attr_designated_cost, 156 &brport_attr_state, 157 &brport_attr_change_ack, 158 &brport_attr_config_pending, 159 &brport_attr_message_age_timer, 160 &brport_attr_forward_delay_timer, 161 &brport_attr_hold_timer, 162 &brport_attr_flush, 163 NULL 164 }; 165 166 #define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr) 167 #define to_brport(obj) container_of(obj, struct net_bridge_port, kobj) 168 169 static ssize_t brport_show(struct kobject * kobj, 170 struct attribute * attr, char * buf) 171 { 172 struct brport_attribute * brport_attr = to_brport_attr(attr); 173 struct net_bridge_port * p = to_brport(kobj); 174 175 return brport_attr->show(p, buf); 176 } 177 178 static ssize_t brport_store(struct kobject * kobj, 179 struct attribute * attr, 180 const char * buf, size_t count) 181 { 182 struct brport_attribute * brport_attr = to_brport_attr(attr); 183 struct net_bridge_port * p = to_brport(kobj); 184 ssize_t ret = -EINVAL; 185 char *endp; 186 unsigned long val; 187 188 if (!capable(CAP_NET_ADMIN)) 189 return -EPERM; 190 191 val = simple_strtoul(buf, &endp, 0); 192 if (endp != buf) { 193 rtnl_lock(); 194 if (p->dev && p->br && brport_attr->store) { 195 spin_lock_bh(&p->br->lock); 196 ret = brport_attr->store(p, val); 197 spin_unlock_bh(&p->br->lock); 198 if (ret == 0) 199 ret = count; 200 } 201 rtnl_unlock(); 202 } 203 return ret; 204 } 205 206 struct sysfs_ops brport_sysfs_ops = { 207 .show = brport_show, 208 .store = brport_store, 209 }; 210 211 /* 212 * Add sysfs entries to ethernet device added to a bridge. 213 * Creates a brport subdirectory with bridge attributes. 214 * Puts symlink in bridge's brport subdirectory 215 */ 216 int br_sysfs_addif(struct net_bridge_port *p) 217 { 218 struct net_bridge *br = p->br; 219 struct brport_attribute **a; 220 int err; 221 222 err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, 223 SYSFS_BRIDGE_PORT_LINK); 224 if (err) 225 goto out2; 226 227 for (a = brport_attrs; *a; ++a) { 228 err = sysfs_create_file(&p->kobj, &((*a)->attr)); 229 if (err) 230 goto out2; 231 } 232 233 err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); 234 out2: 235 return err; 236 } 237