20bb109b578fd26c9b20c80c18af43ee841a0ecb
[cascardo/ovs.git] / datapath / brc_sysfs_if.c
1 /*
2  *      Sysfs attributes of bridge ports for Open vSwitch
3  *
4  *  This has been shamelessly copied from the kernel sources.
5  */
6
7 #include <linux/capability.h>
8 #include <linux/kernel.h>
9 #include <linux/netdevice.h>
10 #include <linux/if_bridge.h>
11 #include <linux/rtnetlink.h>
12 #include <linux/spinlock.h>
13 #include "brc_sysfs.h"
14 #include "datapath.h"
15
16 #ifdef SUPPORT_SYSFS
17
18 struct brport_attribute {
19         struct attribute        attr;
20         ssize_t (*show)(struct net_bridge_port *, char *);
21         ssize_t (*store)(struct net_bridge_port *, unsigned long);
22 };
23
24 #define BRPORT_ATTR(_name,_mode,_show,_store)                   \
25 struct brport_attribute brport_attr_##_name = {                 \
26         .attr = {.name = __stringify(_name),                    \
27                  .mode = _mode,                                 \
28                  .owner = THIS_MODULE, },                       \
29         .show   = _show,                                        \
30         .store  = _store,                                       \
31 };
32
33 static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
34 {
35 #if 0
36         return sprintf(buf, "%d\n", p->path_cost);
37 #else
38         return sprintf(buf, "%d\n", 0);
39 #endif
40 }
41 static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v)
42 {
43 #if 0
44         br_stp_set_path_cost(p, v);
45 #endif
46         return 0;
47 }
48 static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
49                    show_path_cost, store_path_cost);
50
51 static ssize_t show_priority(struct net_bridge_port *p, char *buf)
52 {
53 #if 0
54         return sprintf(buf, "%d\n", p->priority);
55 #else
56         return sprintf(buf, "%d\n", 0);
57 #endif
58 }
59 static ssize_t store_priority(struct net_bridge_port *p, unsigned long v)
60 {
61 #if 0
62         if (v >= (1<<(16-BR_PORT_BITS)))
63                 return -ERANGE;
64         br_stp_set_port_priority(p, v);
65 #endif
66         return 0;
67 }
68 static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
69                          show_priority, store_priority);
70
71 static ssize_t show_designated_root(struct net_bridge_port *p, char *buf)
72 {
73 #if 0
74         return br_show_bridge_id(buf, &p->designated_root);
75 #else
76         return sprintf(buf, "0000.010203040506\n");
77 #endif
78 }
79 static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL);
80
81 static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf)
82 {
83 #if 0
84         return br_show_bridge_id(buf, &p->designated_bridge);
85 #else
86         return sprintf(buf, "0000.060504030201\n");
87 #endif
88 }
89 static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL);
90
91 static ssize_t show_designated_port(struct net_bridge_port *p, char *buf)
92 {
93 #if 0
94         return sprintf(buf, "%d\n", p->designated_port);
95 #else
96         return sprintf(buf, "%d\n", 0);
97 #endif
98 }
99 static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL);
100
101 static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf)
102 {
103 #if 0
104         return sprintf(buf, "%d\n", p->designated_cost);
105 #else
106         return sprintf(buf, "%d\n", 0);
107 #endif
108 }
109 static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL);
110
111 static ssize_t show_port_id(struct net_bridge_port *p, char *buf)
112 {
113 #if 0
114         return sprintf(buf, "0x%x\n", p->port_id);
115 #else
116         return sprintf(buf, "0x%x\n", 0);
117 #endif
118 }
119 static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL);
120
121 static ssize_t show_port_no(struct net_bridge_port *p, char *buf)
122 {
123         return sprintf(buf, "0x%x\n", p->port_no);
124 }
125
126 static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL);
127
128 static ssize_t show_change_ack(struct net_bridge_port *p, char *buf)
129 {
130 #if 0
131         return sprintf(buf, "%d\n", p->topology_change_ack);
132 #else
133         return sprintf(buf, "%d\n", 0);
134 #endif
135 }
136 static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL);
137
138 static ssize_t show_config_pending(struct net_bridge_port *p, char *buf)
139 {
140 #if 0
141         return sprintf(buf, "%d\n", p->config_pending);
142 #else
143         return sprintf(buf, "%d\n", 0);
144 #endif
145 }
146 static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL);
147
148 static ssize_t show_port_state(struct net_bridge_port *p, char *buf)
149 {
150 #if 0
151         return sprintf(buf, "%d\n", p->state);
152 #else
153         return sprintf(buf, "%d\n", 0);
154 #endif
155 }
156 static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
157
158 static ssize_t show_message_age_timer(struct net_bridge_port *p,
159                                             char *buf)
160 {
161 #if 0
162         return sprintf(buf, "%ld\n", br_timer_value(&p->message_age_timer));
163 #else
164         return sprintf(buf, "%d\n", 0);
165 #endif
166 }
167 static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL);
168
169 static ssize_t show_forward_delay_timer(struct net_bridge_port *p,
170                                             char *buf)
171 {
172 #if 0
173         return sprintf(buf, "%ld\n", br_timer_value(&p->forward_delay_timer));
174 #else
175         return sprintf(buf, "%d\n", 0);
176 #endif
177 }
178 static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL);
179
180 static ssize_t show_hold_timer(struct net_bridge_port *p,
181                                             char *buf)
182 {
183 #if 0
184         return sprintf(buf, "%ld\n", br_timer_value(&p->hold_timer));
185 #else
186         return sprintf(buf, "%d\n", 0);
187 #endif
188 }
189 static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL);
190
191 static struct brport_attribute *brport_attrs[] = {
192         &brport_attr_path_cost,
193         &brport_attr_priority,
194         &brport_attr_port_id,
195         &brport_attr_port_no,
196         &brport_attr_designated_root,
197         &brport_attr_designated_bridge,
198         &brport_attr_designated_port,
199         &brport_attr_designated_cost,
200         &brport_attr_state,
201         &brport_attr_change_ack,
202         &brport_attr_config_pending,
203         &brport_attr_message_age_timer,
204         &brport_attr_forward_delay_timer,
205         &brport_attr_hold_timer,
206         NULL
207 };
208
209 #define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr)
210 #define to_brport(obj)  container_of(obj, struct net_bridge_port, kobj)
211
212 static ssize_t brport_show(struct kobject * kobj,
213                            struct attribute * attr, char * buf)
214 {
215         struct brport_attribute * brport_attr = to_brport_attr(attr);
216         struct net_bridge_port * p = to_brport(kobj);
217
218         return brport_attr->show(p, buf);
219 }
220
221 static ssize_t brport_store(struct kobject * kobj,
222                             struct attribute * attr,
223                             const char * buf, size_t count)
224 {
225         struct net_bridge_port * p = to_brport(kobj);
226 #if 0
227         struct brport_attribute * brport_attr = to_brport_attr(attr);
228         char *endp;
229         unsigned long val;
230 #endif
231         ssize_t ret = -EINVAL;
232
233         if (!capable(CAP_NET_ADMIN))
234                 return -EPERM;
235
236 #if 0
237         val = simple_strtoul(buf, &endp, 0);
238         if (endp != buf) {
239                 rtnl_lock();
240                 if (p->dev && p->br && brport_attr->store) {
241                         spin_lock_bh(&p->br->lock);
242                         ret = brport_attr->store(p, val);
243                         spin_unlock_bh(&p->br->lock);
244                         if (ret == 0)
245                                 ret = count;
246                 }
247                 rtnl_unlock();
248         }
249 #else
250         printk("%s: xxx writing port parms not supported yet!\n", 
251                dp_name(p->dp));
252 #endif
253         return ret;
254 }
255
256 struct sysfs_ops brport_sysfs_ops = {
257         .show = brport_show,
258         .store = brport_store,
259 };
260
261 static void release_nbp(struct kobject *kobj)
262 {
263         struct net_bridge_port *p
264                 = container_of(kobj, struct net_bridge_port, kobj);
265         kfree(p);
266 }
267
268 struct kobj_type brport_ktype = {
269         .sysfs_ops = &brport_sysfs_ops,
270         .release = release_nbp
271 };
272
273 /*
274  * Add sysfs entries to ethernet device added to a bridge.
275  * Creates a brport subdirectory with bridge attributes.
276  * Puts symlink in bridge's brport subdirectory
277  */
278 int brc_sysfs_add_if(struct net_bridge_port *p)
279 {
280         struct datapath *dp = p->dp;
281         struct brport_attribute **a;
282         int err;
283
284         kobject_init(&p->kobj);
285         kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
286         p->kobj.ktype = &brport_ktype;
287         p->kobj.kset = NULL;
288         p->kobj.parent = &(p->dev->class_dev.kobj);
289
290         err = kobject_add(&p->kobj);
291         if (err)
292                 goto err_put;
293
294         err = sysfs_create_link(&p->kobj,
295                                 &dp->ports[ODPP_LOCAL]->dev->class_dev.kobj,
296                                 SYSFS_BRIDGE_PORT_LINK);
297         if (err)
298                 goto err_del;
299
300         for (a = brport_attrs; *a; ++a) {
301                 err = sysfs_create_file(&p->kobj, &((*a)->attr));
302                 if (err)
303                         goto err_del;
304         }
305
306         err = sysfs_create_link(&dp->ifobj, &p->kobj, p->dev->name);
307         if (err)
308                 goto err_del;
309
310         kobject_uevent(&p->kobj, KOBJ_ADD);
311
312         return err;
313
314 err_del:
315         kobject_del(&p->kobj);
316 err_put:
317         kobject_put(&p->kobj);
318         return err;
319 }
320
321 int brc_sysfs_del_if(struct net_bridge_port *p)
322 {
323         struct net_device *dev = p->dev;
324
325         kobject_uevent(&p->kobj, KOBJ_REMOVE);
326         kobject_del(&p->kobj);
327
328         dev_put(dev);
329
330         kobject_put(&p->kobj);
331
332         return 0;
333 }
334 #endif /* SUPPORT_SYSFS */