libnl  3.2.28
hfsc.c
1 /*
2  * lib/cli/qdisc/hfsc.c HFSC module for CLI lib
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) 2014 Cong Wang <xiyou.wangcong@gmail.com>
10  */
11 
12 #include <netlink/cli/utils.h>
13 #include <netlink/cli/tc.h>
14 #include <netlink/route/qdisc/hfsc.h>
15 
16 static void print_qdisc_usage(void)
17 {
18  printf(
19 "Usage: nl-qdisc-add [...] hfsc [OPTIONS]...\n"
20 "\n"
21 "OPTIONS\n"
22 " --help Show this help text.\n"
23 " --default=ID Default class for unclassified traffic.\n"
24 "\n"
25 "EXAMPLE"
26 " # Create hfsc root qdisc 1: and direct unclassified traffic to class 1:10\n"
27 " nl-qdisc-add --dev=eth1 --parent=root --handle=1: hfsc --default=10\n");
28 }
29 
30 static void hfsc_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv)
31 {
32  struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
33 
34  for (;;) {
35  int c, optidx = 0;
36  enum {
37  ARG_DEFAULT = 257,
38  };
39  static struct option long_opts[] = {
40  { "help", 0, 0, 'h' },
41  { "default", 1, 0, ARG_DEFAULT },
42  { 0, 0, 0, 0 }
43  };
44 
45  c = getopt_long(argc, argv, "hv", long_opts, &optidx);
46  if (c == -1)
47  break;
48 
49  switch (c) {
50  case 'h':
51  print_qdisc_usage();
52  return;
53 
54  case ARG_DEFAULT:
56  break;
57  }
58  }
59 }
60 
61 static void print_class_usage(void)
62 {
63  printf(
64 "Usage: nl-class-add [...] hfsc [OPTIONS]...\n"
65 "\n"
66 "OPTIONS\n"
67 " --help Show this help text.\n"
68 " --ls=SC Link-sharing service curve\n"
69 " --rt=SC Real-time service curve\n"
70 " --sc=SC Specifiy both of the above\n"
71 " --ul=SC Upper limit\n"
72 " where SC := [ [ m1 bits ] d usec ] m2 bits\n"
73 "\n"
74 "EXAMPLE"
75 " # Attach class 1:1 to hfsc qdisc 1: and use rt and ls curve\n"
76 " nl-class-add --dev=eth1 --parent=1: --classid=1:1 hfsc --sc=m1:250,d:8,m2:100\n");
77 }
78 
79 static int
80 hfsc_get_sc(char *optarg, struct tc_service_curve *sc)
81 {
82  unsigned int m1 = 0, d = 0, m2 = 0;
83  char *tmp = strdup(optarg);
84  char *p, *endptr;
85  char *pp = tmp;
86 
87  if (!tmp)
88  return -ENOMEM;
89 
90  p = strstr(pp, "m1:");
91  if (p) {
92  char *q;
93  p += 3;
94  if (*p == 0)
95  goto err;
96  q = strchr(p, ',');
97  if (!q)
98  goto err;
99  *q = 0;
100  m1 = strtoul(p, &endptr, 10);
101  if (endptr == p)
102  goto err;
103  pp = q + 1;
104  }
105 
106  p = strstr(pp, "d:");
107  if (p) {
108  char *q;
109  p += 2;
110  if (*p == 0)
111  goto err;
112  q = strchr(p, ',');
113  if (!q)
114  goto err;
115  *q = 0;
116  d = strtoul(p, &endptr, 10);
117  if (endptr == p)
118  goto err;
119  pp = q + 1;
120  }
121 
122  p = strstr(pp, "m2:");
123  if (p) {
124  p += 3;
125  if (*p == 0)
126  goto err;
127  m2 = strtoul(p, &endptr, 10);
128  if (endptr == p)
129  goto err;
130  } else
131  goto err;
132 
133  free(tmp);
134  sc->m1 = m1;
135  sc->d = d;
136  sc->m2 = m2;
137  return 0;
138 
139 err:
140  free(tmp);
141  return -EINVAL;
142 }
143 
144 static void hfsc_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv)
145 {
146  struct rtnl_class *class = (struct rtnl_class *) tc;
147  int arg_ok = 0, ret = -EINVAL;
148 
149  for (;;) {
150  int c, optidx = 0;
151  enum {
152  ARG_RT = 257,
153  ARG_LS = 258,
154  ARG_SC,
155  ARG_UL,
156  };
157  static struct option long_opts[] = {
158  { "help", 0, 0, 'h' },
159  { "rt", 1, 0, ARG_RT },
160  { "ls", 1, 0, ARG_LS },
161  { "sc", 1, 0, ARG_SC },
162  { "ul", 1, 0, ARG_UL },
163  { 0, 0, 0, 0 }
164  };
165  struct tc_service_curve tsc;
166 
167  c = getopt_long(argc, argv, "h", long_opts, &optidx);
168  if (c == -1)
169  break;
170 
171  switch (c) {
172  case 'h':
173  print_class_usage();
174  return;
175 
176  case ARG_RT:
177  ret = hfsc_get_sc(optarg, &tsc);
178  if (ret < 0) {
179  nl_cli_fatal(ret, "Unable to parse sc "
180  "\"%s\": Invalid format.", optarg);
181  }
182 
183  rtnl_class_hfsc_set_rsc(class, &tsc);
184  arg_ok++;
185  break;
186 
187  case ARG_LS:
188  ret = hfsc_get_sc(optarg, &tsc);
189  if (ret < 0) {
190  nl_cli_fatal(ret, "Unable to parse sc "
191  "\"%s\": Invalid format.", optarg);
192  }
193 
194  rtnl_class_hfsc_set_fsc(class, &tsc);
195  arg_ok++;
196  break;
197 
198  case ARG_SC:
199  ret = hfsc_get_sc(optarg, &tsc);
200  if (ret < 0) {
201  nl_cli_fatal(ret, "Unable to parse sc "
202  "\"%s\": Invalid format.", optarg);
203  }
204 
205  rtnl_class_hfsc_set_rsc(class, &tsc);
206  rtnl_class_hfsc_set_fsc(class, &tsc);
207  arg_ok++;
208  break;
209 
210  case ARG_UL:
211  ret = hfsc_get_sc(optarg, &tsc);
212  if (ret < 0) {
213  nl_cli_fatal(ret, "Unable to parse sc "
214  "\"%s\": Invalid format.", optarg);
215  }
216 
217  rtnl_class_hfsc_set_usc(class, &tsc);
218  arg_ok++;
219  break;
220  }
221  }
222 
223  if (!arg_ok)
224  nl_cli_fatal(ret, "Invalid arguments");
225 }
226 
227 static struct nl_cli_tc_module hfsc_qdisc_module =
228 {
229  .tm_name = "hfsc",
230  .tm_type = RTNL_TC_TYPE_QDISC,
231  .tm_parse_argv = hfsc_parse_qdisc_argv,
232 };
233 
234 static struct nl_cli_tc_module hfsc_class_module =
235 {
236  .tm_name = "hfsc",
237  .tm_type = RTNL_TC_TYPE_CLASS,
238  .tm_parse_argv = hfsc_parse_class_argv,
239 };
240 
241 static void __init hfsc_init(void)
242 {
243  nl_cli_tc_register(&hfsc_qdisc_module);
244  nl_cli_tc_register(&hfsc_class_module);
245 }
246 
247 static void __exit hfsc_exit(void)
248 {
249  nl_cli_tc_unregister(&hfsc_class_module);
250  nl_cli_tc_unregister(&hfsc_qdisc_module);
251 }
uint32_t nl_cli_parse_u32(const char *arg)
Parse a text based 32 bit unsigned integer argument.
Definition: utils.c:35
int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
Set default class of the hfsc qdisc to the specified value.
Definition: hfsc.c:218
void nl_cli_fatal(int err, const char *fmt,...)
Print error message and quit application.
Definition: utils.c:70