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 struct brport_attribute *brport_attrs[] = { 141 &brport_attr_path_cost, 142 &brport_attr_priority, 143 &brport_attr_port_id, 144 &brport_attr_port_no, 145 &brport_attr_designated_root, 146 &brport_attr_designated_bridge, 147 &brport_attr_designated_port, 148 &brport_attr_designated_cost, 149 &brport_attr_state, 150 &brport_attr_change_ack, 151 &brport_attr_config_pending, 152 &brport_attr_message_age_timer, 153 &brport_attr_forward_delay_timer, 154 &brport_attr_hold_timer, 155 NULL 156 }; 157 158 #define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr) 159 #define to_brport(obj) container_of(obj, struct net_bridge_port, kobj) 160 161 static ssize_t brport_show(struct kobject * kobj, 162 struct attribute * attr, char * buf) 163 { 164 struct brport_attribute * brport_attr = to_brport_attr(attr); 165 struct net_bridge_port * p = to_brport(kobj); 166 167 return brport_attr->show(p, buf); 168 } 169 170 static ssize_t brport_store(struct kobject * kobj, 171 struct attribute * attr, 172 const char * buf, size_t count) 173 { 174 struct brport_attribute * brport_attr = to_brport_attr(attr); 175 struct net_bridge_port * p = to_brport(kobj); 176 ssize_t ret = -EINVAL; 177 char *endp; 178 unsigned long val; 179 180 if (!capable(CAP_NET_ADMIN)) 181 return -EPERM; 182 183 val = simple_strtoul(buf, &endp, 0); 184 if (endp != buf) { 185 rtnl_lock(); 186 if (p->dev && p->br && brport_attr->store) { 187 spin_lock_bh(&p->br->lock); 188 ret = brport_attr->store(p, val); 189 spin_unlock_bh(&p->br->lock); 190 if (ret == 0) 191 ret = count; 192 } 193 rtnl_unlock(); 194 } 195 return ret; 196 } 197 198 struct sysfs_ops brport_sysfs_ops = { 199 .show = brport_show, 200 .store = brport_store, 201 }; 202 203 /* 204 * Add sysfs entries to ethernet device added to a bridge. 205 * Creates a brport subdirectory with bridge attributes. 206 * Puts symlink in bridge's brport subdirectory 207 */ 208 int br_sysfs_addif(struct net_bridge_port *p) 209 { 210 struct net_bridge *br = p->br; 211 struct brport_attribute **a; 212 int err; 213 214 err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, 215 SYSFS_BRIDGE_PORT_LINK); 216 if (err) 217 goto out2; 218 219 for (a = brport_attrs; *a; ++a) { 220 err = sysfs_create_file(&p->kobj, &((*a)->attr)); 221 if (err) 222 goto out2; 223 } 224 225 err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); 226 out2: 227 return err; 228 } 229