From 206c58a9ab53e47cf85227a7c2ee6c6ef7f0c0d5 Mon Sep 17 00:00:00 2001 From: Eugene Syromyatnikov Date: Wed, 10 May 2023 19:58:37 +0200 Subject: rtnl_tc_action: fix tcamsg attribute decoder 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. --- src/rtnl_tc_action.c | 73 +++++++++++- src/xlat/rtnl_tca_root_attrs.in | 7 ++ src/xlat/rtnl_tca_root_flags.in | 2 + tests/.gitignore | 3 + tests/gen_tests.in | 3 + tests/nlattr_tcamsg-Xabbrev.c | 2 + tests/nlattr_tcamsg-Xraw.c | 2 + tests/nlattr_tcamsg-Xverbose.c | 2 + tests/nlattr_tcamsg.c | 253 +++++++++++++++++++++++++++++++++------- tests/pure_executables.list | 3 + 10 files changed, 309 insertions(+), 41 deletions(-) create mode 100644 src/xlat/rtnl_tca_root_attrs.in create mode 100644 src/xlat/rtnl_tca_root_flags.in create mode 100644 tests/nlattr_tcamsg-Xabbrev.c create mode 100644 tests/nlattr_tcamsg-Xraw.c create mode 100644 tests/nlattr_tcamsg-Xverbose.c 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 -- cgit v1.2.1