summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Syromyatnikov <evgsyr@gmail.com>2023-05-10 19:58:37 +0200
committerEugene Syromyatnikov <evgsyr@gmail.com>2023-05-10 20:08:00 +0200
commit83b7f0c841d64ad3d8f28fd73df4d0cc9268daad (patch)
tree3dce04e2109f84c52b7c4750b1d6f0964414eee5
parentb30e9d446019b31c2a74b2addaa5b591e8947d61 (diff)
downloadstrace-esyr/tcamsg-fixes.tar.gz
rtnl_tc_action: fix tcamsg attribute decoderesyr/tcamsg-fixes
It used the wrong attribute table initially. An example of an actual usage: tc actions add action simple sdata "foobar" index 1 * src/xlat/rtnl_tca_root_attrs.in: New file. * src/xlat/rtnl_tca_root_flags.in: Likewise. * src/rtnl_tc_action.c: Include "xlat/rtnl_tca_root_flags.h" and "xlat/rtnl_tca_root_attrs.h". (tcamsg_nla_decoders): Rename to... (tca_act_nla_decoders): ...this. (decode_tca_action, decode_tca_root_act_tab, decode_tca_root_act_flags, decode_tca_msecs): New functions. (tcamsg_nla_decoders): New decoder table. (decode_tcamsg): Use rtnl_tca_root_attrs and "TCA_ROOT_???" as xlat and dflt arguments in the decode_nlattr call. respectively. * tests/.gitignore: Add nlattr_tcamsg-Xabbrev, nlattr_tcamsg-Xraw, and nlattr_tcamsg-Xverbose. * tests/pure_executables.list: Likewise. * tests/gen_tests.in (nlattr_tcamsg-Xabbrev, nlattr_tcamsg-Xraw, nlattr_tcamsg-Xverbose): New tests. * tests/nlattr_tcamsg-Xabbrev.c: New file. * tests/nlattr_tcamsg-Xraw.c: Likewise. * tests/nlattr_tcamsg-Xverbose.c: Likewise. * tests/nlattr_tcamsg.c: Update the expected output.
-rw-r--r--src/rtnl_tc_action.c73
-rw-r--r--src/xlat/rtnl_tca_root_attrs.in7
-rw-r--r--src/xlat/rtnl_tca_root_flags.in2
-rw-r--r--tests/.gitignore3
-rw-r--r--tests/gen_tests.in3
-rw-r--r--tests/nlattr_tcamsg-Xabbrev.c2
-rw-r--r--tests/nlattr_tcamsg-Xraw.c2
-rw-r--r--tests/nlattr_tcamsg-Xverbose.c2
-rw-r--r--tests/nlattr_tcamsg.c253
-rwxr-xr-xtests/pure_executables.list3
10 files changed, 309 insertions, 41 deletions
diff --git a/src/rtnl_tc_action.c b/src/rtnl_tc_action.c
index 33e22d426..55f40f29d 100644
--- a/src/rtnl_tc_action.c
+++ b/src/rtnl_tc_action.c
@@ -18,6 +18,8 @@
#include "xlat/rtnl_tc_action_attrs.h"
#include "xlat/rtnl_tca_act_flags.h"
#include "xlat/rtnl_tca_act_hw_stats.h"
+#include "xlat/rtnl_tca_root_flags.h"
+#include "xlat/rtnl_tca_root_attrs.h"
static bool
@@ -48,7 +50,7 @@ decode_tca_act_hw_stats(struct tcb *const tcp,
return decode_nla_flags(tcp, addr, len, &opts);
}
-static const nla_decoder_t tcamsg_nla_decoders[] = {
+static const nla_decoder_t tca_act_nla_decoders[] = {
[TCA_ACT_KIND] = decode_nla_str,
[TCA_ACT_OPTIONS] = NULL, /* unimplemented */
[TCA_ACT_INDEX] = decode_nla_u32,
@@ -61,6 +63,73 @@ static const nla_decoder_t tcamsg_nla_decoders[] = {
[TCA_ACT_IN_HW_COUNT] = decode_nla_u32,
};
+static bool
+decode_tca_action(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const unsigned int len,
+ const void *const opaque_data)
+{
+ decode_nlattr(tcp, addr, len, rtnl_tc_action_attrs, "TCA_ACT_???",
+ ARRSZ_PAIR(tca_act_nla_decoders), NULL);
+
+ return true;
+}
+
+static bool
+decode_tca_root_act_tab(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const unsigned int len,
+ const void *const opaque_data)
+{
+ nla_decoder_t tca_action_decoder = &decode_tca_action;
+
+ /* TCA_ROOT_TAB (nee TCA_ACT_TAB) misuses nesting for array */
+ decode_nlattr(tcp, addr, len, NULL, NULL,
+ &tca_action_decoder, 0, NULL);
+
+ return true;
+}
+
+static bool
+decode_tca_root_act_flags(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const unsigned int len,
+ const void *const opaque_data)
+{
+ static const struct decode_nla_xlat_opts opts = {
+ rtnl_tca_root_flags, "TCA_ACT_FLAG_???",
+ .size = 4,
+ };
+
+ return decode_nla_flags(tcp, addr, len, &opts);
+}
+
+static bool
+decode_tca_msecs(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const unsigned int len,
+ const void *const opaque_data)
+{
+ uint64_t val;
+
+ if (len > sizeof(val))
+ return false;
+
+ if (!umoven_to_uint64_or_printaddr(tcp, addr, len, &val))
+ print_ticks(val, 1000, 3);
+
+ return true;
+}
+
+static const nla_decoder_t tcamsg_nla_decoders[] = {
+ [TCA_ROOT_UNSPEC] = NULL,
+ [TCA_ROOT_TAB] = decode_tca_root_act_tab,
+ [TCA_ROOT_FLAGS] = decode_tca_root_act_flags,
+ [TCA_ROOT_COUNT] = decode_nla_u32,
+ [TCA_ROOT_TIME_DELTA] = decode_tca_msecs,
+ [TCA_ROOT_EXT_WARN_MSG] = decode_nla_str,
+};
+
DECL_NETLINK_ROUTE_DECODER(decode_tcamsg)
{
struct tcamsg tca = { .tca_family = family };
@@ -73,7 +142,7 @@ DECL_NETLINK_ROUTE_DECODER(decode_tcamsg)
if (len > offset) {
tprint_array_next();
decode_nlattr(tcp, addr + offset, len - offset,
- rtnl_tc_action_attrs, "TCA_ACT_???",
+ rtnl_tca_root_attrs, "TCA_ROOT_???",
tcamsg_nla_decoders,
ARRAY_SIZE(tcamsg_nla_decoders), NULL);
}
diff --git a/src/xlat/rtnl_tca_root_attrs.in b/src/xlat/rtnl_tca_root_attrs.in
new file mode 100644
index 000000000..4daf24e95
--- /dev/null
+++ b/src/xlat/rtnl_tca_root_attrs.in
@@ -0,0 +1,7 @@
+#value_indexed
+TCA_ROOT_UNSPEC 0
+TCA_ROOT_TAB 1
+TCA_ROOT_FLAGS 2
+TCA_ROOT_COUNT 3
+TCA_ROOT_TIME_DELTA 4
+TCA_ROOT_EXT_WARN_MSG 5
diff --git a/src/xlat/rtnl_tca_root_flags.in b/src/xlat/rtnl_tca_root_flags.in
new file mode 100644
index 000000000..f45a0b3d8
--- /dev/null
+++ b/src/xlat/rtnl_tca_root_flags.in
@@ -0,0 +1,2 @@
+TCA_ACT_FLAG_LARGE_DUMP_ON (1 << 0)
+TCA_ACT_FLAG_TERSE_DUMP (1 << 1)
diff --git a/tests/.gitignore b/tests/.gitignore
index d9272ba33..85fe42e9c 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -650,6 +650,9 @@ nlattr_smc_diag_msg
nlattr_tc_stats
nlattr_tca_stab
nlattr_tcamsg
+nlattr_tcamsg-Xabbrev
+nlattr_tcamsg-Xraw
+nlattr_tcamsg-Xverbose
nlattr_tcmsg
nlattr_unix_diag_msg
nsyscalls
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 9a48e9f96..afdf7b60d 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -651,6 +651,9 @@ nlattr_smc_diag_msg +netlink_sock_diag.test
nlattr_tc_stats +netlink_sock_diag.test
nlattr_tca_stab +netlink_sock_diag.test
nlattr_tcamsg +netlink_sock_diag.test
+nlattr_tcamsg-Xabbrev +netlink_sock_diag.test -Xabbrev
+nlattr_tcamsg-Xraw +netlink_sock_diag.test -Xraw
+nlattr_tcamsg-Xverbose +netlink_sock_diag.test -Xverbose
nlattr_tcmsg +netlink_sock_diag.test
nlattr_unix_diag_msg +netlink_sock_diag.test
old_mmap -a11 -e trace=mmap
diff --git a/tests/nlattr_tcamsg-Xabbrev.c b/tests/nlattr_tcamsg-Xabbrev.c
new file mode 100644
index 000000000..f0351398d
--- /dev/null
+++ b/tests/nlattr_tcamsg-Xabbrev.c
@@ -0,0 +1,2 @@
+#define XLAT_ABBREV 1
+#include "nlattr_tcamsg.c"
diff --git a/tests/nlattr_tcamsg-Xraw.c b/tests/nlattr_tcamsg-Xraw.c
new file mode 100644
index 000000000..f1b5d7a00
--- /dev/null
+++ b/tests/nlattr_tcamsg-Xraw.c
@@ -0,0 +1,2 @@
+#define XLAT_RAW 1
+#include "nlattr_tcamsg.c"
diff --git a/tests/nlattr_tcamsg-Xverbose.c b/tests/nlattr_tcamsg-Xverbose.c
new file mode 100644
index 000000000..85f262ad7
--- /dev/null
+++ b/tests/nlattr_tcamsg-Xverbose.c
@@ -0,0 +1,2 @@
+#define XLAT_VERBOSE 1
+#include "nlattr_tcamsg.c"
diff --git a/tests/nlattr_tcamsg.c b/tests/nlattr_tcamsg.c
index 291df76d5..45cfffe1f 100644
--- a/tests/nlattr_tcamsg.c
+++ b/tests/nlattr_tcamsg.c
@@ -32,6 +32,7 @@ enum { TCA_ACT_USED_HW_STATS = 9 };
enum { TCA_ACT_IN_HW_COUNT = 10 };
#endif
+static const unsigned int hdrlen = sizeof(struct tcamsg);
static void
init_tcamsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
@@ -51,9 +52,52 @@ init_tcamsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
static void
print_tcamsg(const unsigned int msg_len)
{
- printf("{nlmsg_len=%u, nlmsg_type=RTM_GETACTION, nlmsg_flags=NLM_F_DUMP"
- ", nlmsg_seq=0, nlmsg_pid=0}, {tca_family=AF_INET}",
- msg_len);
+ printf("{nlmsg_len=%u, nlmsg_type=" XLAT_FMT ", nlmsg_flags=" XLAT_FMT
+ ", nlmsg_seq=0, nlmsg_pid=0}, {tca_family=" XLAT_FMT "}",
+ msg_len, XLAT_ARGS(RTM_GETACTION), XLAT_ARGS(NLM_F_DUMP),
+ XLAT_ARGS(AF_INET));
+}
+
+static void
+init_tcamsg_tab(struct nlmsghdr *const nlh, const unsigned int msg_len)
+{
+ init_tcamsg(nlh, msg_len);
+
+ struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
+ SET_STRUCT(struct nlattr, nla,
+ .nla_len = msg_len - NLMSG_SPACE(hdrlen),
+ .nla_type = 1,
+ );
+}
+
+static void
+print_tcamsg_tab(const unsigned int msg_len)
+{
+ print_tcamsg(msg_len);
+ printf(", [{nla_len=%u, nla_type=" XLAT_FMT "}",
+ msg_len - NLMSG_SPACE(hdrlen), XLAT_ARGS(TCA_ROOT_TAB));
+}
+
+static uint16_t tab_idx;
+
+static void
+init_tcamsg_tab_item(struct nlmsghdr *const nlh, const unsigned int msg_len)
+{
+ init_tcamsg_tab(nlh, msg_len);
+
+ struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen + NLA_HDRLEN);
+ SET_STRUCT(struct nlattr, nla,
+ .nla_len = msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN,
+ .nla_type = tab_idx,
+ );
+}
+
+static void
+print_tcamsg_tab_item(const unsigned int msg_len)
+{
+ print_tcamsg_tab(msg_len);
+ printf(", [{nla_len=%u, nla_type=%#x}",
+ msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN, tab_idx);
}
int
@@ -69,10 +113,11 @@ main(void)
fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
/* Invalid */
- static const unsigned int nla_invalid[] = { 11, 0xffff & NLA_TYPE_MASK };
+ static const unsigned int nla_invalid[] = { 6, 0xffff & NLA_TYPE_MASK };
for (size_t i = 0; i < ARRAY_SIZE(nla_invalid); i++) {
char nla_type_str[256];
- sprintf(nla_type_str, "%#x /* TCA_ACT_??? */", nla_invalid[i]);
+ sprintf(nla_type_str, "%#x" NRAW(" /* TCA_ROOT_??? */"),
+ nla_invalid[i]);
TEST_NLATTR_(fd, nlh0, hdrlen,
init_tcamsg, print_tcamsg,
nla_invalid[i], nla_type_str,
@@ -85,10 +130,7 @@ main(void)
unsigned int val;
const char *str;
} nla_default[] = {
- { ARG_STR(TCA_ACT_UNSPEC) },
- { ARG_STR(TCA_ACT_OPTIONS) },
- { ARG_STR(TCA_ACT_PAD) },
- { ARG_STR(TCA_ACT_COOKIE) },
+ { ARG_XLAT_KNOWN(0, "TCA_ROOT_UNSPEC") },
};
for (size_t i = 0; i < ARRAY_SIZE(nla_default); i++) {
TEST_NLATTR_(fd, nlh0, hdrlen,
@@ -98,51 +140,184 @@ main(void)
print_quoted_hex(pattern, 17));
}
- /* TCA_ACT_KIND */
- TEST_NLATTR(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
- TCA_ACT_KIND, 21, pattern, 21,
- print_quoted_cstring(pattern, 22));
+ /* TCA_ROOT_TAB: Invalid */
+ TEST_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg, print_tcamsg,
+ TCA_ROOT_TAB, XLAT_KNOWN(0x1, "TCA_ROOT_TAB"),
+ 3, &pattern, 3,
+ printf("\"\\x61\\x62\\x63\""));
+
+ /* TCA_ROOT_TAB: item: invalid */
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab, print_tcamsg_tab,
+ 0, "0", 3, &pattern, 3, 1,
+ printf("\"\\x61\\x62\\x63\""));
+ tab_idx++;
+
+ /* TCA_ROOT_TAB: item: default decoder */
+ static const struct {
+ unsigned int val;
+ const char *str;
+ } tcaa_default[] = {
+ { ARG_XLAT_KNOWN(0, "TCA_ACT_UNSPEC") },
+ { ARG_XLAT_KNOWN(0x2, "TCA_ACT_OPTIONS") },
+ { ARG_XLAT_KNOWN(0x5, "TCA_ACT_PAD") },
+ { ARG_XLAT_KNOWN(0x6, "TCA_ACT_COOKIE") },
+ { 11, "0xb" NRAW(" /* TCA_ACT_??? */") },
+ };
+ for (size_t i = 0; i < ARRAY_SIZE(tcaa_default); i++) {
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab_item, print_tcamsg_tab_item,
+ tcaa_default[i].val, tcaa_default[i].str,
+ 17, pattern, 17, 2,
+ print_quoted_hex(pattern, 17));
+ tab_idx++;
+ }
+
+ /* TCA_ROOT_TAB: item: TCA_ACT_KIND */
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab_item, print_tcamsg_tab_item,
+ TCA_ACT_KIND, XLAT_KNOWN(0x1, "TCA_ACT_KIND"),
+ 21, pattern, 21, 2,
+ print_quoted_cstring(pattern, 22));
+ tab_idx++;
static const char kind[] = "Hello\tthere";
- TEST_NLATTR(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
- TCA_ACT_KIND, sizeof(kind), kind, sizeof(kind),
- print_quoted_string(kind));
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab_item, print_tcamsg_tab_item,
+ TCA_ACT_KIND, XLAT_KNOWN(0x1, "TCA_ACT_KIND"),
+ sizeof(kind), kind, sizeof(kind), 2,
+ print_quoted_string(kind));
+ tab_idx++;
- /* TCA_ACT_INDEX */
+ /* TCA_ROOT_TAB: item: TCA_ACT_INDEX */
static uint32_t idx = 0xdeadc0de;
- TEST_NLATTR(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
- TCA_ACT_INDEX, sizeof(idx), &idx, sizeof(idx),
- printf("%u", idx));
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab_item, print_tcamsg_tab_item,
+ TCA_ACT_INDEX, XLAT_KNOWN(0x3, "TCA_ACT_INDEX"),
+ sizeof(idx), &idx, sizeof(idx), 2,
+ printf("%u", idx));
+ tab_idx++;
- /* TCA_ACT_FLAGS */
+ /* TCA_ROOT_TAB: item: TCA_ACT_FLAGS */
static uint32_t flags = 0xfacebeff;
- TEST_NLATTR(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
- TCA_ACT_FLAGS, sizeof(flags), &flags, sizeof(flags),
- printf("TCA_ACT_FLAGS_NO_PERCPU_STATS|"
- "TCA_ACT_FLAGS_SKIP_HW|"
- "TCA_ACT_FLAGS_SKIP_SW|0xfacebef8"));
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab_item, print_tcamsg_tab_item,
+ TCA_ACT_FLAGS, XLAT_KNOWN(0x7, "TCA_ACT_FLAGS"),
+ sizeof(flags), &flags, sizeof(flags), 2,
+ printf(XLAT_FMT, XLAT_SEL(0xfacebeff,
+ "TCA_ACT_FLAGS_NO_PERCPU_STATS|"
+ "TCA_ACT_FLAGS_SKIP_HW|"
+ "TCA_ACT_FLAGS_SKIP_SW|0xfacebef8")));
+ tab_idx++;
- /* TCA_ACT_HW_STATS, TCA_ACT_USED_HW_STATS */
+ /* TCA_ROOT_TAB: item: TCA_ACT_HW_STATS, TCA_ACT_USED_HW_STATS */
static const struct strval32 nla_hw_st[] = {
- { ARG_STR(TCA_ACT_HW_STATS) },
- { ARG_STR(TCA_ACT_USED_HW_STATS) },
+ { ARG_XLAT_KNOWN(0x8, "TCA_ACT_HW_STATS") },
+ { ARG_XLAT_KNOWN(0x9, "TCA_ACT_USED_HW_STATS") },
};
static uint32_t hw_st = 0xfacebeef;
for (size_t i = 0; i < ARRAY_SIZE(nla_hw_st); i++) {
- TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
- nla_hw_st[i].val, nla_hw_st[i].str,
- sizeof(hw_st), &hw_st, sizeof(hw_st),
- printf("TCA_ACT_HW_STATS_IMMEDIATE|"
- "TCA_ACT_HW_STATS_DELAYED|0xfacebeec"));
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab_item, print_tcamsg_tab_item,
+ nla_hw_st[i].val, nla_hw_st[i].str,
+ sizeof(hw_st), &hw_st, sizeof(hw_st), 2,
+ printf(XLAT_FMT, XLAT_SEL(0xfacebeef,
+ "TCA_ACT_HW_STATS_IMMEDIATE|"
+ "TCA_ACT_HW_STATS_DELAYED|"
+ "0xfacebeec")));
+ tab_idx++;
}
- /* TCA_ACT_IN_HW_COUNT */
+ /* TCA_ROOT_TAB: item: TCA_ACT_IN_HW_COUNT */
static uint32_t hw_count = 0xdeadface;
- TEST_NLATTR(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
- TCA_ACT_IN_HW_COUNT, sizeof(hw_count),
- &hw_count, sizeof(hw_count),
- printf("%u", hw_count));
+ TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
+ init_tcamsg_tab_item, print_tcamsg_tab_item,
+ TCA_ACT_IN_HW_COUNT,
+ XLAT_KNOWN(0xa, "TCA_ACT_IN_HW_COUNT"),
+ sizeof(hw_count), &hw_count, sizeof(hw_count), 2,
+ printf("%u", hw_count));
+
+ /* TCA_ROOT_FLAGS */
+ static const struct strval32 root_flags[] = {
+ { ARG_STR(0) },
+ { ARG_XLAT_KNOWN(0x1, "TCA_ACT_FLAG_LARGE_DUMP_ON") },
+ { ARG_XLAT_KNOWN(0x3, "TCA_ACT_FLAG_LARGE_DUMP_ON|"
+ "TCA_ACT_FLAG_TERSE_DUMP") },
+ { ARG_XLAT_KNOWN(0xcafebeef, "TCA_ACT_FLAG_LARGE_DUMP_ON|"
+ "TCA_ACT_FLAG_TERSE_DUMP|"
+ "0xcafebeec") },
+ { ARG_XLAT_UNKNOWN(0xbadc0dec, "TCA_ACT_FLAG_???") },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(root_flags); i++) {
+ TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
+ TCA_ROOT_FLAGS, XLAT_KNOWN(0x2, "TCA_ROOT_FLAGS"),
+ 4, &root_flags[i].val, 4,
+ printf("%s", root_flags[i].str));
+ }
+
+ /* TCA_ROOT_COUNT */
+ static const uint32_t cnt_vals[] = { 0, 1, 0xbac0ded };
+
+ for (size_t i = 0; i < ARRAY_SIZE(cnt_vals); i++) {
+ TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
+ TCA_ROOT_COUNT, XLAT_KNOWN(0x3, "TCA_ROOT_COUNT"),
+ 4, &cnt_vals[i], 4,
+ printf("%u", cnt_vals[i]));
+ }
+
+ /* TCA_ROOT_TIME_DELTA */
+ static const struct strval32 time_deltas[] = {
+ { 0, "0" },
+ { 1, "1" NRAW(" /* 0.001 s */") },
+ { 10, "10" NRAW(" /* 0.010 s */") },
+ { 100, "100" NRAW(" /* 0.100 s */") },
+ { 999, "999" NRAW(" /* 0.999 s */") },
+ { 1000, "1000" NRAW(" /* 1.000 s */") },
+ { 1001, "1001" NRAW(" /* 1.001 s */") },
+ { 1010, "1010" NRAW(" /* 1.010 s */") },
+ { 0xfeedface, "4277009102" NRAW(" /* 4277009.102 s */") },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(time_deltas); i++) {
+ TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
+ TCA_ROOT_TIME_DELTA,
+ XLAT_KNOWN(0x4, "TCA_ROOT_TIME_DELTA"),
+ 4, &time_deltas[i].val, 4,
+ printf("%s", time_deltas[i].str));
+ }
+
+ static const struct strval64 time_deltas64[] = {
+ { 0, "0" },
+ { 1, "1" NRAW(" /* 0.001 s */") },
+ { 10, "10" NRAW(" /* 0.010 s */") },
+ { 100, "100" NRAW(" /* 0.100 s */") },
+ { 999, "999" NRAW(" /* 0.999 s */") },
+ { 1000, "1000" NRAW(" /* 1.000 s */") },
+ { 1001, "1001" NRAW(" /* 1.001 s */") },
+ { 1010, "1010" NRAW(" /* 1.010 s */") },
+ { 0xfeedface, "4277009102" NRAW(" /* 4277009.102 s */") },
+ { 0xbadfacedeadc0ded, "13465671548708589037"
+ NRAW(" /* 13465671548708589.037 s */") },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(time_deltas64); i++) {
+ TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
+ TCA_ROOT_TIME_DELTA,
+ XLAT_KNOWN(0x4, "TCA_ROOT_TIME_DELTA"),
+ 8, &time_deltas64[i].val, 8,
+ printf("%s", time_deltas64[i].str));
+ }
+
+ /* TCA_ROOT_EXT_WARN_MSG */
+ static const char msg[] = "Hello\tthere";
+ TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
+ TCA_ROOT_EXT_WARN_MSG,
+ XLAT_KNOWN(0x5, "TCA_ROOT_EXT_WARN_MSG"),
+ sizeof(msg), msg, sizeof(msg),
+ print_quoted_string(msg));
puts("+++ exited with 0 +++");
return 0;
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index b8f8c364c..9c1b81fa6 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -471,6 +471,9 @@ nlattr_smc_diag_msg
nlattr_tc_stats
nlattr_tca_stab
nlattr_tcamsg
+nlattr_tcamsg-Xabbrev
+nlattr_tcamsg-Xraw
+nlattr_tcamsg-Xverbose
nlattr_tcmsg
nlattr_unix_diag_msg
old_mmap