debugfs.c 13.2 KB
Newer Older
1
/* Copyright (C) 2010-2013 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 19 20 21
 */

#include "main.h"

#include <linux/debugfs.h>

22
#include "debugfs.h"
23 24 25 26 27 28 29
#include "translation-table.h"
#include "originator.h"
#include "hard-interface.h"
#include "gateway_common.h"
#include "gateway_client.h"
#include "soft-interface.h"
#include "icmp_socket.h"
30
#include "bridge_loop_avoidance.h"
31
#include "distributed-arp-table.h"
32
#include "network-coding.h"
33

34
static struct dentry *batadv_debugfs;
35 36

#ifdef CONFIG_BATMAN_ADV_DEBUG
37
#define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
38

39 40
static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN;

41
static char *batadv_log_char_addr(struct batadv_priv_debug_log *debug_log,
42 43 44 45
				  size_t idx)
{
	return &debug_log->log_buff[idx & BATADV_LOG_BUFF_MASK];
}
46

47 48
static void batadv_emit_log_char(struct batadv_priv_debug_log *debug_log,
				 char c)
49
{
50 51 52 53
	char *char_addr;

	char_addr = batadv_log_char_addr(debug_log, debug_log->log_end);
	*char_addr = c;
54 55
	debug_log->log_end++;

56 57
	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;
58 59
}

60
__printf(2, 3)
61
static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log,
62
			     const char *fmt, ...)
63 64 65 66 67 68 69 70 71 72
{
	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);
73
	vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args);
74 75 76
	va_end(args);

	for (p = debug_log_buf; *p != 0; p++)
77
		batadv_emit_log_char(debug_log, *p);
78 79 80 81 82 83 84 85

	spin_unlock_bh(&debug_log->lock);

	wake_up(&debug_log->queue_wait);

	return 0;
}

86
int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
87 88 89 90 91 92
{
	va_list args;
	char tmp_log_buf[256];

	va_start(args, fmt);
	vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
93 94
	batadv_fdebug_log(bat_priv->debug_log, "[%10u] %s",
			  jiffies_to_msecs(jiffies), tmp_log_buf);
95 96 97 98 99
	va_end(args);

	return 0;
}

100
static int batadv_log_open(struct inode *inode, struct file *file)
101
{
102 103 104
	if (!try_module_get(THIS_MODULE))
		return -EBUSY;

105 106 107 108 109
	nonseekable_open(inode, file);
	file->private_data = inode->i_private;
	return 0;
}

110
static int batadv_log_release(struct inode *inode, struct file *file)
111
{
112
	module_put(THIS_MODULE);
113 114 115
	return 0;
}

116
static int batadv_log_empty(struct batadv_priv_debug_log *debug_log)
117 118 119 120
{
	return !(debug_log->log_start - debug_log->log_end);
}

121 122
static ssize_t batadv_log_read(struct file *file, char __user *buf,
			       size_t count, loff_t *ppos)
123
{
124
	struct batadv_priv *bat_priv = file->private_data;
125
	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
126
	int error, i = 0;
127
	char *char_addr;
128 129
	char c;

130
	if ((file->f_flags & O_NONBLOCK) && batadv_log_empty(debug_log))
131 132
		return -EAGAIN;

133
	if (!buf)
134 135 136 137 138 139 140 141 142
		return -EINVAL;

	if (count == 0)
		return 0;

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

	error = wait_event_interruptible(debug_log->queue_wait,
143
					 (!batadv_log_empty(debug_log)));
144 145 146 147 148 149 150 151

	if (error)
		return error;

	spin_lock_bh(&debug_log->lock);

	while ((!error) && (i < count) &&
	       (debug_log->log_start != debug_log->log_end)) {
152 153 154
		char_addr = batadv_log_char_addr(debug_log,
						 debug_log->log_start);
		c = *char_addr;
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175

		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;
}

176
static unsigned int batadv_log_poll(struct file *file, poll_table *wait)
177
{
178
	struct batadv_priv *bat_priv = file->private_data;
179
	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
180 181 182

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

183
	if (!batadv_log_empty(debug_log))
184 185 186 187 188
		return POLLIN | POLLRDNORM;

	return 0;
}

189 190 191 192 193
static const struct file_operations batadv_log_fops = {
	.open           = batadv_log_open,
	.release        = batadv_log_release,
	.read           = batadv_log_read,
	.poll           = batadv_log_poll,
194 195 196
	.llseek         = no_llseek,
};

197
static int batadv_debug_log_setup(struct batadv_priv *bat_priv)
198 199 200 201 202 203
{
	struct dentry *d;

	if (!bat_priv->debug_dir)
		goto err;

204
	bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC);
205 206 207 208 209 210 211
	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,
212 213
				bat_priv->debug_dir, bat_priv,
				&batadv_log_fops);
