Prepare Open vSwitch 1.1.2 release.
[sliver-openvswitch.git] / datapath / dp_sysfs_if.c
1 /*
2  * Copyright (c) 2009, 2010 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
21 #include "datapath.h"
22 #include "dp_sysfs.h"
23 #include "vport.h"
24
25 #ifdef CONFIG_SYSFS
26
27 struct brport_attribute {
28         struct attribute        attr;
29         ssize_t (*show)(struct vport *, char *);
30         ssize_t (*store)(struct vport *, unsigned long);
31 };
32
33 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
34 #define BRPORT_ATTR(_name,_mode,_show,_store)                   \
35 struct brport_attribute brport_attr_##_name = {                 \
36         .attr = {.name = __stringify(_name),                    \
37                  .mode = _mode },                               \
38         .show   = _show,                                        \
39         .store  = _store,                                       \
40 };
41 #else
42 #define BRPORT_ATTR(_name,_mode,_show,_store)                   \
43 struct brport_attribute brport_attr_##_name = {                 \
44         .attr = {.name = __stringify(_name),                    \
45                  .mode = _mode,                                 \
46                  .owner = THIS_MODULE, },                       \
47         .show   = _show,                                        \
48         .store  = _store,                                       \
49 };
50 #endif
51
52 static ssize_t show_path_cost(struct vport *p, char *buf)
53 {
54         return sprintf(buf, "%d\n", 0);
55 }
56 static ssize_t store_path_cost(struct vport *p, unsigned long v)
57 {
58         return 0;
59 }
60 static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
61                    show_path_cost, store_path_cost);
62
63 static ssize_t show_priority(struct vport *p, char *buf)
64 {
65         return sprintf(buf, "%d\n", 0);
66 }
67 static ssize_t store_priority(struct vport *p, unsigned long v)
68 {
69         return 0;
70 }
71 static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
72                          show_priority, store_priority);
73
74 static ssize_t show_designated_root(struct vport *p, char *buf)
75 {
76         return sprintf(buf, "0000.010203040506\n");
77 }
78 static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL);
79
80 static ssize_t show_designated_bridge(struct vport *p, char *buf)
81 {
82         return sprintf(buf, "0000.060504030201\n");
83 }
84 static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL);
85
86 static ssize_t show_designated_port(struct vport *p, char *buf)
87 {
88         return sprintf(buf, "%d\n", 0);
89 }
90 static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL);
91
92 static ssize_t show_designated_cost(struct vport *p, char *buf)
93 {
94         return sprintf(buf, "%d\n", 0);
95 }
96 static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL);
97
98 static ssize_t show_port_id(struct vport *p, char *buf)
99 {
100         return sprintf(buf, "0x%x\n", 0);
101 }
102 static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL);
103
104 static ssize_t show_port_no(struct vport *p, char *buf)
105 {
106         return sprintf(buf, "0x%x\n", p->port_no);
107 }
108
109 static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL);
110
111 static ssize_t show_change_ack(struct vport *p, char *buf)
112 {
113         return sprintf(buf, "%d\n", 0);
114 }
115 static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL);
116
117 static ssize_t show_config_pending(struct vport *p, char *buf)
118 {
119         return sprintf(buf, "%d\n", 0);
120 }
121 static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL);
122
123 static ssize_t show_port_state(struct vport *p, char *buf)
124 {
125         return sprintf(buf, "%d\n", 0);
126 }
127 static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
128
129 static ssize_t show_message_age_timer(struct vport *p,
130                                             char *buf)
131 {
132         return sprintf(buf, "%d\n", 0);
133 }
134 static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL);
135
136 static ssize_t show_forward_delay_timer(struct vport *p,
137                                             char *buf)
138 {
139         return sprintf(buf, "%d\n", 0);
140 }
141 static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL);
142
143 static ssize_t show_hold_timer(struct vport *p,
144                                             char *buf)
145 {
146         return sprintf(buf, "%d\n", 0);
147 }
148 static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL);
149
150 static struct brport_attribute *brport_attrs[] = {
151         &brport_attr_path_cost,
152         &brport_attr_priority,
153         &brport_attr_port_id,
154         &brport_attr_port_no,
155         &brport_attr_designated_root,
156         &brport_attr_designated_bridge,
157         &brport_attr_designated_port,
158         &brport_attr_designated_cost,
159         &brport_attr_state,
160         &brport_attr_change_ack,
161         &brport_attr_config_pending,
162         &brport_attr_message_age_timer,
163         &brport_attr_forward_delay_timer,
164         &brport_attr_hold_timer,
165         NULL
166 };
167
168 #define to_vport_attr(_at) container_of(_at, struct brport_attribute, attr)
169 #define to_vport(obj)   container_of(obj, struct vport, kobj)
170
171 static ssize_t brport_show(struct kobject * kobj,
172                            struct attribute * attr, char * buf)
173 {
174         struct brport_attribute * brport_attr = to_vport_attr(attr);
175         struct vport * p = to_vport(kobj);
176
177         return brport_attr->show(p, buf);
178 }
179
180 static ssize_t brport_store(struct kobject * kobj,
181                             struct attribute * attr,
182                             const char * buf, size_t count)
183 {
184         struct vport * p = to_vport(kobj);
185         ssize_t ret = -EINVAL;
186
187         if (!capable(CAP_NET_ADMIN))
188                 return -EPERM;
189
190         printk("%s: xxx writing port parms not supported yet!\n",
191                dp_name(p->dp));
192
193         return ret;
194 }
195
196 struct sysfs_ops brport_sysfs_ops = {
197         .show = brport_show,
198         .store = brport_store,
199 };
200
201 /*
202  * Add sysfs entries to ethernet device added to a bridge.
203  * Creates a brport subdirectory with bridge attributes.
204  * Puts symlink in bridge's brport subdirectory
205  */
206 int dp_sysfs_add_if(struct vport *p)
207 {
208         struct kobject *kobj = vport_get_kobj(p);
209         struct datapath *dp = p->dp;
210         struct brport_attribute **a;
211         int err;
212
213         /* Create /sys/class/net/<devname>/brport directory. */
214         if (!kobj)
215                 return -ENOENT;
216
217         err = kobject_add(&p->kobj, kobj, SYSFS_BRIDGE_PORT_ATTR);
218         if (err)
219                 goto err;
220
221         /* Create symlink from /sys/class/net/<devname>/brport/bridge to
222          * /sys/class/net/<bridgename>. */
223         err = sysfs_create_link(&p->kobj,
224                 vport_get_kobj(rtnl_dereference(dp->ports[ODPP_LOCAL])),
225                 SYSFS_BRIDGE_PORT_LINK); /* "bridge" */
226         if (err)
227                 goto err_del;
228
229         /* Populate /sys/class/net/<devname>/brport directory with files. */
230         for (a = brport_attrs; *a; ++a) {
231                 err = sysfs_create_file(&p->kobj, &((*a)->attr));
232                 if (err)
233                         goto err_del;
234         }
235
236         /* Create symlink from /sys/class/net/<bridgename>/brif/<devname> to
237          * /sys/class/net/<devname>/brport.  */
238         err = sysfs_create_link(&dp->ifobj, &p->kobj, vport_get_name(p));
239         if (err)
240                 goto err_del;
241         strcpy(p->linkname, vport_get_name(p));
242
243         kobject_uevent(&p->kobj, KOBJ_ADD);
244
245         return 0;
246
247 err_del:
248         kobject_del(&p->kobj);
249 err:
250         p->linkname[0] = 0;
251         return err;
252 }
253
254 int dp_sysfs_del_if(struct vport *p)
255 {
256         if (p->linkname[0]) {
257                 sysfs_remove_link(&p->dp->ifobj, p->linkname);
258                 kobject_uevent(&p->kobj, KOBJ_REMOVE);
259                 kobject_del(&p->kobj);
260                 p->linkname[0] = '\0';
261         }
262         return 0;
263 }
264 #endif /* CONFIG_SYSFS */