1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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;
}
|