2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "bat_sysfs.h"
24 #include "translation-table.h"
25 #include "originator.h"
26 #include "hard-interface.h"
29 #define to_dev(obj) container_of(obj, struct device, kobj)
31 #define BAT_ATTR(_name, _mode, _show, _store) \
32 struct bat_attribute bat_attr_##_name = { \
33 .attr = {.name = __stringify(_name), \
39 #define BAT_BIN_ATTR(_name, _mode, _read, _write) \
40 struct bin_attribute bat_attr_##_name = { \
41 .attr = { .name = __stringify(_name), \
47 static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr,
50 struct device *dev = to_dev(kobj->parent);
51 struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
52 int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
54 return sprintf(buff, "status: %s\ncommands: enable, disable, 0, 1\n",
55 aggr_status == 0 ? "disabled" : "enabled");
58 static ssize_t store_aggr_ogm(struct kobject *kobj, struct attribute *attr,
59 char *buff, size_t count)
61 struct device *dev = to_dev(kobj->parent);
62 struct net_device *net_dev = to_net_dev(dev);
63 struct bat_priv *bat_priv = netdev_priv(net_dev);
66 if (((count == 2) && (buff[0] == '1')) ||
67 (strncmp(buff, "enable", 6) == 0))
70 if (((count == 2) && (buff[0] == '0')) ||
71 (strncmp(buff, "disable", 7) == 0))
75 if (buff[count - 1] == '\n')
76 buff[count - 1] = '\0';
78 printk(KERN_INFO "batman-adv:Invalid parameter for 'aggregate OGM' setting on mesh %s received: %s\n",
83 if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
86 printk(KERN_INFO "batman-adv:Changing aggregation from: %s to: %s on mesh: %s\n",
87 atomic_read(&bat_priv->aggregation_enabled) == 1 ?
88 "enabled" : "disabled", aggr_tmp == 1 ? "enabled" : "disabled",
91 atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
95 static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
98 struct device *dev = to_dev(kobj->parent);
99 struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
100 int vis_mode = atomic_read(&bat_priv->vis_mode);
102 return sprintf(buff, "status: %s\ncommands: client, server, %d, %d\n",
103 vis_mode == VIS_TYPE_CLIENT_UPDATE ?
105 VIS_TYPE_SERVER_SYNC, VIS_TYPE_CLIENT_UPDATE);
108 static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
109 char *buff, size_t count)
111 struct device *dev = to_dev(kobj->parent);
112 struct net_device *net_dev = to_net_dev(dev);
113 struct bat_priv *bat_priv = netdev_priv(net_dev);
115 int ret, vis_mode_tmp = -1;
117 ret = strict_strtoul(buff, 10, &val);
119 if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
120 (strncmp(buff, "client", 6) == 0))
121 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
123 if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
124 (strncmp(buff, "server", 6) == 0))
125 vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
127 if (vis_mode_tmp < 0) {
128 if (buff[count - 1] == '\n')
129 buff[count - 1] = '\0';
131 printk(KERN_INFO "batman-adv:Invalid parameter for 'vis mode' setting on mesh %s received: %s\n",
132 net_dev->name, buff);
136 if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
139 printk(KERN_INFO "batman-adv:Changing vis mode from: %s to: %s on mesh: %s\n",
140 atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
141 "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
142 "client" : "server", net_dev->name);
144 atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
148 static ssize_t show_orig_interval(struct kobject *kobj, struct attribute *attr,
151 struct device *dev = to_dev(kobj->parent);
152 struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
154 return sprintf(buff, "status: %i\n",
155 atomic_read(&bat_priv->orig_interval));
158 static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr,
159 char *buff, size_t count)
161 struct device *dev = to_dev(kobj->parent);
162 struct net_device *net_dev = to_net_dev(dev);
163 struct bat_priv *bat_priv = netdev_priv(net_dev);
164 unsigned long orig_interval_tmp;
167 ret = strict_strtoul(buff, 10, &orig_interval_tmp);
169 printk(KERN_INFO "batman-adv:Invalid parameter for 'orig_interval' setting on mesh %s received: %s\n",
170 net_dev->name, buff);
174 if (orig_interval_tmp <= JITTER * 2) {
175 printk(KERN_INFO "batman-adv:New originator interval too small: %li (min: %i)\n",
176 orig_interval_tmp, JITTER * 2);
180 if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
183 printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li on mesh: %s\n",
184 atomic_read(&bat_priv->orig_interval),
185 orig_interval_tmp, net_dev->name);
187 atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
191 static BAT_ATTR(aggregate_ogm, S_IRUGO | S_IWUSR,
192 show_aggr_ogm, store_aggr_ogm);
193 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
194 static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
195 show_orig_interval, store_orig_interval);
197 static struct bat_attribute *mesh_attrs[] = {
198 &bat_attr_aggregate_ogm,
200 &bat_attr_orig_interval,
204 static ssize_t transtable_local_read(struct kobject *kobj,
205 struct bin_attribute *bin_attr,
206 char *buff, loff_t off, size_t count)
208 struct device *dev = to_dev(kobj->parent);
209 struct net_device *net_dev = to_net_dev(dev);
211 return hna_local_fill_buffer_text(net_dev, buff, count, off);
214 static ssize_t transtable_global_read(struct kobject *kobj,
215 struct bin_attribute *bin_attr,
216 char *buff, loff_t off, size_t count)
218 struct device *dev = to_dev(kobj->parent);
219 struct net_device *net_dev = to_net_dev(dev);
221 return hna_global_fill_buffer_text(net_dev, buff, count, off);
224 static ssize_t originators_read(struct kobject *kobj,
225 struct bin_attribute *bin_attr,
226 char *buff, loff_t off, size_t count)
228 struct device *dev = to_dev(kobj->parent);
229 struct net_device *net_dev = to_net_dev(dev);
231 return orig_fill_buffer_text(net_dev, buff, count, off);
234 static ssize_t vis_data_read(struct kobject *kobj,
235 struct bin_attribute *bin_attr,
236 char *buff, loff_t off, size_t count)
238 struct device *dev = to_dev(kobj->parent);
239 struct net_device *net_dev = to_net_dev(dev);
241 return vis_fill_buffer_text(net_dev, buff, count, off);
244 static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL);
245 static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL);
246 static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL);
247 static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL);
249 static struct bin_attribute *mesh_bin_attrs[] = {
250 &bat_attr_transtable_local,
251 &bat_attr_transtable_global,
252 &bat_attr_originators,
257 int sysfs_add_meshif(struct net_device *dev)
259 struct kobject *batif_kobject = &dev->dev.kobj;
260 struct bat_priv *bat_priv = netdev_priv(dev);
261 struct bat_attribute **bat_attr;
262 struct bin_attribute **bin_attr;
265 /* FIXME: should be done in the general mesh setup
266 routine as soon as we have it */
267 atomic_set(&bat_priv->aggregation_enabled, 1);
268 atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
269 atomic_set(&bat_priv->orig_interval, 1000);
270 bat_priv->primary_if = NULL;
271 bat_priv->num_ifaces = 0;
273 bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
275 if (!bat_priv->mesh_obj) {
276 printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
277 dev->name, SYSFS_IF_MESH_SUBDIR);
281 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
282 err = sysfs_create_file(bat_priv->mesh_obj,
283 &((*bat_attr)->attr));
285 printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
286 dev->name, SYSFS_IF_MESH_SUBDIR,
287 ((*bat_attr)->attr).name);
292 for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) {
293 err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr));
295 printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
296 dev->name, SYSFS_IF_MESH_SUBDIR,
297 ((*bin_attr)->attr).name);
305 for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
306 sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
308 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
309 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
311 kobject_put(bat_priv->mesh_obj);
312 bat_priv->mesh_obj = NULL;
317 void sysfs_del_meshif(struct net_device *dev)
319 struct bat_priv *bat_priv = netdev_priv(dev);
320 struct bat_attribute **bat_attr;
321 struct bin_attribute **bin_attr;
323 for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
324 sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
326 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
327 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
329 kobject_put(bat_priv->mesh_obj);
330 bat_priv->mesh_obj = NULL;
333 static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
336 struct device *dev = to_dev(kobj->parent);
337 struct net_device *net_dev = to_net_dev(dev);
338 struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
343 return sprintf(buff, "status: %s\ncommands: none, bat0\n",
344 batman_if->if_status == IF_NOT_IN_USE ?
348 static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
349 char *buff, size_t count)
351 struct device *dev = to_dev(kobj->parent);
352 struct net_device *net_dev = to_net_dev(dev);
353 struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
359 if (strncmp(buff, "none", 4) == 0)
360 status_tmp = IF_NOT_IN_USE;
362 if (strncmp(buff, "bat0", 4) == 0)
363 status_tmp = IF_I_WANT_YOU;
365 if (status_tmp < 0) {
366 if (buff[count - 1] == '\n')
367 buff[count - 1] = '\0';
369 printk(KERN_ERR "batman-adv:Invalid parameter for 'mesh_iface' setting received: %s\n",
374 if ((batman_if->if_status == status_tmp) ||
375 ((status_tmp == IF_I_WANT_YOU) &&
376 (batman_if->if_status != IF_NOT_IN_USE)))
379 if (status_tmp == IF_I_WANT_YOU)
380 status_tmp = hardif_enable_interface(batman_if);
382 hardif_disable_interface(batman_if);
384 return (status_tmp < 0 ? status_tmp : count);
387 static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
390 struct device *dev = to_dev(kobj->parent);
391 struct net_device *net_dev = to_net_dev(dev);
392 struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
397 switch (batman_if->if_status) {
398 case IF_TO_BE_REMOVED:
399 return sprintf(buff, "disabling\n");
401 return sprintf(buff, "inactive\n");
403 return sprintf(buff, "active\n");
404 case IF_TO_BE_ACTIVATED:
405 return sprintf(buff, "enabling\n");
408 return sprintf(buff, "not in use\n");
412 static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
413 show_mesh_iface, store_mesh_iface);
414 static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
416 static struct bat_attribute *batman_attrs[] = {
417 &bat_attr_mesh_iface,
418 &bat_attr_iface_status,
422 int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
424 struct kobject *hardif_kobject = &dev->dev.kobj;
425 struct bat_attribute **bat_attr;
428 *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
432 printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
433 dev->name, SYSFS_IF_BAT_SUBDIR);
437 for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
438 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
440 printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
441 dev->name, SYSFS_IF_BAT_SUBDIR,
442 ((*bat_attr)->attr).name);
450 for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
451 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
456 void sysfs_del_hardif(struct kobject **hardif_obj)
458 kobject_put(*hardif_obj);