1 /*
2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3 * Copyright (c) 2017-2021 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "tests.h"
10 #include <stdio.h>
11 #include <stddef.h>
12 #include "test_nlattr.h"
13 #include <linux/gen_stats.h>
14 #include <linux/rtnetlink.h>
15
16 const unsigned int hdrlen = sizeof(struct tcmsg);
17
18 static void
19 init_tcmsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
20 {
21 SET_STRUCT(struct nlmsghdr, nlh,
22 .nlmsg_len = msg_len,
23 .nlmsg_type = RTM_GETQDISC,
24 .nlmsg_flags = NLM_F_DUMP
25 );
26
27 struct tcmsg *const msg = NLMSG_DATA(nlh);
28 SET_STRUCT(struct tcmsg, msg,
29 .tcm_family = AF_UNIX,
30 .tcm_ifindex = ifindex_lo()
31 );
32
33 struct nlattr *const nla = NLMSG_ATTR(nlh, sizeof(*msg));
34 SET_STRUCT(struct nlattr, nla,
35 .nla_len = msg_len - NLMSG_SPACE(hdrlen),
36 .nla_type = TCA_STATS2
37 );
38 }
39
40 static void
41 print_tcmsg(const unsigned int msg_len)
42 {
43 printf("{nlmsg_len=%u, nlmsg_type=RTM_GETQDISC, nlmsg_flags=NLM_F_DUMP"
44 ", nlmsg_seq=0, nlmsg_pid=0}, {tcm_family=AF_UNIX"
45 ", tcm_ifindex=" IFINDEX_LO_STR
46 ", tcm_handle=0, tcm_parent=0, tcm_info=0}"
47 ", [{nla_len=%u, nla_type=TCA_STATS2}",
48 msg_len, msg_len - NLMSG_SPACE(hdrlen));
49 }
50
51 int
52 main(void)
53 {
54 skip_if_unavailable("/proc/self/fd/");
55
56 const int fd = create_nl_socket(NETLINK_ROUTE);
57 void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + 8 * 5);
58
59 static char pattern[4096];
60 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
61
62 static const struct gnet_stats_basic sb = {
63 .bytes = 0xabcdebdafefeadeb,
64 .packets = 0xbdcdeabf
65 };
66 char buf[offsetofend(struct gnet_stats_basic, packets)];
67 memcpy(buf, &sb, sizeof(buf));
68 TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen,
69 init_tcmsg, print_tcmsg,
70 TCA_STATS_BASIC, pattern, buf,
71 printf("{");
72 PRINT_FIELD_U(sb, bytes);
73 printf(", ");
74 PRINT_FIELD_U(sb, packets);
75 printf("}"));
76
77 static const struct gnet_stats_rate_est est = {
78 .bps = 0xebcdaebd,
79 .pps = 0xabdceade,
80 };
81 TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen,
82 init_tcmsg, print_tcmsg,
83 TCA_STATS_RATE_EST, pattern, est,
84 printf("{");
85 PRINT_FIELD_U(est, bps);
86 printf(", ");
87 PRINT_FIELD_U(est, pps);
88 printf("}"));
89
90 static const struct gnet_stats_queue qstats = {
91 .qlen = 0xabcdeabd,
92 .backlog = 0xbcdaebad,
93 .drops = 0xcdbeaedb,
94 .requeues = 0xdebaefab,
95 .overlimits = 0xefaebade
96 };
97 TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen,
98 init_tcmsg, print_tcmsg,
99 TCA_STATS_QUEUE, pattern, qstats,
100 printf("{");
101 PRINT_FIELD_U(qstats, qlen);
102 printf(", ");
103 PRINT_FIELD_U(qstats, backlog);
104 printf(", ");
105 PRINT_FIELD_U(qstats, drops);
106 printf(", ");
107 PRINT_FIELD_U(qstats, requeues);
108 printf(", ");
109 PRINT_FIELD_U(qstats, overlimits);
110 printf("}"));
111
112 static const struct gnet_stats_rate_est64 est64 = {
113 .bps = 0xacbdcdefafecaebf,
114 .pps = 0xcdabeabdfeabceaf
115 };
116 TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen,
117 init_tcmsg, print_tcmsg,
118 TCA_STATS_RATE_EST64, pattern, est64,
119 printf("{");
120 PRINT_FIELD_U(est64, bps);
121 printf(", ");
122 PRINT_FIELD_U(est64, pps);
123 printf("}"));
124
125 static const uint64_t pkt64 = 0xdeadc0defacefeedULL;
126 TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen,
127 init_tcmsg, print_tcmsg,
128 TCA_STATS_PKT64, pattern, pkt64,
129 printf("16045693111314087661"));
130
131 puts("+++ exited with 0 +++");
132 return 0;
133 }