debugfs.c 14.6 KB
Newer Older
1
/* Copyright (C) 2010-2016  B.A.T.M.A.N. contributors:
2 3 4 5 6 7 8 9 10 11 12 13 14
 *
 * Marek Lindner
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 17
 */

18
#include "debugfs.h"
19 20
#include "main.h"

21
#include <linux/compiler.h>
22
#include <linux/debugfs.h>
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/poll.h>
#include <linux/printk.h>
#include <linux/sched.h> /* for linux/wait.h */
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/stat.h>
#include <linux/stddef.h>
#include <linux/stringify.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <stdarg.h>
46

47
#include "bridge_loop_avoidance.h"
48
#include "distributed-arp-table.h"
49 50
#include "gateway_client.h"
#include "icmp_socket.h"
51
#include "network-coding.h"
52 53
#include "originator.h"
#include "translation-table.h"
54

55
static struct dentry *batadv_debugfs;
56 57

#ifdef CONFIG_BATMAN_ADV_DEBUG
58
#define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
59

60 61
static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN;

62
static char *batadv_log_char_addr(struct batadv_priv_debug_log *debug_log,
63 64 65 66
				  size_t idx)
{
	return &debug_log->log_buff[idx & BATADV_LOG_BUFF_MASK];
}
67

68 69
static void batadv_emit_log_char(struct batadv_priv_debug_log *debug_log,
				 char c)
70
{
71 72 73 74
	char *char_addr;

	char_addr = batadv_log_char_addr(debug_log, debug_log->log_end);
	*char_addr = c;
75 76
	debug_log->log_end++;

77 78
	if (debug_log->log_end - debug_log->log_start > batadv_log_buff_len)
		debug_log->log_start = debug_log->log_end - batadv_log_buff_len;
79 80
}

81
__printf(2, 3)
82
static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log,
83
			     const char *fmt, ...)
84 85 86 87 88 89 90 91 92 93
{
	va_list args;
	static char debug_log_buf[256];
	char *p;

	if (!debug_log)
		return 0;

	spin_lock_bh(&debug_log->lock);
	va_start(args, fmt);
94
	vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args);
95 96 97
	va_end(args);

	for (p = debug_log_buf; *p != 0; p++)
98
		batadv_emit_log_char(debug_log, *p);
99 100 101 102 103 104 105 106

	spin_unlock_bh(&debug_log->lock);

	wake_up(&debug_log->queue_wait);

	return 0;
}

107
int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
108 109 110 111 112 113
{
	va_list args;
	char tmp_log_buf[256];

	va_start(args, fmt);
	vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
114 115
	batadv_fdebug_log(bat_priv->debug_log, "[%10u] %s",
			  jiffies_to_msecs(jiffies), tmp_log_buf);
116 117 118 119 120
	va_end(args);

	return 0;
}

121
static int batadv_log_open(struct inode *inode, struct file *file)
122
{
123 124 125
	if (!try_module_get(THIS_MODULE))
		return -EBUSY;

126 127 128 129 130
	nonseekable_open(inode, file);
	file->private_data = inode->i_private;
	return 0;
}

131
static int batadv_log_release(struct inode *inode, struct file *file)
132
{
133
	module_put(THIS_MODULE);
134 135 136
	return 0;
}

137
static int batadv_log_empty(struct batadv_priv_debug_log *debug_log)
138 139 140 141
{
	return !(debug_log->log_start - debug_log->log_end);
}

142 143
static ssize_t batadv_log_read(struct file *file, char __user *buf,
			       size_t count, loff_t *ppos)
144
{
145
	struct batadv_priv *bat_priv = file->private_data;
146
	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
147
	int error, i = 0;
148
	char *char_addr;
149 150
	char c;

151
	if ((file->f_flags & O_NONBLOCK) && batadv_log_empty(debug_log))
152 153
		return -EAGAIN;

154
	if (!buf)
155 156 157 158 159 160 161 162 163
		return -EINVAL;

	if (count == 0)
		return 0;

	if (!access_ok(VERIFY_WRITE, buf, count))
		return -EFAULT;

	error = wait_event_interruptible(debug_log->queue_wait,
164
					 (!batadv_log_empty(debug_log)));
165 166 167 168 169 170 171 172

	if (error)
		return error;

	spin_lock_bh(&debug_log->lock);

	while ((!error) && (i < count) &&
	       (debug_log->log_start != debug_log->log_end)) {
173 174 175
		char_addr = batadv_log_char_addr(debug_log,
						 debug_log->log_start);
		c = *char_addr;
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

		debug_log->log_start++;

		spin_unlock_bh(&debug_log->lock);

		error = __put_user(c, buf);

		spin_lock_bh(&debug_log->lock);

		buf++;
		i++;
	}

	spin_unlock_bh(&debug_log->lock);

	if (!error)
		return i;

	return error;
}