214
	if (!d)
215 216 217 218 219
		goto err;

	return 0;

err:
220
	return -ENOMEM;
221 222
}

223
static void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
224 225 226 227 228
{
	kfree(bat_priv->debug_log);
	bat_priv->debug_log = NULL;
}
#else /* CONFIG_BATMAN_ADV_DEBUG */
229
static int batadv_debug_log_setup(struct batadv_priv *bat_priv)
230 231 232 233
{
	return 0;
}

234
static void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
235 236 237 238 239
{
	return;
}
#endif

240
static int batadv_algorithms_open(struct inode *inode, struct file *file)
241
{
242
	return single_open(file, batadv_algo_seq_print_text, NULL);
243 244
}

245
static int batadv_originators_open(struct inode *inode, struct file *file)
246 247
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
248
	return single_open(file, batadv_orig_seq_print_text, net_dev);
249 250
}

251
static int batadv_gateways_open(struct inode *inode, struct file *file)
252 253
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
254
	return single_open(file, batadv_gw_client_seq_print_text, net_dev);
255 256
}

257
static int batadv_transtable_global_open(struct inode *inode, struct file *file)
258 259
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
260
	return single_open(file, batadv_tt_global_seq_print_text, net_dev);
261 262
}

263
#ifdef CONFIG_BATMAN_ADV_BLA
264
static int batadv_bla_claim_table_open(struct inode *inode, struct file *file)
265 266
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
267 268
	return single_open(file, batadv_bla_claim_table_seq_print_text,
			   net_dev);
269
}
270 271 272 273 274 275 276 277 278

static int batadv_bla_backbone_table_open(struct inode *inode,
					  struct file *file)
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
	return single_open(file, batadv_bla_backbone_table_seq_print_text,
			   net_dev);
}

279
#endif
280

281
#ifdef CONFIG_BATMAN_ADV_DAT
282 283 284 285 286 287 288 289 290 291
/**
 * 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;
	return single_open(file, batadv_dat_cache_seq_print_text, net_dev);
}
292
#endif
293

294
static int batadv_transtable_local_open(struct inode *inode, struct file *file)
295 296
{
	struct net_device *net_dev = (struct net_device *)inode->i_private;
297
	return single_open(file, batadv_tt_local_seq_print_text, net_dev);
298 299
}

300
struct batadv_debuginfo {
301 302 303 304
	struct attribute attr;
	const struct file_operations fops;
};

305 306 307 308 309 310 311 312
#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;
	return single_open(file, batadv_nc_nodes_seq_print_text, net_dev);
}
#endif

313
#define BATADV_DEBUGINFO(_name, _mode, _open)		\
314
struct batadv_debuginfo batadv_debuginfo_##_name = {	\
315 316 317 318 319 320 321 322
	.attr = { .name = __stringify(_name),		\
		  .mode = _mode, },			\
	.fops = { .owner = THIS_MODULE,			\
		  .open = _open,			\
		  .read	= seq_read,			\
		  .llseek = seq_lseek,			\
		  .release = single_release,		\
		}					\
323 324
};

325 326 327
/* the following attributes are general and therefore they will be directly
 * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
 */
328
static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
329 330 331 332 333 334 335

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

/* The following attributes are per soft interface */
336 337 338 339
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);
340
#ifdef CONFIG_BATMAN_ADV_BLA
341
static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
342 343
static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
			batadv_bla_backbone_table_open);
344
#endif
345
#ifdef CONFIG_BATMAN_ADV_DAT
346
static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
347
#endif
348 349
static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
			batadv_transtable_local_open);
