1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Sysfs attributes of bridge ports 4 * Linux ethernet bridge 5 * 6 * Authors: 7 * Stephen Hemminger <shemminger@osdl.org> 8 */ 9 10#include <linux/capability.h> 11#include <linux/kernel.h> 12#include <linux/netdevice.h> 13#include <linux/if_bridge.h> 14#include <linux/rtnetlink.h> 15#include <linux/spinlock.h> 16#include <linux/sched/signal.h> 17 18#include "br_private.h" 19 20struct brport_attribute { 21 struct attribute attr; 22 ssize_t (*show)(struct net_bridge_port *, char *); 23 int (*store)(struct net_bridge_port *, unsigned long); 24 int (*store_raw)(struct net_bridge_port *, char *); 25}; 26 27#define BRPORT_ATTR_RAW(_name, _mode, _show, _store) \ 28const struct brport_attribute brport_attr_##_name = { \ 29 .attr = {.name = __stringify(_name), \ 30 .mode = _mode }, \ 31 .show = _show, \ 32 .store_raw = _store, \ 33}; 34 35#define BRPORT_ATTR(_name, _mode, _show, _store) \ 36const struct brport_attribute brport_attr_##_name = { \ 37 .attr = {.name = __stringify(_name), \ 38 .mode = _mode }, \ 39 .show = _show, \ 40 .store = _store, \ 41}; 42 43#define BRPORT_ATTR_FLAG(_name, _mask) \ 44static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \ 45{ \ 46 return sprintf(buf, "%d\n", !!(p->flags & _mask)); \ 47} \ 48static int store_##_name(struct net_bridge_port *p, unsigned long v) \ 49{ \ 50 return store_flag(p, v, _mask); \ 51} \ 52static BRPORT_ATTR(_name, 0644, \ 53 show_##_name, store_##_name) 54 55static int store_flag(struct net_bridge_port *p, unsigned long v, 56 unsigned long mask) 57{ 58 unsigned long flags = p->flags; 59 int err; 60 61 if (v) 62 flags |= mask; 63 else 64 flags &= ~mask; 65 66 if (flags != p->flags) { 67 err = br_switchdev_set_port_flag(p, flags, mask); 68 if (err) 69 return err; 70 71 p->flags = flags; 72 br_port_flags_change(p, mask); 73 } 74 return 0; 75} 76 77static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) 78{ 79 return sprintf(buf, "%d\n", p->path_cost); 80} 81 82static BRPORT_ATTR(path_cost, 0644, 83 show_path_cost, br_stp_set_path_cost); 84 85static ssize_t show_priority(struct net_bridge_port *p, char *buf) 86{ 87 return sprintf(buf, "%d\n", p->priority); 88} 89 90static BRPORT_ATTR(priority, 0644, 91 show_priority, br_stp_set_port_priority); 92 93static ssize_t show_designated_root(struct net_bridge_port *p, char *buf) 94{ 95 return br_show_bridge_id(buf, &p->designated_root); 96} 97static BRPORT_ATTR(designated_root, 0444, show_designated_root, NULL); 98 99static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf) 100{ 101 return br_show_bridge_id(buf, &p->designated_bridge); 102} 103static BRPORT_ATTR(designated_bridge, 0444, show_designated_bridge, NULL); 104 105static ssize_t show_designated_port(struct net_bridge_port *p, char *buf) 106{ 107 return sprintf(buf, "%d\n", p->designated_port); 108} 109static BRPORT_ATTR(designated_port, 0444, show_designated_port, NULL); 110 111static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf) 112{ 113 return sprintf(buf, "%d\n", p->designated_cost); 114} 115static BRPORT_ATTR(designated_cost, 0444, show_designated_cost, NULL); 116 117static ssize_t show_port_id(struct net_bridge_port *p, char *buf) 118{ 119 return sprintf(buf, "0x%x\n", p->port_id); 120} 121static BRPORT_ATTR(port_id, 0444, show_port_id, NULL); 122 123static ssize_t show_port_no(struct net_bridge_port *p, char *buf) 124{ 125 return sprintf(buf, "0x%x\n", p->port_no); 126} 127 128static BRPORT_ATTR(port_no, 0444, show_port_no, NULL); 129 130static ssize_t show_change_ack(struct net_bridge_port *p, char *buf) 131{ 132 return sprintf(buf, "%d\n", p->topology_change_ack); 133} 134static BRPORT_ATTR(change_ack, 0444, show_change_ack, NULL); 135 136static ssize_t show_config_pending(struct net_bridge_port *p, char *buf) 137{ 138 return sprintf(buf, "%d\n", p->config_pending); 139} 140static BRPORT_ATTR(config_pending, 0444, show_config_pending, NULL); 141 142static ssize_t show_port_state(struct net_bridge_port *p, char *buf) 143{ 144 return sprintf(buf, "%d\n", p->state); 145} 146static BRPORT_ATTR(state, 0444, show_port_state, NULL); 147 148static ssize_t show_message_age_timer(struct net_bridge_port *p, 149 char *buf) 150{ 151 return sprintf(buf, "%ld\n", br_timer_value(&p->message_age_timer)); 152} 153static BRPORT_ATTR(message_age_timer, 0444, show_message_age_timer, NULL); 154 155static ssize_t show_forward_delay_timer(struct net_bridge_port *p, 156 char *buf) 157{ 158 return sprintf(buf, "%ld\n", br_timer_value(&p->forward_delay_timer)); 159} 160static BRPORT_ATTR(forward_delay_timer, 0444, show_forward_delay_timer, NULL); 161 162static ssize_t show_hold_timer(struct net_bridge_port *p, 163 char *buf) 164{ 165 return sprintf(buf, "%ld\n", br_timer_value(&p->hold_timer)); 166} 167static BRPORT_ATTR(hold_timer, 0444, show_hold_timer, NULL); 168 169static int store_flush(struct net_bridge_port *p, unsigned long v) 170{ 171 br_fdb_delete_by_port(p->br, p, 0, 0); // Don't delete local entry 172 return 0; 173} 174static BRPORT_ATTR(flush, 0200, NULL, store_flush); 175 176static ssize_t show_group_fwd_mask(struct net_bridge_port *p, char *buf) 177{ 178 return sprintf(buf, "%#x\n", p->group_fwd_mask); 179} 180 181static int store_group_fwd_mask(struct net_bridge_port *p, 182 unsigned long v) 183{ 184 if (v & BR_GROUPFWD_MACPAUSE) 185 return -EINVAL; 186 p->group_fwd_mask = v; 187 188 return 0; 189} 190static BRPORT_ATTR(group_fwd_mask, 0644, show_group_fwd_mask, 191 store_group_fwd_mask); 192 193static ssize_t show_backup_port(struct net_bridge_port *p, char *buf) 194{ 195 struct net_bridge_port *backup_p; 196 int ret = 0; 197 198 rcu_read_lock(); 199 backup_p = rcu_dereference(p->backup_port); 200 if (backup_p) 201 ret = sprintf(buf, "%s\n", backup_p->dev->name); 202 rcu_read_unlock(); 203 204 return ret; 205} 206 207static int store_backup_port(struct net_bridge_port *p, char *buf) 208{ 209 struct net_device *backup_dev = NULL; 210 char *nl = strchr(buf, '\n'); 211 212 if (nl) 213 *nl = '\0'; 214 215 if (strlen(buf) > 0) { 216 backup_dev = __dev_get_by_name(dev_net(p->dev), buf); 217 if (!backup_dev) 218 return -ENOENT; 219 } 220 221 return nbp_backup_change(p, backup_dev); 222} 223static BRPORT_ATTR_RAW(backup_port, 0644, show_backup_port, store_backup_port); 224 225BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); 226BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD); 227BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); 228BRPORT_ATTR_FLAG(learning, BR_LEARNING); 229BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD); 230BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP); 231BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI); 232BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD); 233BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); 234BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); 235BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); 236 237#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 238static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) 239{ 240 return sprintf(buf, "%d\n", p->multicast_router); 241} 242 243static int store_multicast_router(struct net_bridge_port *p, 244 unsigned long v) 245{ 246 return br_multicast_set_port_router(p, v); 247} 248static BRPORT_ATTR(multicast_router, 0644, show_multicast_router, 249 store_multicast_router); 250 251BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE); 252BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST); 253#endif 254 255static const struct brport_attribute *brport_attrs[] = { 256 &brport_attr_path_cost, 257 &brport_attr_priority, 258 &brport_attr_port_id, 259 &brport_attr_port_no, 260 &brport_attr_designated_root, 261 &brport_attr_designated_bridge, 262 &brport_attr_designated_port, 263 &brport_attr_designated_cost, 264 &brport_attr_state, 265 &brport_attr_change_ack, 266 &brport_attr_config_pending, 267 &brport_attr_message_age_timer, 268 &brport_attr_forward_delay_timer, 269 &brport_attr_hold_timer, 270 &brport_attr_flush, 271 &brport_attr_hairpin_mode, 272 &brport_attr_bpdu_guard, 273 &brport_attr_root_block, 274 &brport_attr_learning, 275 &brport_attr_unicast_flood, 276#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 277 &brport_attr_multicast_router, 278 &brport_attr_multicast_fast_leave, 279 &brport_attr_multicast_to_unicast, 280#endif 281 &brport_attr_proxyarp, 282 &brport_attr_proxyarp_wifi, 283 &brport_attr_multicast_flood, 284 &brport_attr_broadcast_flood, 285 &brport_attr_group_fwd_mask, 286 &brport_attr_neigh_suppress, 287 &brport_attr_isolated, 288 &brport_attr_backup_port, 289 NULL 290}; 291 292#define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr) 293 294static ssize_t brport_show(struct kobject *kobj, 295 struct attribute *attr, char *buf) 296{ 297 struct brport_attribute *brport_attr = to_brport_attr(attr); 298 struct net_bridge_port *p = kobj_to_brport(kobj); 299 300 if (!brport_attr->show) 301 return -EINVAL; 302 303 return brport_attr->show(p, buf); 304} 305 306static ssize_t brport_store(struct kobject *kobj, 307 struct attribute *attr, 308 const char *buf, size_t count) 309{ 310 struct brport_attribute *brport_attr = to_brport_attr(attr); 311 struct net_bridge_port *p = kobj_to_brport(kobj); 312 ssize_t ret = -EINVAL; 313 unsigned long val; 314 char *endp; 315 316 if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN)) 317 return -EPERM; 318 319 if (!rtnl_trylock()) 320 return restart_syscall(); 321 322 if (brport_attr->store_raw) { 323 char *buf_copy; 324 325 buf_copy = kstrndup(buf, count, GFP_KERNEL); 326 if (!buf_copy) { 327 ret = -ENOMEM; 328 goto out_unlock; 329 } 330 spin_lock_bh(&p->br->lock); 331 ret = brport_attr->store_raw(p, buf_copy); 332 spin_unlock_bh(&p->br->lock); 333 kfree(buf_copy); 334 } else if (brport_attr->store) { 335 val = simple_strtoul(buf, &endp, 0); 336 if (endp == buf) 337 goto out_unlock; 338 spin_lock_bh(&p->br->lock); 339 ret = brport_attr->store(p, val); 340 spin_unlock_bh(&p->br->lock); 341 } 342 343 if (!ret) { 344 br_ifinfo_notify(RTM_NEWLINK, NULL, p); 345 ret = count; 346 } 347out_unlock: 348 rtnl_unlock(); 349 350 return ret; 351} 352 353const struct sysfs_ops brport_sysfs_ops = { 354 .show = brport_show, 355 .store = brport_store, 356}; 357 358/* 359 * Add sysfs entries to ethernet device added to a bridge. 360 * Creates a brport subdirectory with bridge attributes. 361 * Puts symlink in bridge's brif subdirectory 362 */ 363int br_sysfs_addif(struct net_bridge_port *p) 364{ 365 struct net_bridge *br = p->br; 366 const struct brport_attribute **a; 367 int err; 368 369 err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, 370 SYSFS_BRIDGE_PORT_LINK); 371 if (err) 372 return err; 373 374 for (a = brport_attrs; *a; ++a) { 375 err = sysfs_create_file(&p->kobj, &((*a)->attr)); 376 if (err) 377 return err; 378 } 379 380 strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ); 381 return sysfs_create_link(br->ifobj, &p->kobj, p->sysfs_name); 382} 383 384/* Rename bridge's brif symlink */ 385int br_sysfs_renameif(struct net_bridge_port *p) 386{ 387 struct net_bridge *br = p->br; 388 int err; 389 390 /* If a rename fails, the rollback will cause another 391 * rename call with the existing name. 392 */ 393 if (!strncmp(p->sysfs_name, p->dev->name, IFNAMSIZ)) 394 return 0; 395 396 err = sysfs_rename_link(br->ifobj, &p->kobj, 397 p->sysfs_name, p->dev->name); 398 if (err) 399 netdev_notice(br->dev, "unable to rename link %s to %s", 400 p->sysfs_name, p->dev->name); 401 else 402 strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ); 403 404 return err; 405} 406