197
static unsigned int batadv_log_poll(struct file *file, poll_table *wait)
198
{
199
	struct batadv_priv *bat_priv = file->private_data;
200
	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
201 202 203

	poll_wait(file, &debug_log->queue_wait, wait);

204
	if (!batadv_log_empty(debug_log))
205 206 207 208 209
		return POLLIN | POLLRDNORM;

	return 0;
}

210 211 212 213 214
static const struct file_operations batadv_log_fops = {
	.open           = batadv_log_open,
	.release        = batadv_log_release,
	.read           = batadv_log_read,
	.poll           = batadv_log_poll,
215 216 217
	.llseek         = no_llseek,
};

218
static int batadv_debug_log_setup(struct batadv_priv *bat_priv)
219 220 221 222 223 224
{
	struct dentry *d;

	if (!bat_priv->debug_dir)
		goto err;

225
	bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC);
226 227 228 229 230 231 232
	if (!bat_priv->debug_log)
		goto err;

	spin_lock_init(&bat_priv->debug_log->lock);
	init_waitqueue_head(&bat_priv->debug_log->queue_wait);

	d = debugfs_create_file("log", S_IFREG | S_IRUSR,
233 234
				bat_priv->debug_dir, bat_priv,
				&batadv_log_fops);
235
	if (!d)
236 237 238 239 240
		goto err;

	return 0;

err:
241
	return -ENOMEM;
242 243
}

244
static void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
245 246 247 248 249
{
	kfree(bat_priv->debug_log);
	bat_priv->debug_log = NULL;
}
#else /* CONFIG_BATMAN_ADV_DEBUG */
250
static int batadv_debug_log_setup(struct batadv_priv *bat_priv)
251 252 253 254
{
	return 0;
}

255
static void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
256 257 258 259
{
}
#endif

260
static int batadv_algorithms_open(struct inode *inode, struct file *file)
261
{
262
	return single_open(file, batadv_algo_seq_print_text, NULL);
263 264
}

265 266 267 268 269 270 271
static int neighbors_open(struct inode *inode, struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;

	return single_open(file, batadv_hardif_neigh_seq_print_text, net_dev);
}

272
static int batadv_originators_open(struct inode *inode, struct file *file)
273 274
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
275

276
	return single_open(file, batadv_orig_seq_print_text, net_dev);
277 278
}

279 280 281 282 283
/**
 * batadv_originators_hardif_open - handles debugfs output for the
 *  originator table of an hard interface
 * @inode: inode pointer to debugfs file
 * @file: pointer to the seq_file
284 285
 *
 * Return: 0 on success or negative error number in case of failure
286 287 288 289 290
 */
static int batadv_originators_hardif_open(struct inode *inode,
					  struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
291

292 293 294
	return single_open(file, batadv_orig_hardif_seq_print_text, net_dev);
}

295
static int batadv_gateways_open(struct inode *inode, struct file *file)
296 297
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
298

299
	return single_open(file, batadv_gw_client_seq_print_text, net_dev);
300 301
}

302
static int batadv_transtable_global_open(struct inode *inode, struct file *file)
303 304
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
305

306
	return single_open(file, batadv_tt_global_seq_print_text, net_dev);
307 308
}

309
#ifdef CONFIG_BATMAN_ADV_BLA
310
static int batadv_bla_claim_table_open(struct inode *inode, struct file *file)
311 312
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
313

314 315
	return single_open(file, batadv_bla_claim_table_seq_print_text,
			   net_dev);
316
}
317 318 319 320 321

static int batadv_bla_backbone_table_open(struct inode *inode,
					  struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
322

323 324 325 326
	return single_open(file, batadv_bla_backbone_table_seq_print_text,
			   net_dev);
}

327
#endif
328

