(root)/
strace-6.5/
tests/
nlattr_tcamsg.c
       1  /*
       2   * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
       3   * Copyright (c) 2017-2023 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: GPL-2.0-or-later
       7   */
       8  
       9  #include "tests.h"
      10  
      11  #include <stdio.h>
      12  #include "test_nlattr.h"
      13  #include <linux/pkt_cls.h>
      14  #include <linux/rtnetlink.h>
      15  
      16  #if !HAVE_DECL_TCA_ACT_PAD
      17  enum { TCA_ACT_PAD = 5 };
      18  #endif
      19  #if !HAVE_DECL_TCA_ACT_COOKIE
      20  enum { TCA_ACT_COOKIE = 6 };
      21  #endif
      22  #if !HAVE_DECL_TCA_ACT_FLAGS
      23  enum { TCA_ACT_FLAGS = 7 };
      24  #endif
      25  #if !HAVE_DECL_TCA_ACT_HW_STATS
      26  enum { TCA_ACT_HW_STATS = 8 };
      27  #endif
      28  #if !HAVE_DECL_TCA_ACT_USED_HW_STATS
      29  enum { TCA_ACT_USED_HW_STATS = 9 };
      30  #endif
      31  #if !HAVE_DECL_TCA_ACT_IN_HW_COUNT
      32  enum { TCA_ACT_IN_HW_COUNT = 10 };
      33  #endif
      34  
      35  static const unsigned int hdrlen = sizeof(struct tcamsg);
      36  
      37  static void
      38  init_tcamsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
      39  {
      40  	SET_STRUCT(struct nlmsghdr, nlh,
      41  		.nlmsg_len = msg_len,
      42  		.nlmsg_type = RTM_GETACTION,
      43  		.nlmsg_flags = NLM_F_DUMP
      44  	);
      45  
      46  	struct tcamsg *const msg = NLMSG_DATA(nlh);
      47  	SET_STRUCT(struct tcamsg, msg,
      48  		.tca_family = AF_INET
      49  	);
      50  }
      51  
      52  static void
      53  print_tcamsg(const unsigned int msg_len)
      54  {
      55  	printf("{nlmsg_len=%u, nlmsg_type=" XLAT_FMT ", nlmsg_flags=" XLAT_FMT
      56  	       ", nlmsg_seq=0, nlmsg_pid=0}, {tca_family=" XLAT_FMT "}",
      57  	       msg_len, XLAT_ARGS(RTM_GETACTION), XLAT_ARGS(NLM_F_DUMP),
      58  	       XLAT_ARGS(AF_INET));
      59  }
      60  
      61  static void
      62  init_tcamsg_tab(struct nlmsghdr *const nlh, const unsigned int msg_len)
      63  {
      64  	init_tcamsg(nlh, msg_len);
      65  
      66  	struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
      67  	SET_STRUCT(struct nlattr, nla,
      68  		.nla_len = msg_len - NLMSG_SPACE(hdrlen),
      69  		.nla_type = 1,
      70  	);
      71  }
      72  
      73  static void
      74  print_tcamsg_tab(const unsigned int msg_len)
      75  {
      76  	print_tcamsg(msg_len);
      77  	printf(", [{nla_len=%u, nla_type=" XLAT_FMT "}",
      78  	       msg_len - NLMSG_SPACE(hdrlen), XLAT_ARGS(TCA_ROOT_TAB));
      79  }
      80  
      81  static uint16_t tab_idx;
      82  
      83  static void
      84  init_tcamsg_tab_item(struct nlmsghdr *const nlh, const unsigned int msg_len)
      85  {
      86  	init_tcamsg_tab(nlh, msg_len);
      87  
      88  	struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen + NLA_HDRLEN);
      89  	SET_STRUCT(struct nlattr, nla,
      90  		.nla_len = msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN,
      91  		.nla_type = tab_idx,
      92  	);
      93  }
      94  
      95  static void
      96  print_tcamsg_tab_item(const unsigned int msg_len)
      97  {
      98  	print_tcamsg_tab(msg_len);
      99  	printf(", [{nla_len=%u, nla_type=%#x}",
     100  	       msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN, tab_idx);
     101  }
     102  
     103  int
     104  main(void)
     105  {
     106  	skip_if_unavailable("/proc/self/fd/");
     107  
     108  	const int fd = create_nl_socket(NETLINK_ROUTE);
     109  	const unsigned int hdrlen = sizeof(struct tcamsg);
     110  	void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + 4);
     111  
     112  	static char pattern[4096];
     113  	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
     114  
     115  	/* Invalid */
     116  	static const unsigned int nla_invalid[] = { 6, 0xffff & NLA_TYPE_MASK };
     117  	for (size_t i = 0; i < ARRAY_SIZE(nla_invalid); i++) {
     118  		char nla_type_str[256];
     119  		sprintf(nla_type_str, "%#x" NRAW(" /* TCA_ROOT_??? */"),
     120  			nla_invalid[i]);
     121  		TEST_NLATTR_(fd, nlh0, hdrlen,
     122  			     init_tcamsg, print_tcamsg,
     123  			     nla_invalid[i], nla_type_str,
     124  			     21, pattern, 21,
     125  			     print_quoted_hex(pattern, 21));
     126  	}
     127  
     128  	/* Default decoder */
     129  	static const struct {
     130  		unsigned int val;
     131  		const char *str;
     132  	} nla_default[] = {
     133  		{ ARG_XLAT_KNOWN(0, "TCA_ROOT_UNSPEC") },
     134  	};
     135  	for (size_t i = 0; i < ARRAY_SIZE(nla_default); i++) {
     136  		TEST_NLATTR_(fd, nlh0, hdrlen,
     137  			     init_tcamsg, print_tcamsg,
     138  			     nla_default[i].val, nla_default[i].str,
     139  			     17, pattern, 17,
     140  			     print_quoted_hex(pattern, 17));
     141  	}
     142  
     143  	/* TCA_ROOT_TAB: Invalid */
     144  	TEST_NLATTR_(fd, nlh0, hdrlen,
     145  		     init_tcamsg, print_tcamsg,
     146  		     TCA_ROOT_TAB, XLAT_KNOWN(0x1, "TCA_ROOT_TAB"),
     147  		     3, &pattern, 3,
     148  		     printf("\"\\x61\\x62\\x63\""));
     149  
     150  	/* TCA_ROOT_TAB: item: invalid */
     151  	TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     152  			    init_tcamsg_tab, print_tcamsg_tab,
     153  			    0, "0", 3, &pattern, 3, 1,
     154  			    printf("\"\\x61\\x62\\x63\""));
     155  	tab_idx++;
     156  
     157  	/* TCA_ROOT_TAB: item: default decoder */
     158  	static const struct {
     159  		unsigned int val;
     160  		const char *str;
     161  	} tcaa_default[] = {
     162  		{ ARG_XLAT_KNOWN(0, "TCA_ACT_UNSPEC") },
     163  		{ ARG_XLAT_KNOWN(0x2, "TCA_ACT_OPTIONS") },
     164  		{ ARG_XLAT_KNOWN(0x5, "TCA_ACT_PAD") },
     165  		{ ARG_XLAT_KNOWN(0x6, "TCA_ACT_COOKIE") },
     166  		{ 11, "0xb" NRAW(" /* TCA_ACT_??? */") },
     167  	};
     168  	for (size_t i = 0; i < ARRAY_SIZE(tcaa_default); i++) {
     169  		TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     170  				    init_tcamsg_tab_item, print_tcamsg_tab_item,
     171  				    tcaa_default[i].val, tcaa_default[i].str,
     172  				    17, pattern, 17, 2,
     173  				    print_quoted_hex(pattern, 17));
     174  		tab_idx++;
     175  	}
     176  
     177  	/* TCA_ROOT_TAB: item: TCA_ACT_KIND */
     178  	TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     179  			    init_tcamsg_tab_item, print_tcamsg_tab_item,
     180  			    TCA_ACT_KIND, XLAT_KNOWN(0x1, "TCA_ACT_KIND"),
     181  			    21, pattern, 21, 2,
     182  			    print_quoted_cstring(pattern, 22));
     183  	tab_idx++;
     184  
     185  	static const char kind[] = "Hello\tthere";
     186  	TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     187  			    init_tcamsg_tab_item, print_tcamsg_tab_item,
     188  			    TCA_ACT_KIND, XLAT_KNOWN(0x1, "TCA_ACT_KIND"),
     189  			    sizeof(kind), kind, sizeof(kind), 2,
     190  			    print_quoted_string(kind));
     191  	tab_idx++;
     192  
     193  	/* TCA_ROOT_TAB: item: TCA_ACT_INDEX */
     194  	static uint32_t idx = 0xdeadc0de;
     195  	TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     196  			    init_tcamsg_tab_item, print_tcamsg_tab_item,
     197  			    TCA_ACT_INDEX, XLAT_KNOWN(0x3, "TCA_ACT_INDEX"),
     198  			    sizeof(idx), &idx, sizeof(idx), 2,
     199  			    printf("%u", idx));
     200  	tab_idx++;
     201  
     202  	/* TCA_ROOT_TAB: item: TCA_ACT_FLAGS */
     203  	static uint32_t flags = 0xfacebeff;
     204  	TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     205  			    init_tcamsg_tab_item, print_tcamsg_tab_item,
     206  			    TCA_ACT_FLAGS, XLAT_KNOWN(0x7, "TCA_ACT_FLAGS"),
     207  			    sizeof(flags), &flags, sizeof(flags), 2,
     208  			    printf(XLAT_FMT, XLAT_SEL(0xfacebeff,
     209  				   "TCA_ACT_FLAGS_NO_PERCPU_STATS|"
     210  				   "TCA_ACT_FLAGS_SKIP_HW|"
     211  				   "TCA_ACT_FLAGS_SKIP_SW|0xfacebef8")));
     212  	tab_idx++;
     213  
     214  	/* TCA_ROOT_TAB: item: TCA_ACT_HW_STATS, TCA_ACT_USED_HW_STATS */
     215  	static const struct strval32 nla_hw_st[] = {
     216  		{ ARG_XLAT_KNOWN(0x8, "TCA_ACT_HW_STATS") },
     217  		{ ARG_XLAT_KNOWN(0x9, "TCA_ACT_USED_HW_STATS") },
     218  	};
     219  
     220  	static uint32_t hw_st = 0xfacebeef;
     221  	for (size_t i = 0; i < ARRAY_SIZE(nla_hw_st); i++) {
     222  		TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     223  				    init_tcamsg_tab_item, print_tcamsg_tab_item,
     224  				    nla_hw_st[i].val, nla_hw_st[i].str,
     225  				    sizeof(hw_st), &hw_st, sizeof(hw_st), 2,
     226  				    printf(XLAT_FMT, XLAT_SEL(0xfacebeef,
     227  					   "TCA_ACT_HW_STATS_IMMEDIATE|"
     228  					   "TCA_ACT_HW_STATS_DELAYED|"
     229  					   "0xfacebeec")));
     230  		tab_idx++;
     231  	}
     232  
     233  	/* TCA_ROOT_TAB: item: TCA_ACT_IN_HW_COUNT */
     234  	static uint32_t hw_count = 0xdeadface;
     235  	TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     236  			    init_tcamsg_tab_item, print_tcamsg_tab_item,
     237  			    TCA_ACT_IN_HW_COUNT,
     238  			    XLAT_KNOWN(0xa, "TCA_ACT_IN_HW_COUNT"),
     239  			    sizeof(hw_count), &hw_count, sizeof(hw_count), 2,
     240  			    printf("%u", hw_count));
     241  
     242  	/* TCA_ROOT_FLAGS */
     243  	static const struct strval32 root_flags[] = {
     244  		{ ARG_STR(0) },
     245  		{ ARG_XLAT_KNOWN(0x1, "TCA_ACT_FLAG_LARGE_DUMP_ON") },
     246  		{ ARG_XLAT_KNOWN(0x3, "TCA_ACT_FLAG_LARGE_DUMP_ON|"
     247  				      "TCA_ACT_FLAG_TERSE_DUMP") },
     248  		{ ARG_XLAT_KNOWN(0xcafebeef, "TCA_ACT_FLAG_LARGE_DUMP_ON|"
     249  					     "TCA_ACT_FLAG_TERSE_DUMP|"
     250  					     "0xcafebeec") },
     251  		{ ARG_XLAT_UNKNOWN(0xbadc0dec, "TCA_ACT_FLAG_???") },
     252  	};
     253  
     254  	for (size_t i = 0; i < ARRAY_SIZE(root_flags); i++) {
     255  		TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
     256  			     TCA_ROOT_FLAGS, XLAT_KNOWN(0x2, "TCA_ROOT_FLAGS"),
     257  			     4, &root_flags[i].val, 4,
     258  			     printf("%s", root_flags[i].str));
     259  	}
     260  
     261  	/* TCA_ROOT_COUNT */
     262  	static const uint32_t cnt_vals[] = { 0, 1, 0xbac0ded };
     263  
     264  	for (size_t i = 0; i < ARRAY_SIZE(cnt_vals); i++) {
     265  		TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
     266  			     TCA_ROOT_COUNT, XLAT_KNOWN(0x3, "TCA_ROOT_COUNT"),
     267  			     4, &cnt_vals[i], 4,
     268  			     printf("%u", cnt_vals[i]));
     269  	}
     270  
     271  	/* TCA_ROOT_TIME_DELTA */
     272  	static const struct strval32 time_deltas[] = {
     273  		{ 0,		"0" },
     274  		{ 1,		"1" NRAW(" /* 0.001 s */") },
     275  		{ 10,		"10" NRAW(" /* 0.010 s */") },
     276  		{ 100,		"100" NRAW(" /* 0.100 s */") },
     277  		{ 999,		"999" NRAW(" /* 0.999 s */") },
     278  		{ 1000,		"1000" NRAW(" /* 1.000 s */") },
     279  		{ 1001,		"1001" NRAW(" /* 1.001 s */") },
     280  		{ 1010,		"1010" NRAW(" /* 1.010 s */") },
     281  		{ 0xfeedface,	"4277009102" NRAW(" /* 4277009.102 s */") },
     282  	};
     283  
     284  	for (size_t i = 0; i < ARRAY_SIZE(time_deltas); i++) {
     285  		TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
     286  			     TCA_ROOT_TIME_DELTA,
     287  			     XLAT_KNOWN(0x4, "TCA_ROOT_TIME_DELTA"),
     288  			     4, &time_deltas[i].val, 4,
     289  			     printf("%s", time_deltas[i].str));
     290  	}
     291  
     292  	static const struct strval64 time_deltas64[] = {
     293  		{ 0,		"0" },
     294  		{ 1,		"1" NRAW(" /* 0.001 s */") },
     295  		{ 10,		"10" NRAW(" /* 0.010 s */") },
     296  		{ 100,		"100" NRAW(" /* 0.100 s */") },
     297  		{ 999,		"999" NRAW(" /* 0.999 s */") },
     298  		{ 1000,		"1000" NRAW(" /* 1.000 s */") },
     299  		{ 1001,		"1001" NRAW(" /* 1.001 s */") },
     300  		{ 1010,		"1010" NRAW(" /* 1.010 s */") },
     301  		{ 0xfeedface,	"4277009102" NRAW(" /* 4277009.102 s */") },
     302  		{ 0xbadfacedeadc0ded, "13465671548708589037"
     303  				      NRAW(" /* 13465671548708589.037 s */") },
     304  	};
     305  
     306  	for (size_t i = 0; i < ARRAY_SIZE(time_deltas64); i++) {
     307  		TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
     308  			     TCA_ROOT_TIME_DELTA,
     309  			     XLAT_KNOWN(0x4, "TCA_ROOT_TIME_DELTA"),
     310  			     8, &time_deltas64[i].val, 8,
     311  			     printf("%s", time_deltas64[i].str));
     312  	}
     313  
     314  	/* TCA_ROOT_EXT_WARN_MSG */
     315  	static const char msg[] = "Hello\tthere";
     316  	TEST_NLATTR_(fd, nlh0, hdrlen, init_tcamsg, print_tcamsg,
     317  		     TCA_ROOT_EXT_WARN_MSG,
     318  		     XLAT_KNOWN(0x5, "TCA_ROOT_EXT_WARN_MSG"),
     319  		     sizeof(msg), msg, sizeof(msg),
     320  		     print_quoted_string(msg));
     321  
     322  	puts("+++ exited with 0 +++");
     323  	return 0;
     324  }