• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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