Merge branch 'fixes' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur...
[pandora-kernel.git] / drivers / net / bonding / bond_procfs.c
1 #include <linux/proc_fs.h>
2 #include <linux/export.h>
3 #include <net/net_namespace.h>
4 #include <net/netns/generic.h>
5 #include "bonding.h"
6
7
8 static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
9         __acquires(RCU)
10         __acquires(&bond->lock)
11 {
12         struct bonding *bond = seq->private;
13         loff_t off = 0;
14         struct slave *slave;
15         int i;
16
17         /* make sure the bond won't be taken away */
18         rcu_read_lock();
19         read_lock(&bond->lock);
20
21         if (*pos == 0)
22                 return SEQ_START_TOKEN;
23
24         bond_for_each_slave(bond, slave, i) {
25                 if (++off == *pos)
26                         return slave;
27         }
28
29         return NULL;
30 }
31
32 static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
33 {
34         struct bonding *bond = seq->private;
35         struct slave *slave = v;
36
37         ++*pos;
38         if (v == SEQ_START_TOKEN)
39                 return bond->first_slave;
40
41         slave = slave->next;
42
43         return (slave == bond->first_slave) ? NULL : slave;
44 }
45
46 static void bond_info_seq_stop(struct seq_file *seq, void *v)
47         __releases(&bond->lock)
48         __releases(RCU)
49 {
50         struct bonding *bond = seq->private;
51
52         read_unlock(&bond->lock);
53         rcu_read_unlock();
54 }
55
56 static void bond_info_show_master(struct seq_file *seq)
57 {
58         struct bonding *bond = seq->private;
59         struct slave *curr;
60         int i;
61
62         read_lock(&bond->curr_slave_lock);
63         curr = bond->curr_active_slave;
64         read_unlock(&bond->curr_slave_lock);
65
66         seq_printf(seq, "Bonding Mode: %s",
67                    bond_mode_name(bond->params.mode));
68
69         if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
70             bond->params.fail_over_mac)
71                 seq_printf(seq, " (fail_over_mac %s)",
72                    fail_over_mac_tbl[bond->params.fail_over_mac].modename);
73
74         seq_printf(seq, "\n");
75
76         if (bond->params.mode == BOND_MODE_XOR ||
77                 bond->params.mode == BOND_MODE_8023AD) {
78                 seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
79                         xmit_hashtype_tbl[bond->params.xmit_policy].modename,
80                         bond->params.xmit_policy);
81         }
82
83         if (USES_PRIMARY(bond->params.mode)) {
84                 seq_printf(seq, "Primary Slave: %s",
85                            (bond->primary_slave) ?
86                            bond->primary_slave->dev->name : "None");
87                 if (bond->primary_slave)
88                         seq_printf(seq, " (primary_reselect %s)",
89                    pri_reselect_tbl[bond->params.primary_reselect].modename);
90
91                 seq_printf(seq, "\nCurrently Active Slave: %s\n",
92                            (curr) ? curr->dev->name : "None");
93         }
94
95         seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
96                    "up" : "down");
97         seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
98         seq_printf(seq, "Up Delay (ms): %d\n",
99                    bond->params.updelay * bond->params.miimon);
100         seq_printf(seq, "Down Delay (ms): %d\n",
101                    bond->params.downdelay * bond->params.miimon);
102
103
104         /* ARP information */
105         if (bond->params.arp_interval > 0) {
106                 int printed = 0;
107                 seq_printf(seq, "ARP Polling Interval (ms): %d\n",
108                                 bond->params.arp_interval);
109
110                 seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
111
112                 for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
113                         if (!bond->params.arp_targets[i])
114                                 break;
115                         if (printed)
116                                 seq_printf(seq, ",");
117                         seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
118                         printed = 1;
119                 }
120                 seq_printf(seq, "\n");
121         }
122
123         if (bond->params.mode == BOND_MODE_8023AD) {
124                 struct ad_info ad_info;
125
126                 seq_puts(seq, "\n802.3ad info\n");
127                 seq_printf(seq, "LACP rate: %s\n",
128                            (bond->params.lacp_fast) ? "fast" : "slow");
129                 seq_printf(seq, "Min links: %d\n", bond->params.min_links);
130                 seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
131                            ad_select_tbl[bond->params.ad_select].modename);
132
133                 if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
134                         seq_printf(seq, "bond %s has no active aggregator\n",
135                                    bond->dev->name);
136                 } else {
137                         seq_printf(seq, "Active Aggregator Info:\n");
138
139                         seq_printf(seq, "\tAggregator ID: %d\n",
140                                    ad_info.aggregator_id);
141                         seq_printf(seq, "\tNumber of ports: %d\n",
142                                    ad_info.ports);
143                         seq_printf(seq, "\tActor Key: %d\n",
144                                    ad_info.actor_key);
145                         seq_printf(seq, "\tPartner Key: %d\n",
146                                    ad_info.partner_key);
147                         seq_printf(seq, "\tPartner Mac Address: %pM\n",
148                                    ad_info.partner_system);
149                 }
150         }
151 }
152
153 static void bond_info_show_slave(struct seq_file *seq,
154                                  const struct slave *slave)
155 {
156         struct bonding *bond = seq->private;
157
158         seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
159         seq_printf(seq, "MII Status: %s\n",
160                    (slave->link == BOND_LINK_UP) ?  "up" : "down");
161         if (slave->speed == SPEED_UNKNOWN)
162                 seq_printf(seq, "Speed: %s\n", "Unknown");
163         else
164                 seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
165
166         if (slave->duplex == DUPLEX_UNKNOWN)
167                 seq_printf(seq, "Duplex: %s\n", "Unknown");
168         else
169                 seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
170
171         seq_printf(seq, "Link Failure Count: %u\n",
172                    slave->link_failure_count);
173
174         seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr);
175
176         if (bond->params.mode == BOND_MODE_8023AD) {
177                 const struct aggregator *agg
178                         = SLAVE_AD_INFO(slave).port.aggregator;
179
180                 if (agg)
181                         seq_printf(seq, "Aggregator ID: %d\n",
182                                    agg->aggregator_identifier);
183                 else
184                         seq_puts(seq, "Aggregator ID: N/A\n");
185         }
186         seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id);
187 }
188
189 static int bond_info_seq_show(struct seq_file *seq, void *v)
190 {
191         if (v == SEQ_START_TOKEN) {
192                 seq_printf(seq, "%s\n", bond_version);
193                 bond_info_show_master(seq);
194         } else
195                 bond_info_show_slave(seq, v);
196
197         return 0;
198 }
199
200 static const struct seq_operations bond_info_seq_ops = {
201         .start = bond_info_seq_start,
202         .next  = bond_info_seq_next,
203         .stop  = bond_info_seq_stop,
204         .show  = bond_info_seq_show,
205 };
206
207 static int bond_info_open(struct inode *inode, struct file *file)
208 {
209         struct seq_file *seq;
210         struct proc_dir_entry *proc;
211         int res;
212
213         res = seq_open(file, &bond_info_seq_ops);
214         if (!res) {
215                 /* recover the pointer buried in proc_dir_entry data */
216                 seq = file->private_data;
217                 proc = PDE(inode);
218                 seq->private = proc->data;
219         }
220
221         return res;
222 }
223
224 static const struct file_operations bond_info_fops = {
225         .owner   = THIS_MODULE,
226         .open    = bond_info_open,
227         .read    = seq_read,
228         .llseek  = seq_lseek,
229         .release = seq_release,
230 };
231
232 void bond_create_proc_entry(struct bonding *bond)
233 {
234         struct net_device *bond_dev = bond->dev;
235         struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
236
237         if (bn->proc_dir) {
238                 bond->proc_entry = proc_create_data(bond_dev->name,
239                                                     S_IRUGO, bn->proc_dir,
240                                                     &bond_info_fops, bond);
241                 if (bond->proc_entry == NULL)
242                         pr_warning("Warning: Cannot create /proc/net/%s/%s\n",
243                                    DRV_NAME, bond_dev->name);
244                 else
245                         memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
246         }
247 }
248
249 void bond_remove_proc_entry(struct bonding *bond)
250 {
251         struct net_device *bond_dev = bond->dev;
252         struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
253
254         if (bn->proc_dir && bond->proc_entry) {
255                 remove_proc_entry(bond->proc_file_name, bn->proc_dir);
256                 memset(bond->proc_file_name, 0, IFNAMSIZ);
257                 bond->proc_entry = NULL;
258         }
259 }
260
261 /* Create the bonding directory under /proc/net, if doesn't exist yet.
262  * Caller must hold rtnl_lock.
263  */
264 void __net_init bond_create_proc_dir(struct bond_net *bn)
265 {
266         if (!bn->proc_dir) {
267                 bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
268                 if (!bn->proc_dir)
269                         pr_warning("Warning: cannot create /proc/net/%s\n",
270                                    DRV_NAME);
271         }
272 }
273
274 /* Destroy the bonding directory under /proc/net, if empty.
275  * Caller must hold rtnl_lock.
276  */
277 void __net_exit bond_destroy_proc_dir(struct bond_net *bn)
278 {
279         if (bn->proc_dir) {
280                 remove_proc_entry(DRV_NAME, bn->net->proc_net);
281                 bn->proc_dir = NULL;
282         }
283 }