linux/drivers/net/bonding/bond_sysfs_slave.c
<<
>>
Prefs
   1/*      Sysfs attributes of bond slaves
   2 *
   3 *      Copyright (c) 2014 Scott Feldman <sfeldma@cumulusnetworks.com>
   4 *
   5 *      This program is free software; you can redistribute it and/or
   6 *      modify it under the terms of the GNU General Public License
   7 *      as published by the Free Software Foundation; either version
   8 *      2 of the License, or (at your option) any later version.
   9 */
  10
  11#include <linux/capability.h>
  12#include <linux/kernel.h>
  13#include <linux/netdevice.h>
  14
  15#include <net/bonding.h>
  16
  17struct slave_attribute {
  18        struct attribute attr;
  19        ssize_t (*show)(struct slave *, char *);
  20};
  21
  22#define SLAVE_ATTR(_name, _mode, _show)                         \
  23const struct slave_attribute slave_attr_##_name = {             \
  24        .attr = {.name = __stringify(_name),                    \
  25                 .mode = _mode },                               \
  26        .show   = _show,                                        \
  27};
  28#define SLAVE_ATTR_RO(_name) \
  29        SLAVE_ATTR(_name, S_IRUGO, _name##_show)
  30
  31static ssize_t state_show(struct slave *slave, char *buf)
  32{
  33        switch (bond_slave_state(slave)) {
  34        case BOND_STATE_ACTIVE:
  35                return sprintf(buf, "active\n");
  36        case BOND_STATE_BACKUP:
  37                return sprintf(buf, "backup\n");
  38        default:
  39                return sprintf(buf, "UNKNOWN\n");
  40        }
  41}
  42static SLAVE_ATTR_RO(state);
  43
  44static ssize_t mii_status_show(struct slave *slave, char *buf)
  45{
  46        return sprintf(buf, "%s\n", bond_slave_link_status(slave->link));
  47}
  48static SLAVE_ATTR_RO(mii_status);
  49
  50static ssize_t link_failure_count_show(struct slave *slave, char *buf)
  51{
  52        return sprintf(buf, "%d\n", slave->link_failure_count);
  53}
  54static SLAVE_ATTR_RO(link_failure_count);
  55
  56static ssize_t perm_hwaddr_show(struct slave *slave, char *buf)
  57{
  58        return sprintf(buf, "%pM\n", slave->perm_hwaddr);
  59}
  60static SLAVE_ATTR_RO(perm_hwaddr);
  61
  62static ssize_t queue_id_show(struct slave *slave, char *buf)
  63{
  64        return sprintf(buf, "%d\n", slave->queue_id);
  65}
  66static SLAVE_ATTR_RO(queue_id);
  67
  68static ssize_t ad_aggregator_id_show(struct slave *slave, char *buf)
  69{
  70        const struct aggregator *agg;
  71
  72        if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
  73                agg = SLAVE_AD_INFO(slave)->port.aggregator;
  74                if (agg)
  75                        return sprintf(buf, "%d\n",
  76                                       agg->aggregator_identifier);
  77        }
  78
  79        return sprintf(buf, "N/A\n");
  80}
  81static SLAVE_ATTR_RO(ad_aggregator_id);
  82
  83static ssize_t ad_actor_oper_port_state_show(struct slave *slave, char *buf)
  84{
  85        const struct port *ad_port;
  86
  87        if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
  88                ad_port = &SLAVE_AD_INFO(slave)->port;
  89                if (ad_port->aggregator)
  90                        return sprintf(buf, "%u\n",
  91                                       ad_port->actor_oper_port_state);
  92        }
  93
  94        return sprintf(buf, "N/A\n");
  95}
  96static SLAVE_ATTR_RO(ad_actor_oper_port_state);
  97
  98static ssize_t ad_partner_oper_port_state_show(struct slave *slave, char *buf)
  99{
 100        const struct port *ad_port;
 101
 102        if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
 103                ad_port = &SLAVE_AD_INFO(slave)->port;
 104                if (ad_port->aggregator)
 105                        return sprintf(buf, "%u\n",
 106                                       ad_port->partner_oper.port_state);
 107        }
 108
 109        return sprintf(buf, "N/A\n");
 110}
 111static SLAVE_ATTR_RO(ad_partner_oper_port_state);
 112
 113static const struct slave_attribute *slave_attrs[] = {
 114        &slave_attr_state,
 115        &slave_attr_mii_status,
 116        &slave_attr_link_failure_count,
 117        &slave_attr_perm_hwaddr,
 118        &slave_attr_queue_id,
 119        &slave_attr_ad_aggregator_id,
 120        &slave_attr_ad_actor_oper_port_state,
 121        &slave_attr_ad_partner_oper_port_state,
 122        NULL
 123};
 124
 125#define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr)
 126#define to_slave(obj)   container_of(obj, struct slave, kobj)
 127
 128static ssize_t slave_show(struct kobject *kobj,
 129                          struct attribute *attr, char *buf)
 130{
 131        struct slave_attribute *slave_attr = to_slave_attr(attr);
 132        struct slave *slave = to_slave(kobj);
 133
 134        return slave_attr->show(slave, buf);
 135}
 136
 137static const struct sysfs_ops slave_sysfs_ops = {
 138        .show = slave_show,
 139};
 140
 141static struct kobj_type slave_ktype = {
 142#ifdef CONFIG_SYSFS
 143        .sysfs_ops = &slave_sysfs_ops,
 144#endif
 145};
 146
 147int bond_sysfs_slave_add(struct slave *slave)
 148{
 149        const struct slave_attribute **a;
 150        int err;
 151
 152        err = kobject_init_and_add(&slave->kobj, &slave_ktype,
 153                                   &(slave->dev->dev.kobj), "bonding_slave");
 154        if (err)
 155                return err;
 156
 157        for (a = slave_attrs; *a; ++a) {
 158                err = sysfs_create_file(&slave->kobj, &((*a)->attr));
 159                if (err) {
 160                        kobject_put(&slave->kobj);
 161                        return err;
 162                }
 163        }
 164
 165        return 0;
 166}
 167
 168void bond_sysfs_slave_del(struct slave *slave)
 169{
 170        const struct slave_attribute **a;
 171
 172        for (a = slave_attrs; *a; ++a)
 173                sysfs_remove_file(&slave->kobj, &((*a)->attr));
 174
 175        kobject_put(&slave->kobj);
 176}
 177