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 151ef8019bSDavid S. Miller #include <net/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: 399b13494cSMasanari 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 83254cb6dbSNikolay Aleksandrov static ssize_t ad_actor_oper_port_state_show(struct slave *slave, char *buf) 84254cb6dbSNikolay Aleksandrov { 85254cb6dbSNikolay Aleksandrov const struct port *ad_port; 86254cb6dbSNikolay Aleksandrov 87254cb6dbSNikolay Aleksandrov if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) { 88254cb6dbSNikolay Aleksandrov ad_port = &SLAVE_AD_INFO(slave)->port; 89254cb6dbSNikolay Aleksandrov if (ad_port->aggregator) 90254cb6dbSNikolay Aleksandrov return sprintf(buf, "%u\n", 91254cb6dbSNikolay Aleksandrov ad_port->actor_oper_port_state); 92254cb6dbSNikolay Aleksandrov } 93254cb6dbSNikolay Aleksandrov 94254cb6dbSNikolay Aleksandrov return sprintf(buf, "N/A\n"); 95254cb6dbSNikolay Aleksandrov } 96254cb6dbSNikolay Aleksandrov static SLAVE_ATTR_RO(ad_actor_oper_port_state); 97254cb6dbSNikolay Aleksandrov 98*46ea297eSNikolay Aleksandrov static ssize_t ad_partner_oper_port_state_show(struct slave *slave, char *buf) 99*46ea297eSNikolay Aleksandrov { 100*46ea297eSNikolay Aleksandrov const struct port *ad_port; 101*46ea297eSNikolay Aleksandrov 102*46ea297eSNikolay Aleksandrov if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) { 103*46ea297eSNikolay Aleksandrov ad_port = &SLAVE_AD_INFO(slave)->port; 104*46ea297eSNikolay Aleksandrov if (ad_port->aggregator) 105*46ea297eSNikolay Aleksandrov return sprintf(buf, "%u\n", 106*46ea297eSNikolay Aleksandrov ad_port->partner_oper.port_state); 107*46ea297eSNikolay Aleksandrov } 108*46ea297eSNikolay Aleksandrov 109*46ea297eSNikolay Aleksandrov return sprintf(buf, "N/A\n"); 110*46ea297eSNikolay Aleksandrov } 111*46ea297eSNikolay Aleksandrov static SLAVE_ATTR_RO(ad_partner_oper_port_state); 112*46ea297eSNikolay Aleksandrov 11307699f9aSsfeldma@cumulusnetworks.com static const struct slave_attribute *slave_attrs[] = { 11407699f9aSsfeldma@cumulusnetworks.com &slave_attr_state, 11507699f9aSsfeldma@cumulusnetworks.com &slave_attr_mii_status, 11607699f9aSsfeldma@cumulusnetworks.com &slave_attr_link_failure_count, 11707699f9aSsfeldma@cumulusnetworks.com &slave_attr_perm_hwaddr, 11807699f9aSsfeldma@cumulusnetworks.com &slave_attr_queue_id, 11907699f9aSsfeldma@cumulusnetworks.com &slave_attr_ad_aggregator_id, 120254cb6dbSNikolay Aleksandrov &slave_attr_ad_actor_oper_port_state, 121*46ea297eSNikolay Aleksandrov &slave_attr_ad_partner_oper_port_state, 12207699f9aSsfeldma@cumulusnetworks.com NULL 12307699f9aSsfeldma@cumulusnetworks.com }; 12407699f9aSsfeldma@cumulusnetworks.com 12507699f9aSsfeldma@cumulusnetworks.com #define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr) 12607699f9aSsfeldma@cumulusnetworks.com #define to_slave(obj) container_of(obj, struct slave, kobj) 12707699f9aSsfeldma@cumulusnetworks.com 12807699f9aSsfeldma@cumulusnetworks.com static ssize_t slave_show(struct kobject *kobj, 12907699f9aSsfeldma@cumulusnetworks.com struct attribute *attr, char *buf) 13007699f9aSsfeldma@cumulusnetworks.com { 13107699f9aSsfeldma@cumulusnetworks.com struct slave_attribute *slave_attr = to_slave_attr(attr); 13207699f9aSsfeldma@cumulusnetworks.com struct slave *slave = to_slave(kobj); 13307699f9aSsfeldma@cumulusnetworks.com 13407699f9aSsfeldma@cumulusnetworks.com return slave_attr->show(slave, buf); 13507699f9aSsfeldma@cumulusnetworks.com } 13607699f9aSsfeldma@cumulusnetworks.com 1378d783163Sstephen hemminger static const struct sysfs_ops slave_sysfs_ops = { 13807699f9aSsfeldma@cumulusnetworks.com .show = slave_show, 13907699f9aSsfeldma@cumulusnetworks.com }; 14007699f9aSsfeldma@cumulusnetworks.com 14107699f9aSsfeldma@cumulusnetworks.com static struct kobj_type slave_ktype = { 14207699f9aSsfeldma@cumulusnetworks.com #ifdef CONFIG_SYSFS 14307699f9aSsfeldma@cumulusnetworks.com .sysfs_ops = &slave_sysfs_ops, 14407699f9aSsfeldma@cumulusnetworks.com #endif 14507699f9aSsfeldma@cumulusnetworks.com }; 14607699f9aSsfeldma@cumulusnetworks.com 14707699f9aSsfeldma@cumulusnetworks.com int bond_sysfs_slave_add(struct slave *slave) 14807699f9aSsfeldma@cumulusnetworks.com { 14907699f9aSsfeldma@cumulusnetworks.com const struct slave_attribute **a; 15007699f9aSsfeldma@cumulusnetworks.com int err; 15107699f9aSsfeldma@cumulusnetworks.com 15207699f9aSsfeldma@cumulusnetworks.com err = kobject_init_and_add(&slave->kobj, &slave_ktype, 1530a9099f8SJiri Pirko &(slave->dev->dev.kobj), "bonding_slave"); 15407699f9aSsfeldma@cumulusnetworks.com if (err) 15507699f9aSsfeldma@cumulusnetworks.com return err; 15607699f9aSsfeldma@cumulusnetworks.com 15707699f9aSsfeldma@cumulusnetworks.com for (a = slave_attrs; *a; ++a) { 15807699f9aSsfeldma@cumulusnetworks.com err = sysfs_create_file(&slave->kobj, &((*a)->attr)); 15907699f9aSsfeldma@cumulusnetworks.com if (err) { 1607afcaec4SVeaceslav Falico kobject_put(&slave->kobj); 16107699f9aSsfeldma@cumulusnetworks.com return err; 16207699f9aSsfeldma@cumulusnetworks.com } 16307699f9aSsfeldma@cumulusnetworks.com } 16407699f9aSsfeldma@cumulusnetworks.com 16507699f9aSsfeldma@cumulusnetworks.com return 0; 16607699f9aSsfeldma@cumulusnetworks.com } 16707699f9aSsfeldma@cumulusnetworks.com 16807699f9aSsfeldma@cumulusnetworks.com void bond_sysfs_slave_del(struct slave *slave) 16907699f9aSsfeldma@cumulusnetworks.com { 17007699f9aSsfeldma@cumulusnetworks.com const struct slave_attribute **a; 17107699f9aSsfeldma@cumulusnetworks.com 17207699f9aSsfeldma@cumulusnetworks.com for (a = slave_attrs; *a; ++a) 17307699f9aSsfeldma@cumulusnetworks.com sysfs_remove_file(&slave->kobj, &((*a)->attr)); 17407699f9aSsfeldma@cumulusnetworks.com 1757afcaec4SVeaceslav Falico kobject_put(&slave->kobj); 17607699f9aSsfeldma@cumulusnetworks.com } 177