87 lines
2.3 KiB
C
87 lines
2.3 KiB
C
#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;
|
|
}
|
|
|