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