1 /*
2 * src/nl-qdisc-dump.c Dump qdisc attributes
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
7 * of the License.
8 *
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
10 */
11
12 #include "utils.h"
13 #include <netlink/route/sch/fifo.h>
14 #include <netlink/route/sch/prio.h>
15
print_usage(void)16 static void print_usage(void)
17 {
18 printf(
19 "Usage: nl-qdisc-add <ifindex> <handle> <parent> <kind>\n");
20 exit(1);
21 }
22
parse_blackhole_opts(struct rtnl_qdisc * qdisc,char * argv[],int argc)23 static int parse_blackhole_opts(struct rtnl_qdisc *qdisc, char *argv[],
24 int argc)
25 {
26 return 0;
27 }
28
parse_pfifo_opts(struct rtnl_qdisc * qdisc,char * argv[],int argc)29 static int parse_pfifo_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc)
30 {
31 int err, limit;
32
33 if (argc > 0) {
34 if (argc != 2 || strcasecmp(argv[0], "limit")) {
35 fprintf(stderr, "Usage: ... pfifo limit <limit>\n");
36 return -1;
37 }
38
39 limit = strtoul(argv[1], NULL, 0);
40 err = rtnl_qdisc_fifo_set_limit(qdisc, limit);
41 if (err < 0) {
42 fprintf(stderr, "%s\n", nl_geterror());
43 return -1;
44 }
45 }
46
47 return 0;
48 }
49
parse_bfifo_opts(struct rtnl_qdisc * qdisc,char * argv[],int argc)50 static int parse_bfifo_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc)
51 {
52 int err, limit;
53
54 if (argc > 0) {
55 if (argc != 2 || strcasecmp(argv[0], "limit")) {
56 fprintf(stderr, "Usage: ... bfifo limit <limit>\n");
57 return -1;
58 }
59
60 limit = nl_size2int(argv[1]);
61 if (limit < 0) {
62 fprintf(stderr, "Invalid value for limit.\n");
63 return -1;
64 }
65
66 err = rtnl_qdisc_fifo_set_limit(qdisc, limit);
67 if (err < 0) {
68 fprintf(stderr, "%s\n", nl_geterror());
69 return -1;
70 }
71 }
72
73 return 0;
74 }
75
parse_prio_opts(struct rtnl_qdisc * qdisc,char * argv[],int argc)76 static int parse_prio_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc)
77 {
78 int i, err, bands;
79 uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP;
80
81 if (argc > 0) {
82 if (argc < 2 || strcasecmp(argv[0], "bands"))
83 goto usage;
84
85 bands = strtoul(argv[1], NULL, 0);
86 err = rtnl_qdisc_prio_set_bands(qdisc, bands);
87 if (err < 0) {
88 fprintf(stderr, "%s\n", nl_geterror());
89 return -1;
90 }
91 }
92
93 if (argc > 2) {
94 if (argc < 5 || strcasecmp(argv[2], "map"))
95 goto usage;
96
97 for (i = 3; i < (argc & ~1U); i += 2) {
98 int prio, band;
99
100 prio = rtnl_str2prio(argv[i]);
101 if (prio < 0 || prio > sizeof(map)/sizeof(map[0])) {
102 fprintf(stderr, "Invalid priority \"%s\"\n",
103 argv[i]);
104 return -1;
105 }
106
107 band = strtoul(argv[i+1], NULL, 0);
108
109 map[prio] = band;
110 }
111 }
112
113 err = rtnl_qdisc_prio_set_priomap(qdisc, map, sizeof(map));
114 if (err < 0) {
115 fprintf(stderr, "%s\n", nl_geterror());
116 return -1;
117 }
118
119 return 0;
120 usage:
121 fprintf(stderr, "Usage: ... prio bands <nbands> map MAP\n"
122 "MAP := <prio> <band>\n");
123 return -1;
124 }
125
main(int argc,char * argv[])126 int main(int argc, char *argv[])
127 {
128 struct nl_sock *nlh;
129 struct rtnl_qdisc *qdisc;
130 uint32_t handle, parent;
131 int err = 1;
132
133 if (nltool_init(argc, argv) < 0)
134 return -1;
135
136 if (argc < 5 || !strcmp(argv[1], "-h"))
137 print_usage();
138
139 nlh = nltool_alloc_handle();
140 if (!nlh)
141 goto errout;
142
143 qdisc = rtnl_qdisc_alloc();
144 if (!qdisc)
145 goto errout_free_handle;
146
147 rtnl_qdisc_set_ifindex(qdisc, strtoul(argv[1], NULL, 0));
148
149 if (rtnl_tc_str2handle(argv[2], &handle) < 0) {
150 fprintf(stderr, "%s\n", nl_geterror());
151 goto errout_free_qdisc;
152 }
153
154 if (rtnl_tc_str2handle(argv[3], &parent) < 0) {
155 fprintf(stderr, "%s\n", nl_geterror());
156 goto errout_free_qdisc;
157 }
158
159 rtnl_qdisc_set_handle(qdisc, handle);
160 rtnl_qdisc_set_parent(qdisc, parent);
161 rtnl_qdisc_set_kind(qdisc, argv[4]);
162
163 if (!strcasecmp(argv[4], "blackhole"))
164 err = parse_blackhole_opts(qdisc, &argv[5], argc-5);
165 else if (!strcasecmp(argv[4], "pfifo"))
166 err = parse_pfifo_opts(qdisc, &argv[5], argc-5);
167 else if (!strcasecmp(argv[4], "bfifo"))
168 err = parse_bfifo_opts(qdisc, &argv[5], argc-5);
169 else if (!strcasecmp(argv[4], "prio"))
170 err = parse_prio_opts(qdisc, &argv[5], argc-5);
171 else {
172 fprintf(stderr, "Unknown qdisc \"%s\"\n", argv[4]);
173 goto errout_free_qdisc;
174 }
175
176 if (err < 0)
177 goto errout_free_qdisc;
178
179 if (nltool_connect(nlh, NETLINK_ROUTE) < 0)
180 goto errout_free_qdisc;
181
182 if (rtnl_qdisc_add(nlh, qdisc, NLM_F_REPLACE) < 0) {
183 fprintf(stderr, "Unable to add Qdisc: %s\n", nl_geterror());
184 goto errout_close;
185 }
186
187 err = 0;
188 errout_close:
189 nl_close(nlh);
190 errout_free_qdisc:
191 rtnl_qdisc_put(qdisc);
192 errout_free_handle:
193 nl_handle_destroy(nlh);
194 errout:
195 return err;
196 }
197