Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
http://lists.infradead.org/pipermail/libnl/2014-July/001566.html http://lists.infradead.org/pipermail/libnl/2014-July/001594.html Signed-off-by: Thomas Haller <thaller@redhat.com>
- Loading branch information
Showing
9 changed files
with
718 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* netlink/route/sch/hfsc.h HFSC Qdisc | ||
* | ||
* This library is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation version 2.1 | ||
* of the License. | ||
* | ||
* Copyright (c) 2014 Cong Wang <xiyou.wangcong@gmail.com> | ||
*/ | ||
|
||
#ifndef NETLINK_HFSC_H_ | ||
#define NETLINK_HFSC_H_ | ||
|
||
#include <netlink/netlink.h> | ||
#include <netlink/route/tc.h> | ||
#include <netlink/route/qdisc.h> | ||
#include <netlink/route/class.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
extern uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *); | ||
extern int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *, uint32_t); | ||
|
||
extern int rtnl_class_hfsc_get_rsc(const struct rtnl_class *class, struct tc_service_curve *tsc); | ||
extern int rtnl_class_hfsc_set_rsc(struct rtnl_class *class, const struct tc_service_curve *tsc); | ||
extern int rtnl_class_hfsc_get_fsc(const struct rtnl_class *class, struct tc_service_curve *tsc); | ||
extern int rtnl_class_hfsc_set_fsc(struct rtnl_class *class, const struct tc_service_curve *tsc); | ||
extern int rtnl_class_hfsc_get_usc(const struct rtnl_class *class, struct tc_service_curve *tsc); | ||
extern int rtnl_class_hfsc_set_usc(struct rtnl_class *class, const struct tc_service_curve *tsc); | ||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
/* | ||
* lib/cli/qdisc/hfsc.c HFSC module for CLI lib | ||
* | ||
* This library is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation version 2.1 | ||
* of the License. | ||
* | ||
* Copyright (c) 2014 Cong Wang <xiyou.wangcong@gmail.com> | ||
*/ | ||
|
||
#include <netlink/cli/utils.h> | ||
#include <netlink/cli/tc.h> | ||
#include <netlink/route/qdisc/hfsc.h> | ||
|
||
static void print_qdisc_usage(void) | ||
{ | ||
printf( | ||
"Usage: nl-qdisc-add [...] hfsc [OPTIONS]...\n" | ||
"\n" | ||
"OPTIONS\n" | ||
" --help Show this help text.\n" | ||
" --default=ID Default class for unclassified traffic.\n" | ||
"\n" | ||
"EXAMPLE" | ||
" # Create hfsc root qdisc 1: and direct unclassified traffic to class 1:10\n" | ||
" nl-qdisc-add --dev=eth1 --parent=root --handle=1: hfsc --default=10\n"); | ||
} | ||
|
||
static void hfsc_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv) | ||
{ | ||
struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; | ||
|
||
for (;;) { | ||
int c, optidx = 0; | ||
enum { | ||
ARG_DEFAULT = 257, | ||
}; | ||
static struct option long_opts[] = { | ||
{ "help", 0, 0, 'h' }, | ||
{ "default", 1, 0, ARG_DEFAULT }, | ||
{ 0, 0, 0, 0 } | ||
}; | ||
|
||
c = getopt_long(argc, argv, "hv", long_opts, &optidx); | ||
if (c == -1) | ||
break; | ||
|
||
switch (c) { | ||
case 'h': | ||
print_qdisc_usage(); | ||
return; | ||
|
||
case ARG_DEFAULT: | ||
rtnl_qdisc_hfsc_set_defcls(qdisc, nl_cli_parse_u32(optarg)); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
static void print_class_usage(void) | ||
{ | ||
printf( | ||
"Usage: nl-class-add [...] hfsc [OPTIONS]...\n" | ||
"\n" | ||
"OPTIONS\n" | ||
" --help Show this help text.\n" | ||
" --ls=SC Link-sharing service curve\n" | ||
" --rt=SC Real-time service curve\n" | ||
" --sc=SC Specifiy both of the above\n" | ||
" --ul=SC Upper limit\n" | ||
" where SC := [ [ m1 bits ] d usec ] m2 bits\n" | ||
"\n" | ||
"EXAMPLE" | ||
" # Attach class 1:1 to hfsc qdisc 1: and use rt and ls curve\n" | ||
" nl-class-add --dev=eth1 --parent=1: --classid=1:1 hfsc --sc=m1:250,d:8,m2:100\n"); | ||
} | ||
|
||
static int | ||
hfsc_get_sc(char *optarg, struct tc_service_curve *sc) | ||
{ | ||
unsigned int m1 = 0, d = 0, m2 = 0; | ||
char *tmp = strdup(optarg); | ||
char *p = tmp, *endptr; | ||
|
||
if (!tmp) | ||
return -ENOMEM; | ||
|
||
p = strstr(p, "m1:"); | ||
if (p) { | ||
char *q; | ||
p += 3; | ||
if (*p == 0) | ||
goto err; | ||
q = strchr(p, ','); | ||
if (!q) | ||
goto err; | ||
*q = 0; | ||
m1 = strtoul(p, &endptr, 10); | ||
if (endptr == p) | ||
goto err; | ||
p = q + 1; | ||
} | ||
|
||
p = strstr(p, "d:"); | ||
if (p) { | ||
char *q; | ||
p += 2; | ||
if (*p == 0) | ||
goto err; | ||
q = strchr(p, ','); | ||
if (!q) | ||
goto err; | ||
*q = 0; | ||
d = strtoul(p, &endptr, 10); | ||
if (endptr == p) | ||
goto err; | ||
p = q + 1; | ||
} | ||
|
||
p = strstr(p, "m2:"); | ||
if (p) { | ||
p += 3; | ||
if (*p == 0) | ||
goto err; | ||
m2 = strtoul(p, &endptr, 10); | ||
if (endptr == p) | ||
goto err; | ||
} else | ||
goto err; | ||
|
||
free(tmp); | ||
sc->m1 = m1; | ||
sc->d = d; | ||
sc->m2 = m2; | ||
return 0; | ||
|
||
err: | ||
free(tmp); | ||
return -EINVAL; | ||
} | ||
|
||
static void hfsc_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv) | ||
{ | ||
struct rtnl_class *class = (struct rtnl_class *) tc; | ||
int arg_ok = 0, ret = -EINVAL; | ||
|
||
for (;;) { | ||
int c, optidx = 0; | ||
enum { | ||
ARG_RT = 257, | ||
ARG_LS = 258, | ||
ARG_SC, | ||
ARG_UL, | ||
}; | ||
static struct option long_opts[] = { | ||
{ "help", 0, 0, 'h' }, | ||
{ "rt", 1, 0, ARG_RT }, | ||
{ "ls", 1, 0, ARG_LS }, | ||
{ "sc", 1, 0, ARG_SC }, | ||
{ "ul", 1, 0, ARG_UL }, | ||
{ 0, 0, 0, 0 } | ||
}; | ||
struct tc_service_curve tsc; | ||
|
||
c = getopt_long(argc, argv, "h", long_opts, &optidx); | ||
if (c == -1) | ||
break; | ||
|
||
switch (c) { | ||
case 'h': | ||
print_class_usage(); | ||
return; | ||
|
||
case ARG_RT: | ||
ret = hfsc_get_sc(optarg, &tsc); | ||
if (ret < 0) { | ||
nl_cli_fatal(ret, "Unable to parse sc " | ||
"\"%s\": Invalid format.", optarg); | ||
} | ||
|
||
rtnl_class_hfsc_set_rsc(class, &tsc); | ||
arg_ok++; | ||
break; | ||
|
||
case ARG_LS: | ||
ret = hfsc_get_sc(optarg, &tsc); | ||
if (ret < 0) { | ||
nl_cli_fatal(ret, "Unable to parse sc " | ||
"\"%s\": Invalid format.", optarg); | ||
} | ||
|
||
rtnl_class_hfsc_set_fsc(class, &tsc); | ||
arg_ok++; | ||
break; | ||
|
||
case ARG_SC: | ||
ret = hfsc_get_sc(optarg, &tsc); | ||
if (ret < 0) { | ||
nl_cli_fatal(ret, "Unable to parse sc " | ||
"\"%s\": Invalid format.", optarg); | ||
} | ||
|
||
rtnl_class_hfsc_set_rsc(class, &tsc); | ||
rtnl_class_hfsc_set_fsc(class, &tsc); | ||
arg_ok++; | ||
break; | ||
|
||
case ARG_UL: | ||
ret = hfsc_get_sc(optarg, &tsc); | ||
if (ret < 0) { | ||
nl_cli_fatal(ret, "Unable to parse sc " | ||
"\"%s\": Invalid format.", optarg); | ||
} | ||
|
||
rtnl_class_hfsc_set_usc(class, &tsc); | ||
arg_ok++; | ||
break; | ||
} | ||
} | ||
|
||
if (!arg_ok) | ||
nl_cli_fatal(ret, "Invalid arguments"); | ||
} | ||
|
||
static struct nl_cli_tc_module hfsc_qdisc_module = | ||
{ | ||
.tm_name = "hfsc", | ||
.tm_type = RTNL_TC_TYPE_QDISC, | ||
.tm_parse_argv = hfsc_parse_qdisc_argv, | ||
}; | ||
|
||
static struct nl_cli_tc_module hfsc_class_module = | ||
{ | ||
.tm_name = "hfsc", | ||
.tm_type = RTNL_TC_TYPE_CLASS, | ||
.tm_parse_argv = hfsc_parse_class_argv, | ||
}; | ||
|
||
static void __init hfsc_init(void) | ||
{ | ||
nl_cli_tc_register(&hfsc_qdisc_module); | ||
nl_cli_tc_register(&hfsc_class_module); | ||
} | ||
|
||
static void __exit hfsc_exit(void) | ||
{ | ||
nl_cli_tc_unregister(&hfsc_class_module); | ||
nl_cli_tc_unregister(&hfsc_qdisc_module); | ||
} |
Oops, something went wrong.