350 351 352
#ifdef CONFIG_BATMAN_ADV_NC
static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
#endif
353

354
static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
355 356 357
	&batadv_debuginfo_originators,
	&batadv_debuginfo_gateways,
	&batadv_debuginfo_transtable_global,
358
#ifdef CONFIG_BATMAN_ADV_BLA
359
	&batadv_debuginfo_bla_claim_table,
360
	&batadv_debuginfo_bla_backbone_table,
361
#endif
362
#ifdef CONFIG_BATMAN_ADV_DAT
363
	&batadv_debuginfo_dat_cache,
364
#endif
365
	&batadv_debuginfo_transtable_local,
366 367 368
#ifdef CONFIG_BATMAN_ADV_NC
	&batadv_debuginfo_nc_nodes,
#endif
369 370 371
	NULL,
};

372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
#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,			\
	},							\
};

static struct batadv_debuginfo *batadv_hardif_debuginfos[] = {
	NULL,
};

391
void batadv_debugfs_init(void)
392
{
393
	struct batadv_debuginfo **bat_debug;
394 395
	struct dentry *file;

396
	batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
397 398
	if (batadv_debugfs == ERR_PTR(-ENODEV))
		batadv_debugfs = NULL;
399

400
	if (!batadv_debugfs)
401
		goto err;
402

403 404 405 406 407 408 409 410 411 412 413
	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;
		}
	}
414 415

	return;
416 417
err:
	debugfs_remove_recursive(batadv_debugfs);
418
	batadv_debugfs = NULL;
419 420
}

421
void batadv_debugfs_destroy(void)
422
{
423 424
	debugfs_remove_recursive(batadv_debugfs);
	batadv_debugfs = NULL;
425 426
}

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
/**
 * 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:
#ifdef CONFIG_DEBUG_FS
	return -ENOMEM;
#else
	return 0;
#endif /* CONFIG_DEBUG_FS */
}

/**
 * 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;
	}
}

480
int batadv_debugfs_add_meshif(struct net_device *dev)
481
{
482
	struct batadv_priv *bat_priv = netdev_priv(dev);
483
	struct batadv_debuginfo **bat_debug;
484 485
	struct dentry *file;

486
	if (!batadv_debugfs)
487 488
		goto out;

489
	bat_priv->debug_dir = debugfs_create_dir(dev->name, batadv_debugfs);
490 491 492
	if (!bat_priv->debug_dir)
		goto out;

493
	if (batadv_socket_setup(bat_priv) < 0)
494 495
		goto rem_attr;

496
	if (batadv_debug_log_setup(bat_priv) < 0)
497
		goto rem_attr;
498

499
	for (bat_debug = batadv_mesh_debuginfos; *bat_debug; ++bat_debug) {
500
		file = debugfs_create_file(((*bat_debug)->attr).name,
501 502 503
					   S_IFREG | ((*bat_debug)->attr).mode,
					   bat_priv->debug_dir,
					   dev, &(*bat_debug)->fops);
504
		if (!file) {
505 506
			batadv_err(dev, "Can't add debugfs file: %s/%s\n",
				   dev->name, ((*bat_debug)->attr).name);
507 508 509 510
			goto rem_attr;
		}
	}

511 512 513
	if (batadv_nc_init_debugfs(bat_priv) < 0)
		goto rem_attr;

514 515 516 517 518 519 520 521 522 523 524 525
	return 0;
rem_attr:
	debugfs_remove_recursive(bat_priv->debug_dir);
	bat_priv->debug_dir = NULL;
out:
#ifdef CONFIG_DEBUG_FS
	return -ENOMEM;
#else
	return 0;
#endif /* CONFIG_DEBUG_FS */
}

526
void batadv_debugfs_del_meshif(struct net_device *dev)
527
{
528
	struct batadv_priv *bat_priv = netdev_priv(dev);
529

530
	batadv_debug_log_cleanup(bat_priv);
531

532
	if (batadv_debugfs) {
533 534 535 536
		debugfs_remove_recursive(bat_priv->debug_dir);
		bat_priv->debug_dir = NULL;
	}
}