summaryrefslogtreecommitdiff
path: root/src/lib/tc.c
blob: ba3de180c4b5cfb60e2d0e4adcd3d16292ed2550 (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
159
/* SPDX-License-Identifier: LGPL-2.1-only */
/*
 * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
 */

#include <netlink/cli/utils.h>
#include <netlink/cli/tc.h>
#include <netlink-private/route/tc-api.h>

/**
 * @ingroup cli
 * @defgroup cli_tc Traffic Control
 * @{
 */
void nl_cli_tc_parse_dev(struct rtnl_tc *tc, struct nl_cache *link_cache, char *name)
{
	struct rtnl_link *link;
	
	link = rtnl_link_get_by_name(link_cache, name);
	if (!link)
		nl_cli_fatal(ENOENT, "Link \"%s\" does not exist.", name);

	rtnl_tc_set_link(tc, link);
	rtnl_link_put(link);
}

void nl_cli_tc_parse_parent(struct rtnl_tc *tc, 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_tc_set_parent(tc, parent);
}

void nl_cli_tc_parse_handle(struct rtnl_tc *tc, char *arg, int create)
{
	uint32_t handle, parent;
	int err;

	parent = rtnl_tc_get_parent(tc);

	if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) {
		if (err == -NLE_OBJ_NOTFOUND && create)
			err = rtnl_classid_generate(arg, &handle, parent);

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

	rtnl_tc_set_handle(tc, handle);
}

void nl_cli_tc_parse_mtu(struct rtnl_tc *tc, char *arg)
{
	rtnl_tc_set_mtu(tc, nl_cli_parse_u32(arg));
}

void nl_cli_tc_parse_mpu(struct rtnl_tc *tc, char *arg)
{
	rtnl_tc_set_mpu(tc, nl_cli_parse_u32(arg));
}

void nl_cli_tc_parse_overhead(struct rtnl_tc *tc, char *arg)
{
	rtnl_tc_set_overhead(tc, nl_cli_parse_u32(arg));
}

void nl_cli_tc_parse_kind(struct rtnl_tc *tc, char *arg)
{
	rtnl_tc_set_kind(tc, arg);
}

void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg)
{
	int type;

	if ((type = nl_str2llproto(arg)) < 0)
		nl_cli_fatal(type, "Unable to parse linktype \"%s\": %s",
			arg, nl_geterror(type));

	rtnl_tc_set_linktype(tc, type);
}

static NL_LIST_HEAD(tc_modules);

static struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
{
	struct nl_cli_tc_module *tm;

	nl_list_for_each_entry(tm, &tc_modules, tm_list)
		if (tm->tm_ops == ops)
			return tm;

	return NULL;
}

struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
{
	struct nl_cli_tc_module *tm;

	if ((tm = __nl_cli_tc_lookup(ops)))
		return tm;

	switch (ops->to_type) {
	case RTNL_TC_TYPE_QDISC:
	case RTNL_TC_TYPE_CLASS:
		nl_cli_load_module("cli/qdisc", ops->to_kind);
		break;

	case RTNL_TC_TYPE_CLS:
		nl_cli_load_module("cli/cls", ops->to_kind);
		break;

	default:
		nl_cli_fatal(EINVAL, "BUG: unhandled TC object type %d",
				ops->to_type);
	}

	if (!(tm = __nl_cli_tc_lookup(ops)))  {
		nl_cli_fatal(EINVAL, "Application bug: The shared library for "
			"the tc object \"%s\" was successfully loaded but it "
			"seems that module did not register itself",
			ops->to_kind);
	}

	return tm;
}

void nl_cli_tc_register(struct nl_cli_tc_module *tm)
{
	struct rtnl_tc_ops *ops;

	if (!(ops = rtnl_tc_lookup_ops(tm->tm_type, tm->tm_name))) {
		nl_cli_fatal(ENOENT, "Unable to register CLI TC module "
		"\"%s\": No matching libnl TC module found.", tm->tm_name);
	}

	if (__nl_cli_tc_lookup(ops)) {
		nl_cli_fatal(EEXIST, "Unable to register CLI TC module "
		"\"%s\": Module already registered.", tm->tm_name);
	}

	tm->tm_ops = ops;

	nl_list_add_tail(&tm->tm_list, &tc_modules);
}

void nl_cli_tc_unregister(struct nl_cli_tc_module *tm)
{
	nl_list_del(&tm->tm_list);
}


/** @} */