329
#ifdef CONFIG_BATMAN_ADV_DAT
330 331 332 333
/**
 * batadv_dat_cache_open - Prepare file handler for reads from dat_chache
 * @inode: inode which was opened
 * @file: file handle to be initialized
334 335
 *
 * Return: 0 on success or negative error number in case of failure
336 337 338 339
 */
static int batadv_dat_cache_open(struct inode *inode, struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
340

341 342
	return single_open(file, batadv_dat_cache_seq_print_text, net_dev);
}
343
#endif
344

345
static int batadv_transtable_local_open(struct inode *inode, struct file *file)
346 347
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
348

349
	return single_open(file, batadv_tt_local_seq_print_text, net_dev);
350 351
}

352
struct batadv_debuginfo {
353 354 355 356
	struct attribute attr;
	const struct file_operations fops;
};

357 358 359 360
#ifdef CONFIG_BATMAN_ADV_NC
static int batadv_nc_nodes_open(struct inode *inode, struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
361

362 363 364 365
	return single_open(file, batadv_nc_nodes_seq_print_text, net_dev);
}
#endif

366
#define BATADV_DEBUGINFO(_name, _mode, _open)		\
367
struct batadv_debuginfo batadv_debuginfo_##_name = {	\
368 369 370 371 372 373 374 375 376 377 378
	.attr = {					\
		.name = __stringify(_name),		\
		.mode = _mode,				\
	},						\
	.fops = {					\
		.owner = THIS_MODULE,			\
		.open = _open,				\
		.read	= seq_read,			\
		.llseek = seq_lseek,			\
		.release = single_release,		\
	},						\
379
}
380

381 382 383
/* the following attributes are general and therefore they will be directly
 * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
 */
384
static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
385 386 387 388 389 390 391

static struct batadv_debuginfo *batadv_general_debuginfos[] = {
	&batadv_debuginfo_routing_algos,
	NULL,
};

/* The following attributes are per soft interface */
392
static BATADV_DEBUGINFO(neighbors, S_IRUGO, neighbors_open);
393 394 395 396
static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
			batadv_transtable_global_open);
397
#ifdef CONFIG_BATMAN_ADV_BLA
398
static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
399 400
static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
			batadv_bla_backbone_table_open);
401
#endif
402
#ifdef CONFIG_BATMAN_ADV_DAT
403
static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
404
#endif
405 406
static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
			batadv_transtable_local_open);
407 408 409
#ifdef CONFIG_BATMAN_ADV_NC
static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
#endif
410

411
static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
412
	&batadv_debuginfo_neighbors,
413 414 415
	&batadv_debuginfo_originators,
	&batadv_debuginfo_gateways,
	&batadv_debuginfo_transtable_global,
416
#ifdef CONFIG_BATMAN_ADV_BLA
417
	&batadv_debuginfo_bla_claim_table,
418
	&batadv_debuginfo_bla_backbone_table,
419
#endif
420
#ifdef CONFIG_BATMAN_ADV_DAT
421
	&batadv_debuginfo_dat_cache,
422
#endif
423
	&batadv_debuginfo_transtable_local,
424 425 426
#ifdef CONFIG_BATMAN_ADV_NC
	&batadv_debuginfo_nc_nodes,
#endif
427 428 429
	NULL,
};

430 431 432 433 434 435 436 437 438 439 440 441 442
#define BATADV_HARDIF_DEBUGINFO(_name, _mode, _open)		\
struct batadv_debuginfo batadv_hardif_debuginfo_##_name = {	\
	.attr = {						\
		.name = __stringify(_name),			\
		.mode = _mode,					\
	},							\
	.fops = {						\
		.owner = THIS_MODULE,				\
		.open = _open,					\
		.read	= seq_read,				\
		.llseek = seq_lseek,				\
		.release = single_release,			\
	},							\
443
}
444

445 446
static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO,
			       batadv_originators_hardif_open);
447 448

static struct batadv_debuginfo *batadv_hardif_debuginfos[] = {
449
	&batadv_hardif_debuginfo_originators,
450 451 452
	NULL,
};

