]>
Commit | Line | Data |
---|---|---|
a14bc59f | 1 | /* |
a9a29d22 | 2 | * Copyright (c) 2007-2011 Nicira Networks. |
a14bc59f | 3 | * |
a9a29d22 JG |
4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of version 2 of the GNU General Public | |
6 | * License as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
064af421 | 12 | * |
a9a29d22 JG |
13 | * You should have received a copy of the GNU General Public License |
14 | * along with this program; if not, write to the Free Software | |
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
16 | * 02110-1301, USA | |
064af421 BP |
17 | */ |
18 | ||
6455100f PS |
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | ||
064af421 BP |
21 | #include <linux/capability.h> |
22 | #include <linux/kernel.h> | |
23 | #include <linux/netdevice.h> | |
24 | #include <linux/if_bridge.h> | |
25 | #include <linux/rtnetlink.h> | |
f2459fe7 | 26 | |
064af421 | 27 | #include "datapath.h" |
f2459fe7 JG |
28 | #include "dp_sysfs.h" |
29 | #include "vport.h" | |
064af421 | 30 | |
806e39cf | 31 | #ifdef CONFIG_SYSFS |
064af421 BP |
32 | |
33 | struct brport_attribute { | |
34 | struct attribute attr; | |
e779d8d9 BP |
35 | ssize_t (*show)(struct vport *, char *); |
36 | ssize_t (*store)(struct vport *, unsigned long); | |
064af421 BP |
37 | }; |
38 | ||
e97f8ca7 | 39 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) |
6455100f | 40 | #define BRPORT_ATTR(_name, _mode, _show, _store) \ |
e97f8ca7 SH |
41 | struct brport_attribute brport_attr_##_name = { \ |
42 | .attr = {.name = __stringify(_name), \ | |
43 | .mode = _mode }, \ | |
44 | .show = _show, \ | |
45 | .store = _store, \ | |
46 | }; | |
47 | #else | |
6455100f PS |
48 | #define BRPORT_ATTR(_name, _mode, _show, _store) \ |
49 | struct brport_attribute brport_attr_##_name = { \ | |
50 | .attr = {.name = __stringify(_name), \ | |
51 | .mode = _mode, \ | |
064af421 BP |
52 | .owner = THIS_MODULE, }, \ |
53 | .show = _show, \ | |
54 | .store = _store, \ | |
55 | }; | |
e97f8ca7 | 56 | #endif |
064af421 | 57 | |
e779d8d9 | 58 | static ssize_t show_path_cost(struct vport *p, char *buf) |
064af421 | 59 | { |
064af421 | 60 | return sprintf(buf, "%d\n", 0); |
064af421 | 61 | } |
e779d8d9 | 62 | static ssize_t store_path_cost(struct vport *p, unsigned long v) |
064af421 | 63 | { |
064af421 BP |
64 | return 0; |
65 | } | |
66 | static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, | |
67 | show_path_cost, store_path_cost); | |
68 | ||
e779d8d9 | 69 | static ssize_t show_priority(struct vport *p, char *buf) |
064af421 | 70 | { |
064af421 | 71 | return sprintf(buf, "%d\n", 0); |
064af421 | 72 | } |
e779d8d9 | 73 | static ssize_t store_priority(struct vport *p, unsigned long v) |
064af421 | 74 | { |
064af421 BP |
75 | return 0; |
76 | } | |
77 | static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, | |
78 | show_priority, store_priority); | |
79 | ||
e779d8d9 | 80 | static ssize_t show_designated_root(struct vport *p, char *buf) |
064af421 | 81 | { |
064af421 | 82 | return sprintf(buf, "0000.010203040506\n"); |
064af421 BP |
83 | } |
84 | static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL); | |
85 | ||
e779d8d9 | 86 | static ssize_t show_designated_bridge(struct vport *p, char *buf) |
064af421 | 87 | { |
064af421 | 88 | return sprintf(buf, "0000.060504030201\n"); |
064af421 BP |
89 | } |
90 | static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL); | |
91 | ||
e779d8d9 | 92 | static ssize_t show_designated_port(struct vport *p, char *buf) |
064af421 | 93 | { |
064af421 | 94 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
95 | } |
96 | static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL); | |
97 | ||
e779d8d9 | 98 | static ssize_t show_designated_cost(struct vport *p, char *buf) |
064af421 | 99 | { |
064af421 | 100 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
101 | } |
102 | static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL); | |
103 | ||
e779d8d9 | 104 | static ssize_t show_port_id(struct vport *p, char *buf) |
064af421 | 105 | { |
064af421 | 106 | return sprintf(buf, "0x%x\n", 0); |
064af421 BP |
107 | } |
108 | static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL); | |
109 | ||
e779d8d9 | 110 | static ssize_t show_port_no(struct vport *p, char *buf) |
064af421 BP |
111 | { |
112 | return sprintf(buf, "0x%x\n", p->port_no); | |
113 | } | |
114 | ||
115 | static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL); | |
116 | ||
e779d8d9 | 117 | static ssize_t show_change_ack(struct vport *p, char *buf) |
064af421 | 118 | { |
064af421 | 119 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
120 | } |
121 | static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL); | |
122 | ||
e779d8d9 | 123 | static ssize_t show_config_pending(struct vport *p, char *buf) |
064af421 | 124 | { |
064af421 | 125 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
126 | } |
127 | static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL); | |
128 | ||
e779d8d9 | 129 | static ssize_t show_port_state(struct vport *p, char *buf) |
064af421 | 130 | { |
064af421 | 131 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
132 | } |
133 | static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL); | |
134 | ||
6455100f | 135 | static ssize_t show_message_age_timer(struct vport *p, char *buf) |
064af421 | 136 | { |
064af421 | 137 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
138 | } |
139 | static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL); | |
140 | ||
6455100f | 141 | static ssize_t show_forward_delay_timer(struct vport *p, char *buf) |
064af421 | 142 | { |
064af421 | 143 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
144 | } |
145 | static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL); | |
146 | ||
6455100f | 147 | static ssize_t show_hold_timer(struct vport *p, char *buf) |
064af421 | 148 | { |
064af421 | 149 | return sprintf(buf, "%d\n", 0); |
064af421 BP |
150 | } |
151 | static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); | |
152 | ||
153 | static struct brport_attribute *brport_attrs[] = { | |
154 | &brport_attr_path_cost, | |
155 | &brport_attr_priority, | |
156 | &brport_attr_port_id, | |
157 | &brport_attr_port_no, | |
158 | &brport_attr_designated_root, | |
159 | &brport_attr_designated_bridge, | |
160 | &brport_attr_designated_port, | |
161 | &brport_attr_designated_cost, | |
162 | &brport_attr_state, | |
163 | &brport_attr_change_ack, | |
164 | &brport_attr_config_pending, | |
165 | &brport_attr_message_age_timer, | |
166 | &brport_attr_forward_delay_timer, | |
167 | &brport_attr_hold_timer, | |
168 | NULL | |
169 | }; | |
170 | ||
e779d8d9 BP |
171 | #define to_vport_attr(_at) container_of(_at, struct brport_attribute, attr) |
172 | #define to_vport(obj) container_of(obj, struct vport, kobj) | |
064af421 | 173 | |
6455100f PS |
174 | static ssize_t brport_show(struct kobject *kobj, |
175 | struct attribute *attr, char *buf) | |
064af421 | 176 | { |
6455100f PS |
177 | struct brport_attribute *brport_attr = to_vport_attr(attr); |
178 | struct vport *p = to_vport(kobj); | |
064af421 BP |
179 | |
180 | return brport_attr->show(p, buf); | |
181 | } | |
182 | ||
6455100f PS |
183 | static ssize_t brport_store(struct kobject *kobj, |
184 | struct attribute *attr, | |
185 | const char *buf, size_t count) | |
064af421 | 186 | { |
6455100f | 187 | struct vport *p = to_vport(kobj); |
064af421 BP |
188 | ssize_t ret = -EINVAL; |
189 | ||
190 | if (!capable(CAP_NET_ADMIN)) | |
191 | return -EPERM; | |
192 | ||
6455100f PS |
193 | pr_warning("%s: xxx writing port parms not supported yet!\n", |
194 | dp_name(p->dp)); | |
b4a7d615 | 195 | |
064af421 BP |
196 | return ret; |
197 | } | |
198 | ||
bb8b3479 | 199 | struct sysfs_ops brport_sysfs_ops = { |
064af421 BP |
200 | .show = brport_show, |
201 | .store = brport_store, | |
202 | }; | |
203 | ||
064af421 BP |
204 | /* |
205 | * Add sysfs entries to ethernet device added to a bridge. | |
206 | * Creates a brport subdirectory with bridge attributes. | |
207 | * Puts symlink in bridge's brport subdirectory | |
208 | */ | |
e779d8d9 | 209 | int dp_sysfs_add_if(struct vport *p) |
064af421 BP |
210 | { |
211 | struct datapath *dp = p->dp; | |
16b82e84 | 212 | struct vport *local_port = rtnl_dereference(dp->ports[OVSP_LOCAL]); |
064af421 BP |
213 | struct brport_attribute **a; |
214 | int err; | |
215 | ||
5e93df1c | 216 | /* Create /sys/class/net/<devname>/brport directory. */ |
16b82e84 | 217 | if (!p->ops->get_kobj) |
f2459fe7 JG |
218 | return -ENOENT; |
219 | ||
16b82e84 JG |
220 | err = kobject_add(&p->kobj, p->ops->get_kobj(p), |
221 | SYSFS_BRIDGE_PORT_ATTR); | |
064af421 | 222 | if (err) |
806e39cf | 223 | goto err; |
064af421 | 224 | |
5e93df1c BP |
225 | /* Create symlink from /sys/class/net/<devname>/brport/bridge to |
226 | * /sys/class/net/<bridgename>. */ | |
16b82e84 | 227 | err = sysfs_create_link(&p->kobj, local_port->ops->get_kobj(local_port), |
ad919711 | 228 | SYSFS_BRIDGE_PORT_LINK); /* "bridge" */ |
064af421 BP |
229 | if (err) |
230 | goto err_del; | |
231 | ||
5e93df1c | 232 | /* Populate /sys/class/net/<devname>/brport directory with files. */ |
064af421 BP |
233 | for (a = brport_attrs; *a; ++a) { |
234 | err = sysfs_create_file(&p->kobj, &((*a)->attr)); | |
235 | if (err) | |
236 | goto err_del; | |
237 | } | |
238 | ||
5e93df1c BP |
239 | /* Create symlink from /sys/class/net/<bridgename>/brif/<devname> to |
240 | * /sys/class/net/<devname>/brport. */ | |
16b82e84 | 241 | err = sysfs_create_link(&dp->ifobj, &p->kobj, p->ops->get_name(p)); |
064af421 BP |
242 | if (err) |
243 | goto err_del; | |
16b82e84 | 244 | strcpy(p->linkname, p->ops->get_name(p)); |
064af421 BP |
245 | |
246 | kobject_uevent(&p->kobj, KOBJ_ADD); | |
247 | ||
8fef8c71 | 248 | return 0; |
064af421 BP |
249 | |
250 | err_del: | |
251 | kobject_del(&p->kobj); | |
806e39cf | 252 | err: |
8fef8c71 | 253 | p->linkname[0] = 0; |
064af421 BP |
254 | return err; |
255 | } | |
256 | ||
e779d8d9 | 257 | int dp_sysfs_del_if(struct vport *p) |
064af421 | 258 | { |
0515ceb3 BP |
259 | if (p->linkname[0]) { |
260 | sysfs_remove_link(&p->dp->ifobj, p->linkname); | |
58c342f6 BP |
261 | kobject_uevent(&p->kobj, KOBJ_REMOVE); |
262 | kobject_del(&p->kobj); | |
8fef8c71 | 263 | p->linkname[0] = '\0'; |
58c342f6 | 264 | } |
064af421 BP |
265 | return 0; |
266 | } | |
806e39cf | 267 | #endif /* CONFIG_SYSFS */ |