107699f9aSsfeldma@cumulusnetworks.com /* Sysfs attributes of bond slaves 207699f9aSsfeldma@cumulusnetworks.com * 307699f9aSsfeldma@cumulusnetworks.com * Copyright (c) 2014 Scott Feldman <sfeldma@cumulusnetworks.com> 407699f9aSsfeldma@cumulusnetworks.com * 507699f9aSsfeldma@cumulusnetworks.com * This program is free software; you can redistribute it and/or 607699f9aSsfeldma@cumulusnetworks.com * modify it under the terms of the GNU General Public License 707699f9aSsfeldma@cumulusnetworks.com * as published by the Free Software Foundation; either version 807699f9aSsfeldma@cumulusnetworks.com * 2 of the License, or (at your option) any later version. 907699f9aSsfeldma@cumulusnetworks.com */ 1007699f9aSsfeldma@cumulusnetworks.com 1107699f9aSsfeldma@cumulusnetworks.com #include <linux/capability.h> 1207699f9aSsfeldma@cumulusnetworks.com #include <linux/kernel.h> 1307699f9aSsfeldma@cumulusnetworks.com #include <linux/netdevice.h> 1407699f9aSsfeldma@cumulusnetworks.com 1507699f9aSsfeldma@cumulusnetworks.com #include "bonding.h" 1607699f9aSsfeldma@cumulusnetworks.com 1707699f9aSsfeldma@cumulusnetworks.com struct slave_attribute { 1807699f9aSsfeldma@cumulusnetworks.com struct attribute attr; 1907699f9aSsfeldma@cumulusnetworks.com ssize_t (*show)(struct slave *, char *); 2007699f9aSsfeldma@cumulusnetworks.com }; 2107699f9aSsfeldma@cumulusnetworks.com 2207699f9aSsfeldma@cumulusnetworks.com #define SLAVE_ATTR(_name, _mode, _show) \ 2307699f9aSsfeldma@cumulusnetworks.com const struct slave_attribute slave_attr_##_name = { \ 2407699f9aSsfeldma@cumulusnetworks.com .attr = {.name = __stringify(_name), \ 2507699f9aSsfeldma@cumulusnetworks.com .mode = _mode }, \ 2607699f9aSsfeldma@cumulusnetworks.com .show = _show, \ 2707699f9aSsfeldma@cumulusnetworks.com }; 2807699f9aSsfeldma@cumulusnetworks.com #define SLAVE_ATTR_RO(_name) \ 2907699f9aSsfeldma@cumulusnetworks.com SLAVE_ATTR(_name, S_IRUGO, _name##_show) 3007699f9aSsfeldma@cumulusnetworks.com 3107699f9aSsfeldma@cumulusnetworks.com static ssize_t state_show(struct slave *slave, char *buf) 3207699f9aSsfeldma@cumulusnetworks.com { 3307699f9aSsfeldma@cumulusnetworks.com switch (bond_slave_state(slave)) { 3407699f9aSsfeldma@cumulusnetworks.com case BOND_STATE_ACTIVE: 3507699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "active\n"); 3607699f9aSsfeldma@cumulusnetworks.com case BOND_STATE_BACKUP: 3707699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "backup\n"); 3807699f9aSsfeldma@cumulusnetworks.com default: 39*9b13494cSMasanari Iida return sprintf(buf, "UNKNOWN\n"); 4007699f9aSsfeldma@cumulusnetworks.com } 4107699f9aSsfeldma@cumulusnetworks.com } 4207699f9aSsfeldma@cumulusnetworks.com static SLAVE_ATTR_RO(state); 4307699f9aSsfeldma@cumulusnetworks.com 4407699f9aSsfeldma@cumulusnetworks.com static ssize_t mii_status_show(struct slave *slave, char *buf) 4507699f9aSsfeldma@cumulusnetworks.com { 4607699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "%s\n", bond_slave_link_status(slave->link)); 4707699f9aSsfeldma@cumulusnetworks.com } 4807699f9aSsfeldma@cumulusnetworks.com static SLAVE_ATTR_RO(mii_status); 4907699f9aSsfeldma@cumulusnetworks.com 5007699f9aSsfeldma@cumulusnetworks.com static ssize_t link_failure_count_show(struct slave *slave, char *buf) 5107699f9aSsfeldma@cumulusnetworks.com { 5207699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "%d\n", slave->link_failure_count); 5307699f9aSsfeldma@cumulusnetworks.com } 5407699f9aSsfeldma@cumulusnetworks.com static SLAVE_ATTR_RO(link_failure_count); 5507699f9aSsfeldma@cumulusnetworks.com 5607699f9aSsfeldma@cumulusnetworks.com static ssize_t perm_hwaddr_show(struct slave *slave, char *buf) 5707699f9aSsfeldma@cumulusnetworks.com { 5807699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "%pM\n", slave->perm_hwaddr); 5907699f9aSsfeldma@cumulusnetworks.com } 6007699f9aSsfeldma@cumulusnetworks.com static SLAVE_ATTR_RO(perm_hwaddr); 6107699f9aSsfeldma@cumulusnetworks.com 6207699f9aSsfeldma@cumulusnetworks.com static ssize_t queue_id_show(struct slave *slave, char *buf) 6307699f9aSsfeldma@cumulusnetworks.com { 6407699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "%d\n", slave->queue_id); 6507699f9aSsfeldma@cumulusnetworks.com } 6607699f9aSsfeldma@cumulusnetworks.com static SLAVE_ATTR_RO(queue_id); 6707699f9aSsfeldma@cumulusnetworks.com 6807699f9aSsfeldma@cumulusnetworks.com static ssize_t ad_aggregator_id_show(struct slave *slave, char *buf) 6907699f9aSsfeldma@cumulusnetworks.com { 7007699f9aSsfeldma@cumulusnetworks.com const struct aggregator *agg; 7107699f9aSsfeldma@cumulusnetworks.com 7201844098SVeaceslav Falico if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) { 733fdddd85Sdingtianhong agg = SLAVE_AD_INFO(slave)->port.aggregator; 7407699f9aSsfeldma@cumulusnetworks.com if (agg) 7507699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "%d\n", 7607699f9aSsfeldma@cumulusnetworks.com agg->aggregator_identifier); 7707699f9aSsfeldma@cumulusnetworks.com } 7807699f9aSsfeldma@cumulusnetworks.com 7907699f9aSsfeldma@cumulusnetworks.com return sprintf(buf, "N/A\n"); 8007699f9aSsfeldma@cumulusnetworks.com } 8107699f9aSsfeldma@cumulusnetworks.com static SLAVE_ATTR_RO(ad_aggregator_id); 8207699f9aSsfeldma@cumulusnetworks.com 8307699f9aSsfeldma@cumulusnetworks.com static const struct slave_attribute *slave_attrs[] = { 8407699f9aSsfeldma@cumulusnetworks.com &slave_attr_state, 8507699f9aSsfeldma@cumulusnetworks.com &slave_attr_mii_status, 8607699f9aSsfeldma@cumulusnetworks.com &slave_attr_link_failure_count, 8707699f9aSsfeldma@cumulusnetworks.com &slave_attr_perm_hwaddr, 8807699f9aSsfeldma@cumulusnetworks.com &slave_attr_queue_id, 8907699f9aSsfeldma@cumulusnetworks.com &slave_attr_ad_aggregator_id, 9007699f9aSsfeldma@cumulusnetworks.com NULL 9107699f9aSsfeldma@cumulusnetworks.com }; 9207699f9aSsfeldma@cumulusnetworks.com 9307699f9aSsfeldma@cumulusnetworks.com #define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr) 9407699f9aSsfeldma@cumulusnetworks.com #define to_slave(obj) container_of(obj, struct slave, kobj) 9507699f9aSsfeldma@cumulusnetworks.com 9607699f9aSsfeldma@cumulusnetworks.com static ssize_t slave_show(struct kobject *kobj, 9707699f9aSsfeldma@cumulusnetworks.com struct attribute *attr, char *buf) 9807699f9aSsfeldma@cumulusnetworks.com { 9907699f9aSsfeldma@cumulusnetworks.com struct slave_attribute *slave_attr = to_slave_attr(attr); 10007699f9aSsfeldma@cumulusnetworks.com struct slave *slave = to_slave(kobj); 10107699f9aSsfeldma@cumulusnetworks.com 10207699f9aSsfeldma@cumulusnetworks.com return slave_attr->show(slave, buf); 10307699f9aSsfeldma@cumulusnetworks.com } 10407699f9aSsfeldma@cumulusnetworks.com 1058d783163Sstephen hemminger static const struct sysfs_ops slave_sysfs_ops = { 10607699f9aSsfeldma@cumulusnetworks.com .show = slave_show, 10707699f9aSsfeldma@cumulusnetworks.com }; 10807699f9aSsfeldma@cumulusnetworks.com 10907699f9aSsfeldma@cumulusnetworks.com static struct kobj_type slave_ktype = { 11007699f9aSsfeldma@cumulusnetworks.com #ifdef CONFIG_SYSFS 11107699f9aSsfeldma@cumulusnetworks.com .sysfs_ops = &slave_sysfs_ops, 11207699f9aSsfeldma@cumulusnetworks.com #endif 11307699f9aSsfeldma@cumulusnetworks.com }; 11407699f9aSsfeldma@cumulusnetworks.com 11507699f9aSsfeldma@cumulusnetworks.com int bond_sysfs_slave_add(struct slave *slave) 11607699f9aSsfeldma@cumulusnetworks.com { 11707699f9aSsfeldma@cumulusnetworks.com const struct slave_attribute **a; 11807699f9aSsfeldma@cumulusnetworks.com int err; 11907699f9aSsfeldma@cumulusnetworks.com 12007699f9aSsfeldma@cumulusnetworks.com err = kobject_init_and_add(&slave->kobj, &slave_ktype, 1210a9099f8SJiri Pirko &(slave->dev->dev.kobj), "bonding_slave"); 12207699f9aSsfeldma@cumulusnetworks.com if (err) 12307699f9aSsfeldma@cumulusnetworks.com return err; 12407699f9aSsfeldma@cumulusnetworks.com 12507699f9aSsfeldma@cumulusnetworks.com for (a = slave_attrs; *a; ++a) { 12607699f9aSsfeldma@cumulusnetworks.com err = sysfs_create_file(&slave->kobj, &((*a)->attr)); 12707699f9aSsfeldma@cumulusnetworks.com if (err) { 1287afcaec4SVeaceslav Falico kobject_put(&slave->kobj); 12907699f9aSsfeldma@cumulusnetworks.com return err; 13007699f9aSsfeldma@cumulusnetworks.com } 13107699f9aSsfeldma@cumulusnetworks.com } 13207699f9aSsfeldma@cumulusnetworks.com 13307699f9aSsfeldma@cumulusnetworks.com return 0; 13407699f9aSsfeldma@cumulusnetworks.com } 13507699f9aSsfeldma@cumulusnetworks.com 13607699f9aSsfeldma@cumulusnetworks.com void bond_sysfs_slave_del(struct slave *slave) 13707699f9aSsfeldma@cumulusnetworks.com { 13807699f9aSsfeldma@cumulusnetworks.com const struct slave_attribute **a; 13907699f9aSsfeldma@cumulusnetworks.com 14007699f9aSsfeldma@cumulusnetworks.com for (a = slave_attrs; *a; ++a) 14107699f9aSsfeldma@cumulusnetworks.com sysfs_remove_file(&slave->kobj, &((*a)->attr)); 14207699f9aSsfeldma@cumulusnetworks.com 1437afcaec4SVeaceslav Falico kobject_put(&slave->kobj); 14407699f9aSsfeldma@cumulusnetworks.com } 145