Import from old repository commit 61ef2b42a9c4ba8e1600f15bb0236765edc2ad45.
[sliver-openvswitch.git] / datapath / brc_sysfs_dp.c
1 #include <linux/version.h>
2
3 /*
4  *      Sysfs attributes of bridge for Open vSwitch
5  *
6  *  This has been shamelessly copied from the kernel sources.
7  */
8
9 #include <linux/capability.h>
10 #include <linux/device.h>
11 #include <linux/kernel.h>
12 #include <linux/netdevice.h>
13 #include <linux/if_bridge.h>
14 #include <linux/rtnetlink.h>
15 #include <linux/spinlock.h>
16 #include <linux/times.h>
17 #include <linux/version.h>
18
19 #include "brc_sysfs.h"
20 #include "datapath.h"
21 #include "dp_dev.h"
22
23 #ifdef SUPPORT_SYSFS
24 #define to_dev(obj)     container_of(obj, struct device, kobj)
25
26 /* Hack to attempt to build on more platforms. */
27 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
28 #define to_kobj(d) &(d)->class_dev.kobj
29 #define BRC_DEVICE_ATTR CLASS_DEVICE_ATTR
30 #else
31 #define to_kobj(d) &(d)->dev.kobj
32 #define BRC_DEVICE_ATTR DEVICE_ATTR
33 #endif
34
35 /*
36  * Common code for storing bridge parameters.
37  */
38 static ssize_t store_bridge_parm(struct class_device *d,
39                                  const char *buf, size_t len,
40                                  void (*set)(struct datapath *, unsigned long))
41 {
42         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
43         char *endp;
44         unsigned long val;
45
46         if (!capable(CAP_NET_ADMIN))
47                 return -EPERM;
48
49         val = simple_strtoul(buf, &endp, 0);
50         if (endp == buf)
51                 return -EINVAL;
52
53 #if 0
54         spin_lock_bh(&br->lock);
55         (*set)(br, val);
56         spin_unlock_bh(&br->lock);
57 #else
58         /* xxx We use a default value of 0 for all fields.  If the caller is
59          * xxx attempting to set the value to our default, just silently
60          * xxx ignore the request. 
61          */
62         if (val != 0) {
63                 printk("%s: xxx writing dp parms not supported yet!\n", 
64                        dp_name(dp));
65         }
66 #endif
67         return len;
68 }
69
70
71 static ssize_t show_forward_delay(struct class_device *d,
72                                   char *buf)
73 {
74 #if 0
75         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
76         return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
77 #else
78         return sprintf(buf, "%d\n", 0);
79 #endif
80 }
81
82 static void set_forward_delay(struct datapath *dp, unsigned long val)
83 {
84 #if 0
85         unsigned long delay = clock_t_to_jiffies(val);
86         br->forward_delay = delay;
87         if (br_is_root_bridge(br))
88                 br->bridge_forward_delay = delay;
89 #else
90         printk("%s: xxx attempt to set_forward_delay()\n", dp_name(dp));
91 #endif
92 }
93
94 static ssize_t store_forward_delay(struct class_device *d,
95                                    const char *buf, size_t len)
96 {
97         return store_bridge_parm(d, buf, len, set_forward_delay);
98 }
99 static BRC_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
100                    show_forward_delay, store_forward_delay);
101
102 static ssize_t show_hello_time(struct class_device *d, char *buf)
103 {
104 #if 0
105         return sprintf(buf, "%lu\n",
106                        jiffies_to_clock_t(to_bridge(d)->hello_time));
107 #else
108         return sprintf(buf, "%d\n", 0);
109 #endif
110 }
111
112 static void set_hello_time(struct datapath *dp, unsigned long val)
113 {
114 #if 0
115         unsigned long t = clock_t_to_jiffies(val);
116         br->hello_time = t;
117         if (br_is_root_bridge(br))
118                 br->bridge_hello_time = t;
119 #else
120         printk("%s: xxx attempt to set_hello_time()\n", dp_name(dp));
121 #endif
122 }
123
124 static ssize_t store_hello_time(struct class_device *d,
125                                 const char *buf,
126                                 size_t len)
127 {
128         return store_bridge_parm(d, buf, len, set_hello_time);
129 }
130 static BRC_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
131                    store_hello_time);
132
133 static ssize_t show_max_age(struct class_device *d, 
134                             char *buf)
135 {
136 #if 0
137         return sprintf(buf, "%lu\n",
138                        jiffies_to_clock_t(to_bridge(d)->max_age));
139 #else
140         return sprintf(buf, "%d\n", 0);
141 #endif
142 }
143
144 static void set_max_age(struct datapath *dp, unsigned long val)
145 {
146 #if 0
147         unsigned long t = clock_t_to_jiffies(val);
148         br->max_age = t;
149         if (br_is_root_bridge(br))
150                 br->bridge_max_age = t;
151 #else
152         printk("%s: xxx attempt to set_max_age()\n", dp_name(dp));
153 #endif
154 }
155
156 static ssize_t store_max_age(struct class_device *d, 
157                              const char *buf, size_t len)
158 {
159         return store_bridge_parm(d, buf, len, set_max_age);
160 }
161 static BRC_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
162
163 static ssize_t show_ageing_time(struct class_device *d,
164                                 char *buf)
165 {
166 #if 0
167         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
168         return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
169 #else
170         return sprintf(buf, "%d\n", 0);
171 #endif
172 }
173
174 static void set_ageing_time(struct datapath *dp, unsigned long val)
175 {
176 #if 0
177         br->ageing_time = clock_t_to_jiffies(val);
178 #else
179         printk("%s: xxx attempt to set_ageing_time()\n", dp_name(dp));
180 #endif
181 }
182
183 static ssize_t store_ageing_time(struct class_device *d,
184                                  const char *buf, size_t len)
185 {
186         return store_bridge_parm(d, buf, len, set_ageing_time);
187 }
188 static BRC_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
189                    store_ageing_time);
190
191 static ssize_t show_stp_state(struct class_device *d,
192                               char *buf)
193 {
194 #if 0
195         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
196         return sprintf(buf, "%d\n", br->stp_enabled);
197 #else
198         return sprintf(buf, "%d\n", 0);
199 #endif
200 }
201
202
203 static ssize_t store_stp_state(struct class_device *d,
204                                const char *buf,
205                                size_t len)
206 {
207         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
208 #if 0
209         char *endp;
210         unsigned long val;
211
212         if (!capable(CAP_NET_ADMIN))
213                 return -EPERM;
214
215         val = simple_strtoul(buf, &endp, 0);
216         if (endp == buf)
217                 return -EINVAL;
218
219         rtnl_lock();
220         br_stp_set_enabled(br, val);
221         rtnl_unlock();
222 #else
223         printk("%s: xxx attempt to set_stp_state()\n", dp_name(dp));
224 #endif
225
226         return len;
227 }
228 static BRC_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
229                    store_stp_state);
230
231 static ssize_t show_priority(struct class_device *d, 
232                              char *buf)
233 {
234 #if 0
235         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
236         return sprintf(buf, "%d\n",
237                        (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
238 #else
239         return sprintf(buf, "%d\n", 0);
240 #endif
241 }
242
243 static void set_priority(struct datapath *dp, unsigned long val)
244 {
245 #if 0
246         br_stp_set_bridge_priority(br, (u16) val);
247 #else
248         printk("%s: xxx attempt to set_priority()\n", dp_name(dp));
249 #endif
250 }
251
252 static ssize_t store_priority(struct class_device *d, 
253                                const char *buf, size_t len)
254 {
255         return store_bridge_parm(d, buf, len, set_priority);
256 }
257 static BRC_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
258
259 static ssize_t show_root_id(struct class_device *d, 
260                             char *buf)
261 {
262 #if 0
263         return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
264 #else
265         return sprintf(buf, "0000.010203040506\n");
266 #endif
267 }
268 static BRC_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
269
270 static ssize_t show_bridge_id(struct class_device *d, 
271                               char *buf)
272 {
273         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
274         const unsigned char *addr = dp->ports[ODPP_LOCAL]->dev->dev_addr;
275
276         /* xxx Do we need a lock of some sort? */
277         return sprintf(buf, "%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x\n",
278                         0, 0, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
279 }
280 static BRC_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
281
282 static ssize_t show_root_port(struct class_device *d, 
283                               char *buf)
284 {
285 #if 0
286         return sprintf(buf, "%d\n", to_bridge(d)->root_port);
287 #else
288         return sprintf(buf, "%d\n", 0);
289 #endif
290 }
291 static BRC_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
292
293 static ssize_t show_root_path_cost(struct class_device *d,
294                                    char *buf)
295 {
296 #if 0
297         return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
298 #else
299         return sprintf(buf, "%d\n", 0);
300 #endif
301 }
302 static BRC_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
303
304 static ssize_t show_topology_change(struct class_device *d,
305                                     char *buf)
306 {
307 #if 0
308         return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
309 #else
310         return sprintf(buf, "%d\n", 0);
311 #endif
312 }
313 static BRC_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
314
315 static ssize_t show_topology_change_detected(struct class_device *d,
316                                              char *buf)
317 {
318 #if 0
319         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
320         return sprintf(buf, "%d\n", br->topology_change_detected);
321 #else
322         return sprintf(buf, "%d\n", 0);
323 #endif
324 }
325 static BRC_DEVICE_ATTR(topology_change_detected, S_IRUGO,
326                    show_topology_change_detected, NULL);
327
328 static ssize_t show_hello_timer(struct class_device *d,
329                                 char *buf)
330 {
331 #if 0
332         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
333         return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer));
334 #else
335         return sprintf(buf, "%d\n", 0);
336 #endif
337 }
338 static BRC_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
339
340 static ssize_t show_tcn_timer(struct class_device *d, 
341                               char *buf)
342 {
343 #if 0
344         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
345         return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer));
346 #else
347         return sprintf(buf, "%d\n", 0);
348 #endif
349 }
350 static BRC_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
351
352 static ssize_t show_topology_change_timer(struct class_device *d,
353                                           char *buf)
354 {
355 #if 0
356         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
357         return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer));
358 #else
359         return sprintf(buf, "%d\n", 0);
360 #endif
361 }
362 static BRC_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
363                    NULL);
364
365 static ssize_t show_gc_timer(struct class_device *d, 
366                              char *buf)
367 {
368 #if 0
369         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
370         return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer));
371 #else
372         return sprintf(buf, "%d\n", 0);
373 #endif
374 }
375 static BRC_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
376
377 static ssize_t show_group_addr(struct class_device *d,
378                                char *buf)
379 {
380 #if 0
381         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
382         return sprintf(buf, "%x:%x:%x:%x:%x:%x\n",
383                        br->group_addr[0], br->group_addr[1],
384                        br->group_addr[2], br->group_addr[3],
385                        br->group_addr[4], br->group_addr[5]);
386 #else
387         return sprintf(buf, "00:01:02:03:04:05\n");
388 #endif
389 }
390
391 static ssize_t store_group_addr(struct class_device *d,
392                                 const char *buf, size_t len)
393 {
394         struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
395 #if 0
396         unsigned new_addr[6];
397         int i;
398
399         if (!capable(CAP_NET_ADMIN))
400                 return -EPERM;
401
402         if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
403                    &new_addr[0], &new_addr[1], &new_addr[2],
404                    &new_addr[3], &new_addr[4], &new_addr[5]) != 6)
405                 return -EINVAL;
406
407         /* Must be 01:80:c2:00:00:0X */
408         for (i = 0; i < 5; i++)
409                 if (new_addr[i] != br_group_address[i])
410                         return -EINVAL;
411
412         if (new_addr[5] & ~0xf)
413                 return -EINVAL;
414
415         if (new_addr[5] == 1    /* 802.3x Pause address */
416             || new_addr[5] == 2 /* 802.3ad Slow protocols */
417             || new_addr[5] == 3) /* 802.1X PAE address */
418                 return -EINVAL;
419
420         spin_lock_bh(&br->lock);
421         for (i = 0; i < 6; i++)
422                 br->group_addr[i] = new_addr[i];
423         spin_unlock_bh(&br->lock);
424 #else
425         printk("%s: xxx attempt to store_group_addr()\n", dp_name(dp));
426 #endif
427         return len;
428 }
429
430 static BRC_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
431                    show_group_addr, store_group_addr);
432
433 static struct attribute *bridge_attrs[] = {
434         &class_device_attr_forward_delay.attr,
435         &class_device_attr_hello_time.attr,
436         &class_device_attr_max_age.attr,
437         &class_device_attr_ageing_time.attr,
438         &class_device_attr_stp_state.attr,
439         &class_device_attr_priority.attr,
440         &class_device_attr_bridge_id.attr,
441         &class_device_attr_root_id.attr,
442         &class_device_attr_root_path_cost.attr,
443         &class_device_attr_root_port.attr,
444         &class_device_attr_topology_change.attr,
445         &class_device_attr_topology_change_detected.attr,
446         &class_device_attr_hello_timer.attr,
447         &class_device_attr_tcn_timer.attr,
448         &class_device_attr_topology_change_timer.attr,
449         &class_device_attr_gc_timer.attr,
450         &class_device_attr_group_addr.attr,
451         NULL
452 };
453
454 static struct attribute_group bridge_group = {
455         .name = SYSFS_BRIDGE_ATTR,
456         .attrs = bridge_attrs,
457 };
458
459 /*
460  * Add entries in sysfs onto the existing network class device
461  * for the bridge.
462  *   Adds a attribute group "bridge" containing tuning parameters.
463  *   Sub directory to hold links to interfaces.
464  *
465  * Note: the ifobj exists only to be a subdirectory
466  *   to hold links.  The ifobj exists in the same data structure
467  *   as its parent the bridge so reference counting works.
468  */
469 int brc_sysfs_add_dp(struct datapath *dp)
470 {
471         struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
472         int err;
473
474         err = sysfs_create_group(kobj, &bridge_group);
475         if (err) {
476                 pr_info("%s: can't create group %s/%s\n",
477                         __func__, dp_name(dp), bridge_group.name);
478                 goto out1;
479         }
480
481 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
482         kobject_set_name(&dp->ifobj, SYSFS_BRIDGE_PORT_SUBDIR);
483         dp->ifobj.ktype = NULL;
484         dp->ifobj.kset = NULL;
485         dp->ifobj.parent = kobj;
486
487         err = kobject_register(&dp->ifobj);
488         if (err) {
489                 pr_info("%s: can't add kobject (directory) %s/%s\n",
490                                 __FUNCTION__, dp_name(dp), dp->ifobj.name);
491                 goto out2;
492         }
493 #else
494         br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, kobj);
495         if (!br->ifobj) {
496                 pr_info("%s: can't add kobject (directory) %s/%s\n",
497                         __func__, dp_name(dp), SYSFS_BRIDGE_PORT_SUBDIR);
498                 goto out2;
499         }
500 #endif
501         return 0;
502
503  out2:
504         sysfs_remove_group(kobj, &bridge_group);
505  out1:
506         return err;
507 }
508
509 int brc_sysfs_del_dp(struct datapath *dp)
510 {
511         struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
512
513 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
514         kobject_unregister(&dp->ifobj);
515 #else 
516         kobject_put(dp->ifobj);
517 #endif
518         sysfs_remove_group(kobj, &bridge_group);
519
520         return 0;
521 }
522 #else /* !SUPPORT_SYSFS */
523 int brc_sysfs_add_dp(struct datapath *dp) { return 0; }
524 int brc_sysfs_del_dp(struct datapath *dp) { return 0; }
525 int brc_sysfs_add_if(struct net_bridge_port *p) { return 0; }
526 int brc_sysfs_del_if(struct net_bridge_port *p)
527 {
528         dev_put(p->dev);
529         kfree(p);
530         return 0;
531 }
532 #endif /* !SUPPORT_SYSFS */