blob: bc47f5d1e1481326234e8b4c1c1142e07b94cda5 [file] [log] [blame]
Willy Tarreaua1bd1fa2019-03-29 17:26:33 +01001#include <inttypes.h>
Frédéric Lécaillea4d03612017-06-14 15:16:15 +02002#include <netlink/cache.h>
3#include <netlink/cli/utils.h>
4#include <netlink/cli/tc.h>
5#include <netlink/cli/qdisc.h>
6#include <netlink/cli/link.h>
7#include <netlink/route/qdisc/plug.h>
8
9/*
10 * XXX Please, first note that this code is not safe. XXX
11 * It was developed fast so that to reproduce a bug.
12 * You will certainly have to adapt it to your application.
Ilya Shipitsince7b00f2020-03-23 22:28:40 +050013 * But at least it gives an idea about how to programmatically use plug
Frédéric Lécaillea4d03612017-06-14 15:16:15 +020014 * queueing disciplines.
15 */
16
17static struct nl_sock *nl_sock;
18static struct nl_cache *link_cache;
19static struct rtnl_qdisc *qdisc;
20static struct rtnl_tc *tc;
21
22static int qdisc_init(void)
23{
24 nl_sock = nl_cli_alloc_socket();
25 nl_cli_connect(nl_sock, NETLINK_ROUTE);
26 link_cache = nl_cli_link_alloc_cache(nl_sock);
27 qdisc = nl_cli_qdisc_alloc();
28 tc = (struct rtnl_tc *)qdisc;
29
30 return 0;
31}
32
33/* Stop buffering and release all buffered and incoming 'qdisc'
34 * queueing discipline traffic.
35 */
36int plug_qdisc_release_indefinite_buffer(void)
37{
38 rtnl_qdisc_plug_release_indefinite(qdisc);
39 return rtnl_qdisc_add(nl_sock, qdisc, 0);
40}
41
42/* Start buffering incoming 'qdisc' queueing discipline traffic. */
43int plug_qdisc_plug_buffer(void)
44{
45 rtnl_qdisc_plug_buffer(qdisc);
46 return rtnl_qdisc_add(nl_sock, qdisc, 0);
47}
48
49/* Create a plug qdisc attached to 'device' network device with 'parent'
50 * as parent, with 'id' as ID and 'limit' as buffer size.
51 * This is equivalent to use nl-qdisc-add tool like that:
52 * $ nl-qdisc-add --dev=<device> --parent=<parent> --id=<id> plug --limit <limit>
53 * $ nl-qdisc-add --dev=<device> --parent=<parent> --id=<id> --update plug --release-indefinite
54 */
55int plug_qdisc_attach(char *device, char *parent, char *id, uint32_t limit)
56{
57 int ret;
58
59 if (!tc && qdisc_init() == -1)
60 return -1;
61
62 nl_cli_tc_parse_dev(tc, link_cache, device);
63 nl_cli_tc_parse_parent(tc, parent);
64 if (!rtnl_tc_get_ifindex(tc))
65 return -1;
66
67 if (!rtnl_tc_get_parent(tc))
68 return -1;
69 if (id)
70 nl_cli_tc_parse_handle(tc, id, 1);
71
72 rtnl_tc_set_kind(tc, "plug");
73 if (limit)
74 rtnl_qdisc_plug_set_limit(qdisc, limit);
75
76 ret = rtnl_qdisc_add(nl_sock, qdisc, NLM_F_CREATE);
77 if (ret < 0) {
78 fprintf(stderr, "Could add attach qdisc: %s\n", nl_geterror(ret));
79 return -1;
80 }
81 /* Release buffer. */
82 plug_qdisc_release_indefinite_buffer();
83
84 return 0;
85}
86