diff options
Diffstat (limited to 'dev/plug_qdisc/plug_qdisc.c')
-rw-r--r-- | dev/plug_qdisc/plug_qdisc.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/dev/plug_qdisc/plug_qdisc.c b/dev/plug_qdisc/plug_qdisc.c new file mode 100644 index 0000000..bc47f5d --- /dev/null +++ b/dev/plug_qdisc/plug_qdisc.c @@ -0,0 +1,86 @@ +#include <inttypes.h> +#include <netlink/cache.h> +#include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> +#include <netlink/cli/qdisc.h> +#include <netlink/cli/link.h> +#include <netlink/route/qdisc/plug.h> + +/* + * XXX Please, first note that this code is not safe. XXX + * It was developed fast so that to reproduce a bug. + * You will certainly have to adapt it to your application. + * But at least it gives an idea about how to programmatically use plug + * queueing disciplines. + */ + +static struct nl_sock *nl_sock; +static struct nl_cache *link_cache; +static struct rtnl_qdisc *qdisc; +static struct rtnl_tc *tc; + +static int qdisc_init(void) +{ + nl_sock = nl_cli_alloc_socket(); + nl_cli_connect(nl_sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(nl_sock); + qdisc = nl_cli_qdisc_alloc(); + tc = (struct rtnl_tc *)qdisc; + + return 0; +} + +/* Stop buffering and release all buffered and incoming 'qdisc' + * queueing discipline traffic. + */ +int plug_qdisc_release_indefinite_buffer(void) +{ + rtnl_qdisc_plug_release_indefinite(qdisc); + return rtnl_qdisc_add(nl_sock, qdisc, 0); +} + +/* Start buffering incoming 'qdisc' queueing discipline traffic. */ +int plug_qdisc_plug_buffer(void) +{ + rtnl_qdisc_plug_buffer(qdisc); + return rtnl_qdisc_add(nl_sock, qdisc, 0); +} + +/* Create a plug qdisc attached to 'device' network device with 'parent' + * as parent, with 'id' as ID and 'limit' as buffer size. + * This is equivalent to use nl-qdisc-add tool like that: + * $ nl-qdisc-add --dev=<device> --parent=<parent> --id=<id> plug --limit <limit> + * $ nl-qdisc-add --dev=<device> --parent=<parent> --id=<id> --update plug --release-indefinite + */ +int plug_qdisc_attach(char *device, char *parent, char *id, uint32_t limit) +{ + int ret; + + if (!tc && qdisc_init() == -1) + return -1; + + nl_cli_tc_parse_dev(tc, link_cache, device); + nl_cli_tc_parse_parent(tc, parent); + if (!rtnl_tc_get_ifindex(tc)) + return -1; + + if (!rtnl_tc_get_parent(tc)) + return -1; + if (id) + nl_cli_tc_parse_handle(tc, id, 1); + + rtnl_tc_set_kind(tc, "plug"); + if (limit) + rtnl_qdisc_plug_set_limit(qdisc, limit); + + ret = rtnl_qdisc_add(nl_sock, qdisc, NLM_F_CREATE); + if (ret < 0) { + fprintf(stderr, "Could add attach qdisc: %s\n", nl_geterror(ret)); + return -1; + } + /* Release buffer. */ + plug_qdisc_release_indefinite_buffer(); + + return 0; +} + |