Staging: batman-adv: layer2 unicast packet fragmentation
[firefly-linux-kernel-4.4.55.git] / drivers / staging / batman-adv / bat_sysfs.c
1 /*
2  * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3  *
4  * Marek Lindner
5  *
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.
9  *
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.
14  *
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
18  * 02110-1301, USA
19  *
20  */
21
22 #include "main.h"
23 #include "bat_sysfs.h"
24 #include "translation-table.h"
25 #include "originator.h"
26 #include "hard-interface.h"
27 #include "vis.h"
28
29 #define to_dev(obj)     container_of(obj, struct device, kobj)
30
31 #define BAT_ATTR(_name, _mode, _show, _store)   \
32 struct bat_attribute bat_attr_##_name = {       \
33         .attr = {.name = __stringify(_name),    \
34                  .mode = _mode },               \
35         .show   = _show,                        \
36         .store  = _store,                       \
37 };
38
39 static ssize_t show_aggr_ogms(struct kobject *kobj, struct attribute *attr,
40                              char *buff)
41 {
42         struct device *dev = to_dev(kobj->parent);
43         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
44         int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
45
46         return sprintf(buff, "%s\n",
47                        aggr_status == 0 ? "disabled" : "enabled");
48 }
49
50 static ssize_t store_aggr_ogms(struct kobject *kobj, struct attribute *attr,
51                               char *buff, size_t count)
52 {
53         struct device *dev = to_dev(kobj->parent);
54         struct net_device *net_dev = to_net_dev(dev);
55         struct bat_priv *bat_priv = netdev_priv(net_dev);
56         int aggr_tmp = -1;
57
58         if (((count == 2) && (buff[0] == '1')) ||
59             (strncmp(buff, "enable", 6) == 0))
60                 aggr_tmp = 1;
61
62         if (((count == 2) && (buff[0] == '0')) ||
63             (strncmp(buff, "disable", 7) == 0))
64                 aggr_tmp = 0;
65
66         if (aggr_tmp < 0) {
67                 if (buff[count - 1] == '\n')
68                         buff[count - 1] = '\0';
69
70                 bat_info(net_dev,
71                          "Invalid parameter for 'aggregate OGM' setting"
72                          "received: %s\n", buff);
73                 return -EINVAL;
74         }
75
76         if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
77                 return count;
78
79         bat_info(net_dev, "Changing aggregation from: %s to: %s\n",
80                  atomic_read(&bat_priv->aggregation_enabled) == 1 ?
81                  "enabled" : "disabled", aggr_tmp == 1 ? "enabled" :
82                  "disabled");
83
84         atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
85         return count;
86 }
87
88 static ssize_t show_bond(struct kobject *kobj, struct attribute *attr,
89                              char *buff)
90 {
91         struct device *dev = to_dev(kobj->parent);
92         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
93         int bond_status = atomic_read(&bat_priv->bonding_enabled);
94
95         return sprintf(buff, "%s\n",
96                        bond_status == 0 ? "disabled" : "enabled");
97 }
98
99 static ssize_t store_bond(struct kobject *kobj, struct attribute *attr,
100                           char *buff, size_t count)
101 {
102         struct device *dev = to_dev(kobj->parent);
103         struct net_device *net_dev = to_net_dev(dev);
104         struct bat_priv *bat_priv = netdev_priv(net_dev);
105         int bonding_enabled_tmp = -1;
106
107         if (((count == 2) && (buff[0] == '1')) ||
108             (strncmp(buff, "enable", 6) == 0))
109                 bonding_enabled_tmp = 1;
110
111         if (((count == 2) && (buff[0] == '0')) ||
112             (strncmp(buff, "disable", 7) == 0))
113                 bonding_enabled_tmp = 0;
114
115         if (bonding_enabled_tmp < 0) {
116                 if (buff[count - 1] == '\n')
117                         buff[count - 1] = '\0';
118
119                 bat_err(net_dev,
120                         "Invalid parameter for 'bonding' setting received: "
121                         "%s\n", buff);
122                 return -EINVAL;
123         }
124
125         if (atomic_read(&bat_priv->bonding_enabled) == bonding_enabled_tmp)
126                 return count;
127
128         bat_info(net_dev, "Changing bonding from: %s to: %s\n",
129                  atomic_read(&bat_priv->bonding_enabled) == 1 ?
130                  "enabled" : "disabled",
131                  bonding_enabled_tmp == 1 ? "enabled" : "disabled");
132
133         atomic_set(&bat_priv->bonding_enabled, (unsigned)bonding_enabled_tmp);
134         return count;
135 }
136
137 static ssize_t show_frag(struct kobject *kobj, struct attribute *attr,
138                              char *buff)
139 {
140         struct device *dev = to_dev(kobj->parent);
141         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
142         int frag_status = atomic_read(&bat_priv->frag_enabled);
143
144         return sprintf(buff, "%s\n",
145                        frag_status == 0 ? "disabled" : "enabled");
146 }
147
148 static ssize_t store_frag(struct kobject *kobj, struct attribute *attr,
149                           char *buff, size_t count)
150 {
151         struct device *dev = to_dev(kobj->parent);
152         struct net_device *net_dev = to_net_dev(dev);
153         struct bat_priv *bat_priv = netdev_priv(net_dev);
154         int frag_enabled_tmp = -1;
155
156         if (((count == 2) && (buff[0] == '1')) ||
157             (strncmp(buff, "enable", 6) == 0))
158                 frag_enabled_tmp = 1;
159
160         if (((count == 2) && (buff[0] == '0')) ||
161             (strncmp(buff, "disable", 7) == 0))
162                 frag_enabled_tmp = 0;
163
164         if (frag_enabled_tmp < 0) {
165                 if (buff[count - 1] == '\n')
166                         buff[count - 1] = '\0';
167
168                 bat_err(net_dev,
169                         "Invalid parameter for 'fragmentation' setting on mesh"
170                         "received: %s\n", buff);
171                 return -EINVAL;
172         }
173
174         if (atomic_read(&bat_priv->frag_enabled) == frag_enabled_tmp)
175                 return count;
176
177         bat_info(net_dev, "Changing fragmentation from: %s to: %s\n",
178                  atomic_read(&bat_priv->frag_enabled) == 1 ?
179                  "enabled" : "disabled",
180                  frag_enabled_tmp == 1 ? "enabled" : "disabled");
181
182         atomic_set(&bat_priv->frag_enabled, (unsigned)frag_enabled_tmp);
183
184         update_min_mtu();
185
186         return count;
187 }
188
189 static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
190                              char *buff)
191 {
192         struct device *dev = to_dev(kobj->parent);
193         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
194         int vis_mode = atomic_read(&bat_priv->vis_mode);
195
196         return sprintf(buff, "%s\n",
197                        vis_mode == VIS_TYPE_CLIENT_UPDATE ?
198                                                         "client" : "server");
199 }
200
201 static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
202                               char *buff, size_t count)
203 {
204         struct device *dev = to_dev(kobj->parent);
205         struct net_device *net_dev = to_net_dev(dev);
206         struct bat_priv *bat_priv = netdev_priv(net_dev);
207         unsigned long val;
208         int ret, vis_mode_tmp = -1;
209
210         ret = strict_strtoul(buff, 10, &val);
211
212         if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
213             (strncmp(buff, "client", 6) == 0) ||
214             (strncmp(buff, "off", 3) == 0))
215                 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
216
217         if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
218             (strncmp(buff, "server", 6) == 0))
219                 vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
220
221         if (vis_mode_tmp < 0) {
222                 if (buff[count - 1] == '\n')
223                         buff[count - 1] = '\0';
224
225                 bat_info(net_dev,
226                          "Invalid parameter for 'vis mode' setting received: "
227                          "%s\n", buff);
228                 return -EINVAL;
229         }
230
231         if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
232                 return count;
233
234         bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
235                  atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
236                  "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
237                  "client" : "server");
238
239         atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
240         return count;
241 }
242
243 static ssize_t show_orig_interval(struct kobject *kobj, struct attribute *attr,
244                                  char *buff)
245 {
246         struct device *dev = to_dev(kobj->parent);
247         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
248
249         return sprintf(buff, "%i\n",
250                        atomic_read(&bat_priv->orig_interval));
251 }
252
253 static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr,
254                                   char *buff, size_t count)
255 {
256         struct device *dev = to_dev(kobj->parent);
257         struct net_device *net_dev = to_net_dev(dev);
258         struct bat_priv *bat_priv = netdev_priv(net_dev);
259         unsigned long orig_interval_tmp;
260         int ret;
261
262         ret = strict_strtoul(buff, 10, &orig_interval_tmp);
263         if (ret) {
264                 bat_info(net_dev, "Invalid parameter for 'orig_interval' "
265                          "setting received: %s\n", buff);
266                 return -EINVAL;
267         }
268
269         if (orig_interval_tmp < JITTER * 2) {
270                 bat_info(net_dev, "New originator interval too small: %li "
271                          "(min: %i)\n", orig_interval_tmp, JITTER * 2);
272                 return -EINVAL;
273         }
274
275         if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
276                 return count;
277
278         bat_info(net_dev, "Changing originator interval from: %i to: %li\n",
279                  atomic_read(&bat_priv->orig_interval),
280                  orig_interval_tmp);
281
282         atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
283         return count;
284 }
285
286 #ifdef CONFIG_BATMAN_ADV_DEBUG
287 static ssize_t show_log_level(struct kobject *kobj, struct attribute *attr,
288                              char *buff)
289 {
290         struct device *dev = to_dev(kobj->parent);
291         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
292         int log_level = atomic_read(&bat_priv->log_level);
293
294         return sprintf(buff, "%d\n", log_level);
295 }
296
297 static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
298                               char *buff, size_t count)
299 {
300         struct device *dev = to_dev(kobj->parent);
301         struct net_device *net_dev = to_net_dev(dev);
302         struct bat_priv *bat_priv = netdev_priv(net_dev);
303         unsigned long log_level_tmp;
304         int ret;
305
306         ret = strict_strtoul(buff, 10, &log_level_tmp);
307         if (ret) {
308                 bat_info(net_dev, "Invalid parameter for 'log_level' "
309                          "setting received: %s\n", buff);
310                 return -EINVAL;
311         }
312
313         if (log_level_tmp > 3) {
314                 bat_info(net_dev, "New log level too big: %li "
315                          "(max: %i)\n", log_level_tmp, 3);
316                 return -EINVAL;
317         }
318
319         if (atomic_read(&bat_priv->log_level) == log_level_tmp)
320                 return count;
321
322         bat_info(net_dev, "Changing log level from: %i to: %li\n",
323                  atomic_read(&bat_priv->log_level),
324                  log_level_tmp);
325
326         atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
327         return count;
328 }
329 #endif
330
331 static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR,
332                 show_aggr_ogms, store_aggr_ogms);
333 static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond);
334 static BAT_ATTR(fragmentation, S_IRUGO | S_IWUSR, show_frag, store_frag);
335 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
336 static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
337                 show_orig_interval, store_orig_interval);
338 #ifdef CONFIG_BATMAN_ADV_DEBUG
339 static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level);
340 #endif
341
342 static struct bat_attribute *mesh_attrs[] = {
343         &bat_attr_aggregated_ogms,
344         &bat_attr_bonding,
345         &bat_attr_fragmentation,
346         &bat_attr_vis_mode,
347         &bat_attr_orig_interval,
348 #ifdef CONFIG_BATMAN_ADV_DEBUG
349         &bat_attr_log_level,
350 #endif
351         NULL,
352 };
353
354 int sysfs_add_meshif(struct net_device *dev)
355 {
356         struct kobject *batif_kobject = &dev->dev.kobj;
357         struct bat_priv *bat_priv = netdev_priv(dev);
358         struct bat_attribute **bat_attr;
359         int err;
360
361         /* FIXME: should be done in the general mesh setup
362                   routine as soon as we have it */
363         atomic_set(&bat_priv->aggregation_enabled, 1);
364         atomic_set(&bat_priv->bonding_enabled, 0);
365         atomic_set(&bat_priv->frag_enabled, 1);
366         atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
367         atomic_set(&bat_priv->orig_interval, 1000);
368         atomic_set(&bat_priv->log_level, 0);
369         atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN);
370         atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
371
372         bat_priv->primary_if = NULL;
373         bat_priv->num_ifaces = 0;
374
375         bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
376                                                     batif_kobject);
377         if (!bat_priv->mesh_obj) {
378                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
379                         SYSFS_IF_MESH_SUBDIR);
380                 goto out;
381         }
382
383         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
384                 err = sysfs_create_file(bat_priv->mesh_obj,
385                                         &((*bat_attr)->attr));
386                 if (err) {
387                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
388                                 dev->name, SYSFS_IF_MESH_SUBDIR,
389                                 ((*bat_attr)->attr).name);
390                         goto rem_attr;
391                 }
392         }
393
394         return 0;
395
396 rem_attr:
397         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
398                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
399
400         kobject_put(bat_priv->mesh_obj);
401         bat_priv->mesh_obj = NULL;
402 out:
403         return -ENOMEM;
404 }
405
406 void sysfs_del_meshif(struct net_device *dev)
407 {
408         struct bat_priv *bat_priv = netdev_priv(dev);
409         struct bat_attribute **bat_attr;
410
411         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
412                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
413
414         kobject_put(bat_priv->mesh_obj);
415         bat_priv->mesh_obj = NULL;
416 }
417
418 static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
419                                char *buff)
420 {
421         struct device *dev = to_dev(kobj->parent);
422         struct net_device *net_dev = to_net_dev(dev);
423         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
424
425         if (!batman_if)
426                 return 0;
427
428         return sprintf(buff, "%s\n",
429                        batman_if->if_status == IF_NOT_IN_USE ?
430                                                         "none" : "bat0");
431 }
432
433 static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
434                                 char *buff, size_t count)
435 {
436         struct device *dev = to_dev(kobj->parent);
437         struct net_device *net_dev = to_net_dev(dev);
438         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
439         int status_tmp = -1;
440
441         if (!batman_if)
442                 return count;
443
444         if (strncmp(buff, "none", 4) == 0)
445                 status_tmp = IF_NOT_IN_USE;
446
447         if (strncmp(buff, "bat0", 4) == 0)
448                 status_tmp = IF_I_WANT_YOU;
449
450         if (status_tmp < 0) {
451                 if (buff[count - 1] == '\n')
452                         buff[count - 1] = '\0';
453
454                 pr_err("Invalid parameter for 'mesh_iface' setting received: "
455                        "%s\n", buff);
456                 return -EINVAL;
457         }
458
459         if ((batman_if->if_status == status_tmp) ||
460             ((status_tmp == IF_I_WANT_YOU) &&
461              (batman_if->if_status != IF_NOT_IN_USE)))
462                 return count;
463
464         if (status_tmp == IF_I_WANT_YOU)
465                 status_tmp = hardif_enable_interface(batman_if);
466         else
467                 hardif_disable_interface(batman_if);
468
469         return (status_tmp < 0 ? status_tmp : count);
470 }
471
472 static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
473                                  char *buff)
474 {
475         struct device *dev = to_dev(kobj->parent);
476         struct net_device *net_dev = to_net_dev(dev);
477         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
478
479         if (!batman_if)
480                 return 0;
481
482         switch (batman_if->if_status) {
483         case IF_TO_BE_REMOVED:
484                 return sprintf(buff, "disabling\n");
485         case IF_INACTIVE:
486                 return sprintf(buff, "inactive\n");
487         case IF_ACTIVE:
488                 return sprintf(buff, "active\n");
489         case IF_TO_BE_ACTIVATED:
490                 return sprintf(buff, "enabling\n");
491         case IF_NOT_IN_USE:
492         default:
493                 return sprintf(buff, "not in use\n");
494         }
495 }
496
497 static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
498                 show_mesh_iface, store_mesh_iface);
499 static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
500
501 static struct bat_attribute *batman_attrs[] = {
502         &bat_attr_mesh_iface,
503         &bat_attr_iface_status,
504         NULL,
505 };
506
507 int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
508 {
509         struct kobject *hardif_kobject = &dev->dev.kobj;
510         struct bat_attribute **bat_attr;
511         int err;
512
513         *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
514                                                     hardif_kobject);
515
516         if (!*hardif_obj) {
517                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
518                         SYSFS_IF_BAT_SUBDIR);
519                 goto out;
520         }
521
522         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
523                 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
524                 if (err) {
525                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
526                                 dev->name, SYSFS_IF_BAT_SUBDIR,
527                                 ((*bat_attr)->attr).name);
528                         goto rem_attr;
529                 }
530         }
531
532         return 0;
533
534 rem_attr:
535         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
536                 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
537 out:
538         return -ENOMEM;
539 }
540
541 void sysfs_del_hardif(struct kobject **hardif_obj)
542 {
543         kobject_put(*hardif_obj);
544         *hardif_obj = NULL;
545 }