summaryrefslogtreecommitdiffstats
path: root/src/lib/qdisc.c
blob: 8b16f3f24f93402e8e168ff618852dac078dcbf1 (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * src/lib/qdisc.c     CLI QDisc Helpers
 *
 *	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>
 */

/**
 * @ingroup cli
 * @defgroup cli_qdisc Queueing Disciplines
 * @{
 */

#include <netlink/cli/utils.h>
#include <netlink/cli/qdisc.h>
#include <netlink/route/class.h>
#include <netlink/route/class-modules.h>

struct rtnl_qdisc *nl_cli_qdisc_alloc(void)
{
	struct rtnl_qdisc *qdisc;

	qdisc = rtnl_qdisc_alloc();
	if (!qdisc)
		nl_cli_fatal(ENOMEM, "Unable to allocate qdisc object");

	return qdisc;
}

void nl_cli_qdisc_parse_dev(struct rtnl_qdisc *qdisc, struct nl_cache *link_cache, char *arg)
{
	int ival;

	if (!(ival = rtnl_link_name2i(link_cache, arg)))
		nl_cli_fatal(ENOENT, "Link \"%s\" does not exist", arg);

	rtnl_qdisc_set_ifindex(qdisc, ival);
}

void nl_cli_qdisc_parse_parent(struct rtnl_qdisc *qdisc, char *arg)
{
	uint32_t parent;
	int err;

	if ((err = rtnl_tc_str2handle(arg, &parent)) < 0)
		nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
		      arg, nl_geterror(err));

	rtnl_qdisc_set_parent(qdisc, parent);
}

void nl_cli_qdisc_parse_handle(struct rtnl_qdisc *qdisc, char *arg)
{
	uint32_t handle;
	int err;

	if ((err = rtnl_tc_str2handle(arg, &handle)) < 0)
		nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
		      arg, nl_geterror(err));

	rtnl_qdisc_set_handle(qdisc, handle);
}

void nl_cli_qdisc_parse_kind(struct rtnl_qdisc *qdisc, char *arg)
{
	rtnl_qdisc_set_kind(qdisc, arg);
}

static NL_LIST_HEAD(qdisc_modules);

struct nl_cli_qdisc_module *__nl_cli_qdisc_lookup(struct rtnl_qdisc_ops *ops)
{
	struct nl_cli_qdisc_module *qm;

	nl_list_for_each_entry(qm, &qdisc_modules, qm_list)
		if (qm->qm_ops == ops)
			return qm;

	return NULL;
}

struct nl_cli_qdisc_module *__nl_cli_class_lookup(struct rtnl_class_ops *ops)
{
	struct nl_cli_qdisc_module *qm;

	nl_list_for_each_entry(qm, &qdisc_modules, qm_list)
		if (qm->qm_class_ops == ops)
			return qm;

	return NULL;
}

struct nl_cli_qdisc_module *nl_cli_qdisc_lookup(struct rtnl_qdisc_ops *ops)
{
	struct nl_cli_qdisc_module *qm;

	if ((qm = __nl_cli_qdisc_lookup(ops)))
		return qm;

	nl_cli_load_module("cli/qdisc", ops->qo_kind);

	if (!(qm = __nl_cli_qdisc_lookup(ops)))  {
		nl_cli_fatal(EINVAL, "Application bug: The shared library for "
			"the qdisc \"%s\" was successfully loaded but it "
			"seems that module did not register itself");
	}

	return qm;
}

struct nl_cli_qdisc_module *nl_cli_qdisc_lookup_by_class(struct rtnl_class_ops *ops)
{
	struct nl_cli_qdisc_module *qm;

	if ((qm = __nl_cli_class_lookup(ops)))
		return qm;

	nl_cli_load_module("cli/qdisc", ops->co_kind);

	if (!(qm = __nl_cli_class_lookup(ops)))  {
		nl_cli_fatal(EINVAL, "Application bug: The shared library for "
			"the class \"%s\" was successfully loaded but it "
			"seems that module did not register itself");
	}

	return qm;
}

void nl_cli_qdisc_register(struct nl_cli_qdisc_module *qm)
{
	struct rtnl_qdisc_ops *ops;

	if (!(ops = __rtnl_qdisc_lookup_ops(qm->qm_name))) {
		nl_cli_fatal(ENOENT, "Unable to register CLI qdisc module "
		"\"%s\": No matching libnl qdisc module found.", qm->qm_name);
	}

	if (__nl_cli_qdisc_lookup(ops)) {
		nl_cli_fatal(EEXIST, "Unable to register CLI qdisc module "
		"\"%s\": Module already registered.", qm->qm_name);
	}

	qm->qm_ops = ops;
	qm->qm_class_ops = __rtnl_class_lookup_ops(qm->qm_name);

	nl_list_add_tail(&qm->qm_list, &qdisc_modules);
}

void nl_cli_qdisc_unregister(struct nl_cli_qdisc_module *qm)
{
	nl_list_del(&qm->qm_list);
}

/** @} */