453
void batadv_debugfs_init(void)
454
{
455
	struct batadv_debuginfo **bat_debug;
456 457
	struct dentry *file;

458
	batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
459 460
	if (batadv_debugfs == ERR_PTR(-ENODEV))
		batadv_debugfs = NULL;
461

462
	if (!batadv_debugfs)
463
		goto err;
464

465 466 467 468 469 470 471 472 473 474 475
	for (bat_debug = batadv_general_debuginfos; *bat_debug; ++bat_debug) {
		file = debugfs_create_file(((*bat_debug)->attr).name,
					   S_IFREG | ((*bat_debug)->attr).mode,
					   batadv_debugfs, NULL,
					   &(*bat_debug)->fops);
		if (!file) {
			pr_err("Can't add general debugfs file: %s\n",
			       ((*bat_debug)->attr).name);
			goto err;
		}
	}
476 477

	return;
478 479
err:
	debugfs_remove_recursive(batadv_debugfs);
480
	batadv_debugfs = NULL;
481 482
}

483
void batadv_debugfs_destroy(void)
484
{
485 486
	debugfs_remove_recursive(batadv_debugfs);
	batadv_debugfs = NULL;
487 488
}

489 490 491 492
/**
 * batadv_debugfs_add_hardif - creates the base directory for a hard interface
 *  in debugfs.
 * @hard_iface: hard interface which should be added.
493 494
 *
 * Return: 0 on success or negative error number in case of failure
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
 */
int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface)
{
	struct batadv_debuginfo **bat_debug;
	struct dentry *file;

	if (!batadv_debugfs)
		goto out;

	hard_iface->debug_dir = debugfs_create_dir(hard_iface->net_dev->name,
						   batadv_debugfs);
	if (!hard_iface->debug_dir)
		goto out;

	for (bat_debug = batadv_hardif_debuginfos; *bat_debug; ++bat_debug) {
		file = debugfs_create_file(((*bat_debug)->attr).name,
					   S_IFREG | ((*bat_debug)->attr).mode,
					   hard_iface->debug_dir,
					   hard_iface->net_dev,
					   &(*bat_debug)->fops);
		if (!file)
			goto rem_attr;
	}

	return 0;
rem_attr:
	debugfs_remove_recursive(hard_iface->debug_dir);
	hard_iface->debug_dir = NULL;
out:
	return -ENOMEM;
}

/**
 * batadv_debugfs_del_hardif - delete the base directory for a hard interface
 *  in debugfs.
 * @hard_iface: hard interface which is deleted.
 */
void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface)
{
	if (batadv_debugfs) {
		debugfs_remove_recursive(hard_iface->debug_dir);
		hard_iface->debug_dir = NULL;
	}
}

540
int batadv_debugfs_add_meshif(struct net_device *dev)
541
{
542
	struct batadv_priv *bat_priv = netdev_priv(dev);
543
	struct batadv_debuginfo **bat_debug;
544 545
	struct dentry *file;

546
	if (!batadv_debugfs)
547 548
		goto out;

549
	bat_priv->debug_dir = debugfs_create_dir(dev->name, batadv_debugfs);
550 551 552
	if (!bat_priv->debug_dir)
		goto out;

553
	if (batadv_socket_setup(bat_priv) < 0)
554 555
		goto rem_attr;

556
	if (batadv_debug_log_setup(bat_priv) < 0)
557
		goto rem_attr;
558

559
	for (bat_debug = batadv_mesh_debuginfos; *bat_debug; ++bat_debug) {
560
		file = debugfs_create_file(((*bat_debug)->attr).name,
561 562 563
					   S_IFREG | ((*bat_debug)->attr).mode,
					   bat_priv->debug_dir,
					   dev, &(*bat_debug)->fops);
564
		if (!file) {
565 566
			batadv_err(dev, "Can't add debugfs file: %s/%s\n",
				   dev->name, ((*bat_debug)->attr).name);
567 568 569 570
			goto rem_attr;
		}
	}

571 572 573
	if (batadv_nc_init_debugfs(bat_priv) < 0)
		goto rem_attr;

574 575 576 577 578 579 580 581
	return 0;
rem_attr:
	debugfs_remove_recursive(bat_priv->debug_dir);
	bat_priv->debug_dir = NULL;
out:
	return -ENOMEM;
}

582
void batadv_debugfs_del_meshif(struct net_device *dev)
583
{
584
	struct batadv_priv *bat_priv = netdev_priv(dev);
585

586
	batadv_debug_log_cleanup(bat_priv);
587

588
	if (batadv_debugfs) {
589 590 591 592
		debugfs_remove_recursive(bat_priv->debug_dir);
		bat_priv->debug_dir = NULL;
	}
}