summaryrefslogtreecommitdiff
path: root/src/nl-cls-list.c
blob: 5d4faa0f2cdf5fcd34dfc2aa4d155cb80c658018 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* SPDX-License-Identifier: LGPL-2.1-only */
/*
 * src/nl-cls-list.c     	List classifiers
 *
 *	This library is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation version 2.1
 *	of the License.
 *
 * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
 */

#include <netlink/cli/utils.h>
#include <netlink/cli/tc.h>
#include <netlink/cli/cls.h>
#include <netlink/cli/link.h>

#include <linux/netlink.h>

static struct nl_sock *sock;

static struct nl_dump_params params = {
	.dp_type = NL_DUMP_LINE,
};

static void print_usage(void)
{
	printf(
"Usage: nl-cls-list [OPTION]...\n"
"\n"
"OPTIONS\n"
"     --details             Show details\n"
"     --stats               Show statistics\n"
" -h, --help                Show this help\n"
" -v, --version             Show versioning information\n"
"\n"
" -d, --dev=DEV             Device the classifier is attached to. (default: all)\n"
" -p, --parent=ID           Identifier of parent class.\n"
" -i, --id=ID               Identifier.\n"
" -k, --kind=NAME           Kind of classifier (e.g. basic, u32, fw)\n"
"     --proto=PROTO         Protocol to match (default: all)\n"
"     --prio=PRIO           Priority (default: 0)\n"
"\n"
"EXAMPLE\n"
"    # Display statistics of all classes on eth0\n"
"    $ nl-cls-list --stats --dev=eth0\n"
"\n"
	);
	exit(0);
}

static void __dump_link(int ifindex, struct rtnl_cls *filter)
{
	struct nl_cache *cache;
	uint32_t parent = rtnl_tc_get_parent((struct rtnl_tc *) filter);

	cache = nl_cli_cls_alloc_cache(sock, ifindex, parent);
	nl_cache_dump_filter(cache, &params, OBJ_CAST(filter));
	nl_cache_free(cache);
}

static void dump_link(struct nl_object *obj, void *arg)
{
	struct rtnl_link *link = nl_object_priv(obj);

	__dump_link(rtnl_link_get_ifindex(link), arg);
}

int main(int argc, char *argv[])
{
	struct rtnl_cls *cls;
	struct rtnl_tc *tc;
	struct nl_cache *link_cache;
	int ifindex;

	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	cls = nl_cli_cls_alloc();
	tc = (struct rtnl_tc *) cls;

	params.dp_fd = stdout;

	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_DETAILS = 257,
			ARG_STATS = 258,
			ARG_PROTO,
			ARG_PRIO,
		};
		static struct option long_opts[] = {
			{ "details", 0, 0, ARG_DETAILS },
			{ "stats", 0, 0, ARG_STATS },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "dev", 1, 0, 'd' },
			{ "parent", 1, 0, 'p' },
			{ "id", 1, 0, 'i' },
			{ "kind", 1, 0, 'k' },
			{ "proto", 1, 0, ARG_PROTO },
			{ "prio", 1, 0, ARG_PRIO },
			{ 0, 0, 0, 0 }
		};

		c = getopt_long(argc, argv, "hvd:p:i:k:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break;
		case ARG_STATS: params.dp_type = NL_DUMP_STATS; break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
		case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
		case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
		case 'k': nl_cli_tc_parse_kind(tc, optarg); break;
		case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break;
		case ARG_PRIO:
			rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg));
			break;
		}
	}

	if ((ifindex = rtnl_tc_get_ifindex(tc)))
		__dump_link(ifindex, cls);
	else
		nl_cache_foreach(link_cache, dump_link, cls);

	return 0;
}