1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2010 Thomas Graf <[email protected]>
4 */
5
6 #include "nl-default.h"
7
8 #include <netlink/cli/utils.h>
9 #include <netlink/cli/tc.h>
10
11 #include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
12
13 /**
14 * @ingroup cli
15 * @defgroup cli_tc Traffic Control
16 * @{
17 */
nl_cli_tc_parse_dev(struct rtnl_tc * tc,struct nl_cache * link_cache,char * name)18 void nl_cli_tc_parse_dev(struct rtnl_tc *tc, struct nl_cache *link_cache, char *name)
19 {
20 struct rtnl_link *link;
21
22 link = rtnl_link_get_by_name(link_cache, name);
23 if (!link)
24 nl_cli_fatal(ENOENT, "Link \"%s\" does not exist.", name);
25
26 rtnl_tc_set_link(tc, link);
27 rtnl_link_put(link);
28 }
29
nl_cli_tc_parse_parent(struct rtnl_tc * tc,char * arg)30 void nl_cli_tc_parse_parent(struct rtnl_tc *tc, char *arg)
31 {
32 uint32_t parent;
33 int err;
34
35 if ((err = rtnl_tc_str2handle(arg, &parent)) < 0)
36 nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
37 arg, nl_geterror(err));
38
39 rtnl_tc_set_parent(tc, parent);
40 }
41
nl_cli_tc_parse_handle(struct rtnl_tc * tc,char * arg,int create)42 void nl_cli_tc_parse_handle(struct rtnl_tc *tc, char *arg, int create)
43 {
44 uint32_t handle, parent;
45 int err;
46
47 parent = rtnl_tc_get_parent(tc);
48
49 if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) {
50 if (err == -NLE_OBJ_NOTFOUND && create)
51 err = rtnl_classid_generate(arg, &handle, parent);
52
53 if (err < 0)
54 nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
55 arg, nl_geterror(err));
56 }
57
58 rtnl_tc_set_handle(tc, handle);
59 }
60
nl_cli_tc_parse_mtu(struct rtnl_tc * tc,char * arg)61 void nl_cli_tc_parse_mtu(struct rtnl_tc *tc, char *arg)
62 {
63 rtnl_tc_set_mtu(tc, nl_cli_parse_u32(arg));
64 }
65
nl_cli_tc_parse_mpu(struct rtnl_tc * tc,char * arg)66 void nl_cli_tc_parse_mpu(struct rtnl_tc *tc, char *arg)
67 {
68 rtnl_tc_set_mpu(tc, nl_cli_parse_u32(arg));
69 }
70
nl_cli_tc_parse_overhead(struct rtnl_tc * tc,char * arg)71 void nl_cli_tc_parse_overhead(struct rtnl_tc *tc, char *arg)
72 {
73 rtnl_tc_set_overhead(tc, nl_cli_parse_u32(arg));
74 }
75
nl_cli_tc_parse_kind(struct rtnl_tc * tc,char * arg)76 void nl_cli_tc_parse_kind(struct rtnl_tc *tc, char *arg)
77 {
78 rtnl_tc_set_kind(tc, arg);
79 }
80
nl_cli_tc_parse_linktype(struct rtnl_tc * tc,char * arg)81 void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg)
82 {
83 int type;
84
85 if ((type = nl_str2llproto(arg)) < 0)
86 nl_cli_fatal(type, "Unable to parse linktype \"%s\": %s",
87 arg, nl_geterror(type));
88
89 rtnl_tc_set_linktype(tc, type);
90 }
91
92 static NL_LIST_HEAD(tc_modules);
93
__nl_cli_tc_lookup(struct rtnl_tc_ops * ops)94 static struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
95 {
96 struct nl_cli_tc_module *tm;
97
98 nl_list_for_each_entry(tm, &tc_modules, tm_list)
99 if (tm->tm_ops == ops)
100 return tm;
101
102 return NULL;
103 }
104
nl_cli_tc_lookup(struct rtnl_tc_ops * ops)105 struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
106 {
107 struct nl_cli_tc_module *tm;
108
109 if ((tm = __nl_cli_tc_lookup(ops)))
110 return tm;
111
112 switch (ops->to_type) {
113 case RTNL_TC_TYPE_QDISC:
114 case RTNL_TC_TYPE_CLASS:
115 nl_cli_load_module("cli/qdisc", ops->to_kind);
116 break;
117
118 case RTNL_TC_TYPE_CLS:
119 nl_cli_load_module("cli/cls", ops->to_kind);
120 break;
121
122 default:
123 nl_cli_fatal(EINVAL, "BUG: unhandled TC object type %d",
124 ops->to_type);
125 }
126
127 if (!(tm = __nl_cli_tc_lookup(ops))) {
128 nl_cli_fatal(EINVAL, "Application bug: The shared library for "
129 "the tc object \"%s\" was successfully loaded but it "
130 "seems that module did not register itself",
131 ops->to_kind);
132 }
133
134 return tm;
135 }
136
nl_cli_tc_register(struct nl_cli_tc_module * tm)137 void nl_cli_tc_register(struct nl_cli_tc_module *tm)
138 {
139 struct rtnl_tc_ops *ops;
140
141 if (!(ops = rtnl_tc_lookup_ops(tm->tm_type, tm->tm_name))) {
142 nl_cli_fatal(ENOENT, "Unable to register CLI TC module "
143 "\"%s\": No matching libnl TC module found.", tm->tm_name);
144 }
145
146 if (__nl_cli_tc_lookup(ops)) {
147 nl_cli_fatal(EEXIST, "Unable to register CLI TC module "
148 "\"%s\": Module already registered.", tm->tm_name);
149 }
150
151 tm->tm_ops = ops;
152
153 nl_list_add_tail(&tm->tm_list, &tc_modules);
154 }
155
nl_cli_tc_unregister(struct nl_cli_tc_module * tm)156 void nl_cli_tc_unregister(struct nl_cli_tc_module *tm)
157 {
158 nl_list_del(&tm->tm_list);
159 }
160
161
162 /** @} */
163