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