debugfs.c 14.1 KB
Newer Older
1
/* Copyright (C) 2010-2015 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
static int batadv_originators_open(struct inode *inode, struct file *file)
266 267
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
268

269
	return single_open(file, batadv_orig_seq_print_text, net_dev);
270 271
}

272 273 274 275 276 277 278 279 280 281
/**
 * 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
 */
static int batadv_originators_hardif_open(struct inode *inode,
					  struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
282

283 284 285
	return single_open(file, batadv_orig_hardif_seq_print_text, net_dev);
}

286
static int batadv_gateways_open(struct inode *inode, struct file *file)
287 288
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
289

290
	return single_open(file, batadv_gw_client_seq_print_text, net_dev);
291 292
}

293
static int batadv_transtable_global_open(struct inode *inode, struct file *file)
294 295
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
296

297
	return single_open(file, batadv_tt_global_seq_print_text, net_dev);
298 299
}

300
#ifdef CONFIG_BATMAN_ADV_BLA
301
static int batadv_bla_claim_table_open(struct inode *inode, struct file *file)
302 303
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
304

305 306
	return single_open(file, batadv_bla_claim_table_seq_print_text,
			   net_dev);
307
}
308 309 310 311 312

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

314 315 316 317
	return single_open(file, batadv_bla_backbone_table_seq_print_text,
			   net_dev);
}

318
#endif
319

320
#ifdef CONFIG_BATMAN_ADV_DAT
321 322 323 324 325 326 327 328
/**
 * batadv_dat_cache_open - Prepare file handler for reads from dat_chache
 * @inode: inode which was opened
 * @file: file handle to be initialized
 */
static int batadv_dat_cache_open(struct inode *inode, struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
329

330 331
	return single_open(file, batadv_dat_cache_seq_print_text, net_dev);
}
332
#endif
333

334
static int batadv_transtable_local_open(struct inode *inode, struct file *file)
335 336
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
337

338
	return single_open(file, batadv_tt_local_seq_print_text, net_dev);
339 340
}

341
struct batadv_debuginfo {
342 343 344 345
	struct attribute attr;
	const struct file_operations fops;
};

346 347 348 349
#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;
350

351 352 353 354
	return single_open(file, batadv_nc_nodes_seq_print_text, net_dev);
}
#endif

355
#define BATADV_DEBUGINFO(_name, _mode, _open)		\
356
struct batadv_debuginfo batadv_debuginfo_##_name = {	\
357 358 359 360 361 362 363 364
	.attr = { .name = __stringify(_name),		\
		  .mode = _mode, },			\
	.fops = { .owner = THIS_MODULE,			\
		  .open = _open,			\
		  .read	= seq_read,			\
		  .llseek = seq_lseek,			\
		  .release = single_release,		\
		}					\
365
}
366

367 368 369
/* the following attributes are general and therefore they will be directly
 * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
 */
370
static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
371 372 373 374 375 376 377

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

/* The following attributes are per soft interface */
378 379 380 381
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);
382
#ifdef CONFIG_BATMAN_ADV_BLA
383
static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
384 385
static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
			batadv_bla_backbone_table_open);
386
#endif
387
#ifdef CONFIG_BATMAN_ADV_DAT
388
static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
389
#endif
390 391
static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
			batadv_transtable_local_open);
392 393 394
#ifdef CONFIG_BATMAN_ADV_NC
static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
#endif
395

396
static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
397 398 399
	&batadv_debuginfo_originators,
	&batadv_debuginfo_gateways,
	&batadv_debuginfo_transtable_global,
400
#ifdef CONFIG_BATMAN_ADV_BLA
401
	&batadv_debuginfo_bla_claim_table,
402
	&batadv_debuginfo_bla_backbone_table,
403
#endif
404
#ifdef CONFIG_BATMAN_ADV_DAT
405
	&batadv_debuginfo_dat_cache,
406
#endif
407
	&batadv_debuginfo_transtable_local,
408 409 410
#ifdef CONFIG_BATMAN_ADV_NC
	&batadv_debuginfo_nc_nodes,
#endif
411 412 413
	NULL,
};

414 415 416 417 418 419 420 421 422 423 424 425 426
#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,			\
	},							\
427
}
428

429 430
static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO,
			       batadv_originators_hardif_open);
431 432

static struct batadv_debuginfo *batadv_hardif_debuginfos[] = {
433
	&batadv_hardif_debuginfo_originators,
434 435 436
	NULL,
};

437
void batadv_debugfs_init(void)
438
{
439
	struct batadv_debuginfo **bat_debug;
440 441
	struct dentry *file;

442
	batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
443 444
	if (batadv_debugfs == ERR_PTR(-ENODEV))
		batadv_debugfs = NULL;
445

446
	if (!batadv_debugfs)
447
		goto err;
448

449 450 451 452 453 454 455 456 457 458 459
	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;
		}
	}
460 461

	return;
462 463
err:
	debugfs_remove_recursive(batadv_debugfs);
464
	batadv_debugfs = NULL;
465 466
}

467
void batadv_debugfs_destroy(void)
468
{
469 470
	debugfs_remove_recursive(batadv_debugfs);
	batadv_debugfs = NULL;
471 472
}

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 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
/**
 * batadv_debugfs_add_hardif - creates the base directory for a hard interface
 *  in debugfs.
 * @hard_iface: hard interface which should be added.
 */
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;
	}
}

522
int batadv_debugfs_add_meshif(struct net_device *dev)
523
{
524
	struct batadv_priv *bat_priv = netdev_priv(dev);
525
	struct batadv_debuginfo **bat_debug;
526 527
	struct dentry *file;

528
	if (!batadv_debugfs)
529 530
		goto out;

531
	bat_priv->debug_dir = debugfs_create_dir(dev->name, batadv_debugfs);
532 533 534
	if (!bat_priv->debug_dir)
		goto out;

535
	if (batadv_socket_setup(bat_priv) < 0)
536 537
		goto rem_attr;

538
	if (batadv_debug_log_setup(bat_priv) < 0)
539
		goto rem_attr;
540

541
	for (bat_debug = batadv_mesh_debuginfos; *bat_debug; ++bat_debug) {
542
		file = debugfs_create_file(((*bat_debug)->attr).name,
543 544 545
					   S_IFREG | ((*bat_debug)->attr).mode,
					   bat_priv->debug_dir,
					   dev, &(*bat_debug)->fops);
546
		if (!file) {
547 548
			batadv_err(dev, "Can't add debugfs file: %s/%s\n",
				   dev->name, ((*bat_debug)->attr).name);
549 550 551 552
			goto rem_attr;
		}
	}

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

556 557 558 559 560 561 562 563
	return 0;
rem_attr:
	debugfs_remove_recursive(bat_priv->debug_dir);
	bat_priv->debug_dir = NULL;
out:
	return -ENOMEM;
}

564
void batadv_debugfs_del_meshif(struct net_device *dev)
565
{
566
	struct batadv_priv *bat_priv = netdev_priv(dev);
567

568
	batadv_debug_log_cleanup(bat_priv);
569

570
	if (batadv_debugfs) {
571 572 573 574
		debugfs_remove_recursive(bat_priv->debug_dir);
		bat_priv->debug_dir = NULL;
	}
}