Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bonding: add sysfs /slave dir for bond slave devices.

Add sub-directory under /sys/class/net/<interface>/slave with
read-only attributes for slave. Directory only appears when
<interface> is a slave.

$ tree /sys/class/net/eth2/slave/
/sys/class/net/eth2/slave/
├── ad_aggregator_id
├── link_failure_count
├── mii_status
├── perm_hwaddr
├── queue_id
└── state

$ cat /sys/class/net/eth2/slave/*
2
0
up
40:02:10:ef:06:01
0
active

Signed-off-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

sfeldma@cumulusnetworks.com and committed by
David S. Miller
07699f9a fd27e0d4

+176 -13
+1 -1
drivers/net/bonding/Makefile
··· 4 4 5 5 obj-$(CONFIG_BONDING) += bonding.o 6 6 7 - bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o bond_netlink.o bond_options.o 7 + bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_sysfs_slave.o bond_debugfs.o bond_netlink.o bond_options.o 8 8 9 9 proc-$(CONFIG_PROC_FS) += bond_procfs.o 10 10 bonding-objs += $(proc-y)
+27
drivers/net/bonding/bond_main.c
··· 466 466 return; 467 467 } 468 468 469 + const char *bond_slave_link_status(s8 link) 470 + { 471 + switch (link) { 472 + case BOND_LINK_UP: 473 + return "up"; 474 + case BOND_LINK_FAIL: 475 + return "going down"; 476 + case BOND_LINK_DOWN: 477 + return "down"; 478 + case BOND_LINK_BACK: 479 + return "going back"; 480 + default: 481 + return "unknown"; 482 + } 483 + } 484 + 469 485 /* 470 486 * if <dev> supports MII link status reporting, check its link status. 471 487 * ··· 1592 1576 goto err_unregister; 1593 1577 } 1594 1578 1579 + res = bond_sysfs_slave_add(new_slave); 1580 + if (res) { 1581 + pr_debug("Error %d calling bond_sysfs_slave_add\n", res); 1582 + goto err_upper_unlink; 1583 + } 1584 + 1595 1585 bond->slave_cnt++; 1596 1586 bond_compute_features(bond); 1597 1587 bond_set_carrier(bond); ··· 1617 1595 return 0; 1618 1596 1619 1597 /* Undo stages on error */ 1598 + err_upper_unlink: 1599 + bond_upper_dev_unlink(bond_dev, slave_dev); 1600 + 1620 1601 err_unregister: 1621 1602 netdev_rx_handler_unregister(slave_dev); 1622 1603 ··· 1711 1686 1712 1687 /* release the slave from its bond */ 1713 1688 bond->slave_cnt--; 1689 + 1690 + bond_sysfs_slave_del(slave); 1714 1691 1715 1692 bond_upper_dev_unlink(bond_dev, slave_dev); 1716 1693 /* unregister rx_handler early so bond_handle_frame wouldn't be called
-12
drivers/net/bonding/bond_procfs.c
··· 159 159 } 160 160 } 161 161 162 - static const char *bond_slave_link_status(s8 link) 163 - { 164 - static const char * const status[] = { 165 - [BOND_LINK_UP] = "up", 166 - [BOND_LINK_FAIL] = "going down", 167 - [BOND_LINK_DOWN] = "down", 168 - [BOND_LINK_BACK] = "going back", 169 - }; 170 - 171 - return status[link]; 172 - } 173 - 174 162 static void bond_info_show_slave(struct seq_file *seq, 175 163 const struct slave *slave) 176 164 {
+144
drivers/net/bonding/bond_sysfs_slave.c
··· 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 "bonding.h" 16 + 17 + struct slave_attribute { 18 + struct attribute attr; 19 + ssize_t (*show)(struct slave *, char *); 20 + }; 21 + 22 + #define SLAVE_ATTR(_name, _mode, _show) \ 23 + const 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 + 31 + static 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, "UNKONWN\n"); 40 + } 41 + } 42 + static SLAVE_ATTR_RO(state); 43 + 44 + static ssize_t mii_status_show(struct slave *slave, char *buf) 45 + { 46 + return sprintf(buf, "%s\n", bond_slave_link_status(slave->link)); 47 + } 48 + static SLAVE_ATTR_RO(mii_status); 49 + 50 + static ssize_t link_failure_count_show(struct slave *slave, char *buf) 51 + { 52 + return sprintf(buf, "%d\n", slave->link_failure_count); 53 + } 54 + static SLAVE_ATTR_RO(link_failure_count); 55 + 56 + static ssize_t perm_hwaddr_show(struct slave *slave, char *buf) 57 + { 58 + return sprintf(buf, "%pM\n", slave->perm_hwaddr); 59 + } 60 + static SLAVE_ATTR_RO(perm_hwaddr); 61 + 62 + static ssize_t queue_id_show(struct slave *slave, char *buf) 63 + { 64 + return sprintf(buf, "%d\n", slave->queue_id); 65 + } 66 + static SLAVE_ATTR_RO(queue_id); 67 + 68 + static ssize_t ad_aggregator_id_show(struct slave *slave, char *buf) 69 + { 70 + const struct aggregator *agg; 71 + 72 + if (slave->bond->params.mode == 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 + } 81 + static SLAVE_ATTR_RO(ad_aggregator_id); 82 + 83 + static const struct slave_attribute *slave_attrs[] = { 84 + &slave_attr_state, 85 + &slave_attr_mii_status, 86 + &slave_attr_link_failure_count, 87 + &slave_attr_perm_hwaddr, 88 + &slave_attr_queue_id, 89 + &slave_attr_ad_aggregator_id, 90 + NULL 91 + }; 92 + 93 + #define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr) 94 + #define to_slave(obj) container_of(obj, struct slave, kobj) 95 + 96 + static ssize_t slave_show(struct kobject *kobj, 97 + struct attribute *attr, char *buf) 98 + { 99 + struct slave_attribute *slave_attr = to_slave_attr(attr); 100 + struct slave *slave = to_slave(kobj); 101 + 102 + return slave_attr->show(slave, buf); 103 + } 104 + 105 + const struct sysfs_ops slave_sysfs_ops = { 106 + .show = slave_show, 107 + }; 108 + 109 + static struct kobj_type slave_ktype = { 110 + #ifdef CONFIG_SYSFS 111 + .sysfs_ops = &slave_sysfs_ops, 112 + #endif 113 + }; 114 + 115 + int bond_sysfs_slave_add(struct slave *slave) 116 + { 117 + const struct slave_attribute **a; 118 + int err; 119 + 120 + err = kobject_init_and_add(&slave->kobj, &slave_ktype, 121 + &(slave->dev->dev.kobj), "slave"); 122 + if (err) 123 + return err; 124 + 125 + for (a = slave_attrs; *a; ++a) { 126 + err = sysfs_create_file(&slave->kobj, &((*a)->attr)); 127 + if (err) { 128 + kobject_del(&slave->kobj); 129 + return err; 130 + } 131 + } 132 + 133 + return 0; 134 + } 135 + 136 + void bond_sysfs_slave_del(struct slave *slave) 137 + { 138 + const struct slave_attribute **a; 139 + 140 + for (a = slave_attrs; *a; ++a) 141 + sysfs_remove_file(&slave->kobj, &((*a)->attr)); 142 + 143 + kobject_del(&slave->kobj); 144 + }
+4
drivers/net/bonding/bonding.h
··· 203 203 #ifdef CONFIG_NET_POLL_CONTROLLER 204 204 struct netpoll *np; 205 205 #endif 206 + struct kobject kobj; 206 207 }; 207 208 208 209 /* ··· 422 421 int bond_create_sysfs(struct bond_net *net); 423 422 void bond_destroy_sysfs(struct bond_net *net); 424 423 void bond_prepare_sysfs_group(struct bonding *bond); 424 + int bond_sysfs_slave_add(struct slave *slave); 425 + void bond_sysfs_slave_del(struct slave *slave); 425 426 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev); 426 427 int bond_release(struct net_device *bond_dev, struct net_device *slave_dev); 427 428 int bond_xmit_hash(struct bonding *bond, struct sk_buff *skb, int count); ··· 472 469 int bond_option_ad_select_set(struct bonding *bond, int ad_select); 473 470 struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); 474 471 struct net_device *bond_option_active_slave_get(struct bonding *bond); 472 + const char *bond_slave_link_status(s8 link); 475 473 476 474 struct bond_net { 477 475 struct net * net; /* Associated network namespace */