(root)/
strace-6.5/
src/
rtnl_stats.c
       1  /*
       2   * Copyright (c) 2018-2021 Eugene Syromyatnikov <evgsyr@gmail.com>
       3   * All rights reserved.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   */
       7  
       8  #include "defs.h"
       9  #include "netlink_route.h"
      10  #include "nlattr.h"
      11  #include "print_fields.h"
      12  
      13  #include "netlink.h"
      14  
      15  #include <netinet/in.h>
      16  
      17  #include <linux/if_bonding.h>
      18  #include <linux/if_bridge.h>
      19  #include <linux/if_link.h>
      20  #include <linux/mpls.h>
      21  #include <linux/rtnetlink.h>
      22  
      23  #include "xlat/ifstats_af_spec_mpls_attrs.h"
      24  #include "xlat/ifstats_attrs.h"
      25  #include "xlat/ifstats_attr_flags.h"
      26  #include "xlat/ifstats_offload_attrs.h"
      27  #include "xlat/ifstats_xstats_bond_attrs.h"
      28  #include "xlat/ifstats_xstats_bond_3ad_attrs.h"
      29  #include "xlat/ifstats_xstats_bridge_attrs.h"
      30  #include "xlat/ifstats_xstats_bridge_mcast_indices.h"
      31  #include "xlat/ifstats_xstats_type_attrs.h"
      32  #include "xlat/nl_bridge_vlan_flags.h"
      33  
      34  #define XLAT_MACROS_ONLY
      35  # include "xlat/addrfams.h" /* AF_MPLS */
      36  #undef XLAT_MACROS_ONLY
      37  
      38  static bool
      39  decode_ifstats_link_xstats_bridge_vlan(struct tcb *const tcp,
      40  				       const kernel_ulong_t addr,
      41  				       const unsigned int len,
      42  				       const void *const opaque_data)
      43  {
      44  	struct bridge_vlan_xstats st;
      45  
      46  	if (len < sizeof(st))
      47  		return false;
      48  
      49  	if (umove_or_printaddr(tcp, addr, &st))
      50  		return true;
      51  
      52  	tprint_struct_begin();
      53  	PRINT_FIELD_U(st, rx_bytes);
      54  	tprint_struct_next();
      55  	PRINT_FIELD_U(st, rx_packets);
      56  	tprint_struct_next();
      57  	PRINT_FIELD_U(st, tx_bytes);
      58  	tprint_struct_next();
      59  	PRINT_FIELD_U(st, tx_packets);
      60  	tprint_struct_next();
      61  	PRINT_FIELD_U(st, vid);
      62  	tprint_struct_next();
      63  	PRINT_FIELD_FLAGS(st, flags, nl_bridge_vlan_flags,
      64  			  "BRIDGE_VLAN_INFO_???");
      65  	if (st.pad2) {
      66  		tprint_struct_next();
      67  		PRINT_FIELD_X(st, pad2);
      68  	}
      69  	tprint_struct_end();
      70  
      71  	if (len > sizeof(st)) {
      72  		tprint_array_next();
      73  		printstr_ex(tcp, addr + sizeof(st), len - sizeof(st),
      74  			    QUOTE_FORCE_HEX);
      75  	}
      76  
      77  	return true;
      78  }
      79  
      80  static bool
      81  decode_ifstats_link_xstats_bridge_mcast(struct tcb *const tcp,
      82  					const kernel_ulong_t addr,
      83  					const unsigned int len,
      84  					const void *const opaque_data)
      85  {
      86  	struct br_mcast_stats st;
      87  
      88  	if (len < sizeof(st))
      89  		return false;
      90  
      91  	if (umove_or_printaddr(tcp, addr, &st))
      92  		return true;
      93  
      94  #define PRINT_FIELD_MCAST_ARRAY_(where_, field_)			\
      95  	PRINT_FIELD_ARRAY_INDEXED(where_, field_,			\
      96  				  tcp, print_uint_array_member,		\
      97  				  ifstats_xstats_bridge_mcast_indices,	\
      98  				  NULL);
      99  
     100  	tprint_struct_begin();
     101  	PRINT_FIELD_MCAST_ARRAY_(st, igmp_v1queries);
     102  	tprint_struct_next();
     103  	PRINT_FIELD_MCAST_ARRAY_(st, igmp_v2queries);
     104  	tprint_struct_next();
     105  	PRINT_FIELD_MCAST_ARRAY_(st, igmp_v3queries);
     106  	tprint_struct_next();
     107  	PRINT_FIELD_MCAST_ARRAY_(st, igmp_leaves);
     108  	tprint_struct_next();
     109  	PRINT_FIELD_MCAST_ARRAY_(st, igmp_v1reports);
     110  	tprint_struct_next();
     111  	PRINT_FIELD_MCAST_ARRAY_(st, igmp_v2reports);
     112  	tprint_struct_next();
     113  	PRINT_FIELD_MCAST_ARRAY_(st, igmp_v3reports);
     114  	tprint_struct_next();
     115  	PRINT_FIELD_U(st, igmp_parse_errors);
     116  	tprint_struct_next();
     117  	PRINT_FIELD_MCAST_ARRAY_(st, mld_v1queries);
     118  	tprint_struct_next();
     119  	PRINT_FIELD_MCAST_ARRAY_(st, mld_v2queries);
     120  	tprint_struct_next();
     121  	PRINT_FIELD_MCAST_ARRAY_(st, mld_leaves);
     122  	tprint_struct_next();
     123  	PRINT_FIELD_MCAST_ARRAY_(st, mld_v1reports);
     124  	tprint_struct_next();
     125  	PRINT_FIELD_MCAST_ARRAY_(st, mld_v2reports);
     126  	tprint_struct_next();
     127  	PRINT_FIELD_U(st, mld_parse_errors);
     128  	tprint_struct_next();
     129  	PRINT_FIELD_MCAST_ARRAY_(st, mcast_bytes);
     130  	tprint_struct_next();
     131  	PRINT_FIELD_MCAST_ARRAY_(st, mcast_packets);
     132  	tprint_struct_end();
     133  
     134  #undef PRINT_FIELD_MCAST_ARRAY_
     135  
     136  	if (len > sizeof(st)) {
     137  		tprint_array_next();
     138  		printstr_ex(tcp, addr + sizeof(st), len - sizeof(st),
     139  			    QUOTE_FORCE_HEX);
     140  	}
     141  
     142  	return true;
     143  }
     144  
     145  static bool
     146  decode_ifstats_link_xstats_bridge_stp(struct tcb *const tcp,
     147  				      const kernel_ulong_t addr,
     148  				      const unsigned int len,
     149  				      const void *const opaque_data)
     150  {
     151  	struct bridge_stp_xstats st;
     152  
     153  	if (len < sizeof(st))
     154  		return false;
     155  
     156  	if (umove_or_printaddr(tcp, addr, &st))
     157  		return true;
     158  
     159  	tprint_struct_begin();
     160  	PRINT_FIELD_U(st, transition_blk);
     161  	tprint_struct_next();
     162  	PRINT_FIELD_U(st, transition_fwd);
     163  	tprint_struct_next();
     164  	PRINT_FIELD_U(st, rx_bpdu);
     165  	tprint_struct_next();
     166  	PRINT_FIELD_U(st, tx_bpdu);
     167  	tprint_struct_next();
     168  	PRINT_FIELD_U(st, rx_tcn);
     169  	tprint_struct_next();
     170  	PRINT_FIELD_U(st, tx_tcn);
     171  	tprint_struct_end();
     172  
     173  	if (len > sizeof(st)) {
     174  		tprint_array_next();
     175  		printstr_ex(tcp, addr + sizeof(st), len - sizeof(st),
     176  			    QUOTE_FORCE_HEX);
     177  	}
     178  
     179  	return true;
     180  }
     181  
     182  static const nla_decoder_t ifstats_xstats_bridge_decoders[] = {
     183  	[BRIDGE_XSTATS_UNSPEC]	= NULL,
     184  	[BRIDGE_XSTATS_VLAN]	= decode_ifstats_link_xstats_bridge_vlan,
     185  	[BRIDGE_XSTATS_MCAST]	= decode_ifstats_link_xstats_bridge_mcast,
     186  	[BRIDGE_XSTATS_PAD]	= NULL,
     187  	[BRIDGE_XSTATS_STP]	= decode_ifstats_link_xstats_bridge_stp,
     188  };
     189  
     190  static bool
     191  decode_ifstats_link_xstats_bridge(struct tcb *const tcp,
     192  				  const kernel_ulong_t addr,
     193  				  const unsigned int len,
     194  				  const void *const opaque_data)
     195  {
     196  	decode_nlattr(tcp, addr, len, ifstats_xstats_bridge_attrs,
     197  		      "BRIDGE_XSTATS_???",
     198  		      ARRSZ_PAIR(ifstats_xstats_bridge_decoders),
     199  		      opaque_data);
     200  
     201  	return true;
     202  }
     203  
     204  static const nla_decoder_t ifstats_xstats_bond_3ad_decoders[] = {
     205  	[BOND_3AD_STAT_LACPDU_RX]		= decode_nla_u64,
     206  	[BOND_3AD_STAT_LACPDU_TX]		= decode_nla_u64,
     207  	[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]	= decode_nla_u64,
     208  	[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]	= decode_nla_u64,
     209  	[BOND_3AD_STAT_MARKER_RX]		= decode_nla_u64,
     210  	[BOND_3AD_STAT_MARKER_TX]		= decode_nla_u64,
     211  	[BOND_3AD_STAT_MARKER_RESP_RX]		= decode_nla_u64,
     212  	[BOND_3AD_STAT_MARKER_RESP_TX]		= decode_nla_u64,
     213  	[BOND_3AD_STAT_MARKER_UNKNOWN_RX]	= decode_nla_u64,
     214  	[BOND_3AD_STAT_PAD]			= NULL,
     215  };
     216  
     217  static bool
     218  decode_ifstats_link_xstats_bond_3ad(struct tcb *const tcp,
     219  				    const kernel_ulong_t addr,
     220  				    const unsigned int len,
     221  				    const void *const opaque_data)
     222  {
     223  	decode_nlattr(tcp, addr, len, ifstats_xstats_bond_3ad_attrs,
     224  		      "BOND_XSTATS_???",
     225  		      ARRSZ_PAIR(ifstats_xstats_bond_3ad_decoders),
     226  		      opaque_data);
     227  
     228  	return true;
     229  }
     230  
     231  static const nla_decoder_t ifstats_xstats_bond_decoders[] = {
     232  	[BOND_XSTATS_UNSPEC]	= NULL,
     233  	[BOND_XSTATS_3AD]	= decode_ifstats_link_xstats_bond_3ad,
     234  };
     235  
     236  static bool
     237  decode_ifstats_link_xstats_bond(struct tcb *const tcp,
     238  				const kernel_ulong_t addr,
     239  				const unsigned int len,
     240  				const void *const opaque_data)
     241  {
     242  	decode_nlattr(tcp, addr, len, ifstats_xstats_bond_attrs,
     243  		      "BOND_XSTATS_???",
     244  		      ARRSZ_PAIR(ifstats_xstats_bond_decoders),
     245  		      opaque_data);
     246  
     247  	return true;
     248  }
     249  
     250  static const nla_decoder_t ifstats_xstats_decoders[] = {
     251  	[LINK_XSTATS_TYPE_UNSPEC]	= NULL,
     252  	[LINK_XSTATS_TYPE_BRIDGE]	= decode_ifstats_link_xstats_bridge,
     253  	[LINK_XSTATS_TYPE_BOND]		= decode_ifstats_link_xstats_bond,
     254  };
     255  
     256  static bool
     257  decode_ifstats_link_xstats(struct tcb *const tcp,
     258  			   const kernel_ulong_t addr,
     259  			   const unsigned int len,
     260  			   const void *const opaque_data)
     261  {
     262  	decode_nlattr(tcp, addr, len, ifstats_xstats_type_attrs,
     263  		      "LINK_XSTATS_TYPE_???",
     264  		      ARRSZ_PAIR(ifstats_xstats_decoders),
     265  		      opaque_data);
     266  
     267  	return true;
     268  }
     269  
     270  static const nla_decoder_t ifstats_offload_xstats_decoders[] = {
     271  	[IFLA_OFFLOAD_XSTATS_UNSPEC]	= NULL,
     272  	[IFLA_OFFLOAD_XSTATS_CPU_HIT]	= decode_nla_rtnl_link_stats64,
     273  };
     274  
     275  static bool
     276  decode_ifstats_link_offload_xstats(struct tcb *const tcp,
     277  				   const kernel_ulong_t addr,
     278  				   const unsigned int len,
     279  				   const void *const opaque_data)
     280  {
     281  	decode_nlattr(tcp, addr, len, ifstats_offload_attrs,
     282  		      "IFLA_OFFLOAD_XSTATS_???",
     283  		      ARRSZ_PAIR(ifstats_offload_xstats_decoders),
     284  		      opaque_data);
     285  
     286  	return true;
     287  }
     288  
     289  static bool
     290  decode_ifstats_af_mpls_stats_link(struct tcb *const tcp,
     291  				  const kernel_ulong_t addr,
     292  				  const unsigned int len,
     293  				  const void *const opaque_data)
     294  {
     295  	struct mpls_link_stats st;
     296  
     297  	if (len < sizeof(st))
     298  		return false;
     299  
     300  	if (umove_or_printaddr(tcp, addr, &st))
     301  		return true;
     302  
     303  	tprint_struct_begin();
     304  	PRINT_FIELD_U(st, rx_packets);
     305  	tprint_struct_next();
     306  	PRINT_FIELD_U(st, tx_packets);
     307  	tprint_struct_next();
     308  	PRINT_FIELD_U(st, rx_bytes);
     309  	tprint_struct_next();
     310  	PRINT_FIELD_U(st, tx_bytes);
     311  	tprint_struct_next();
     312  	PRINT_FIELD_U(st, rx_errors);
     313  	tprint_struct_next();
     314  	PRINT_FIELD_U(st, tx_errors);
     315  	tprint_struct_next();
     316  	PRINT_FIELD_U(st, rx_dropped);
     317  	tprint_struct_next();
     318  	PRINT_FIELD_U(st, tx_dropped);
     319  	tprint_struct_next();
     320  	PRINT_FIELD_U(st, rx_noroute);
     321  	tprint_struct_end();
     322  
     323  	if (len > sizeof(st)) {
     324  		tprint_array_next();
     325  		printstr_ex(tcp, addr + sizeof(st), len - sizeof(st),
     326  			    QUOTE_FORCE_HEX);
     327  	}
     328  
     329  	return true;
     330  }
     331  
     332  static const nla_decoder_t ifla_stats_mpls_nla_decoders[] = {
     333  	[MPLS_STATS_UNSPEC]	= NULL,
     334  	[MPLS_STATS_LINK]	= decode_ifstats_af_mpls_stats_link,
     335  };
     336  
     337  static bool
     338  decode_ifstats_af(struct tcb *const tcp,
     339  		  const kernel_ulong_t addr,
     340  		  const unsigned int len,
     341  		  const void *const opaque_data)
     342  {
     343  	static const struct af_spec_decoder_desc protos[] = {
     344  		{ AF_MPLS, ifstats_af_spec_mpls_attrs, "MPLS_STATS_???",
     345  		  ARRSZ_PAIR(ifla_stats_mpls_nla_decoders) },
     346  	};
     347  
     348  	decode_nla_af_spec(tcp, addr, len,
     349  			   (uintptr_t) opaque_data, ARRSZ_PAIR(protos));
     350  
     351  	return true;
     352  }
     353  
     354  static bool
     355  decode_ifstats_af_spec(struct tcb *const tcp,
     356  		       const kernel_ulong_t addr,
     357  		       const unsigned int len,
     358  		       const void *const opaque_data)
     359  {
     360  	static const nla_decoder_t af_spec_decoder = &decode_ifstats_af;
     361  
     362  	decode_nlattr(tcp, addr, len, addrfams, "AF_???",
     363  		      &af_spec_decoder, 0, 0);
     364  
     365  	return true;
     366  }
     367  
     368  
     369  static const nla_decoder_t ifstatsmsg_nla_decoders[] = {
     370  	[IFLA_STATS_UNSPEC]			= NULL,
     371  	[IFLA_STATS_LINK_64]			= decode_nla_rtnl_link_stats64,
     372  	[IFLA_STATS_LINK_XSTATS]		= decode_ifstats_link_xstats,
     373  	[IFLA_STATS_LINK_XSTATS_SLAVE]		= decode_ifstats_link_xstats,
     374  	[IFLA_STATS_LINK_OFFLOAD_XSTATS]	= decode_ifstats_link_offload_xstats,
     375  	[IFLA_STATS_AF_SPEC]			= decode_ifstats_af_spec,
     376  };
     377  
     378  DECL_NETLINK_ROUTE_DECODER(decode_ifstatsmsg)
     379  {
     380  	struct if_stats_msg ifstats = { .family = family };
     381  	size_t offset = sizeof(ifstats.family);
     382  	bool decode_nla = false;
     383  
     384  	tprint_struct_begin();
     385  	PRINT_FIELD_XVAL(ifstats, family, addrfams, "AF_???");
     386  	tprint_struct_next();
     387  
     388  	if (len >= sizeof(ifstats)) {
     389  		if (!umoven_or_printaddr(tcp, addr + offset,
     390  					 sizeof(ifstats) - offset,
     391  					 (char *) &ifstats + offset)) {
     392  			if (ifstats.pad1) {
     393  				PRINT_FIELD_X(ifstats, pad1);
     394  				tprint_struct_next();
     395  			}
     396  			if (ifstats.pad2) {
     397  				PRINT_FIELD_X(ifstats, pad2);
     398  				tprint_struct_next();
     399  			}
     400  			PRINT_FIELD_IFINDEX(ifstats, ifindex);
     401  			tprint_struct_next();
     402  			PRINT_FIELD_FLAGS(ifstats, filter_mask,
     403  					  ifstats_attr_flags,
     404  					  "1<<IFLA_STATS_???");
     405  			decode_nla = true;
     406  		}
     407  	} else {
     408  		tprint_more_data_follows();
     409  	}
     410  	tprint_struct_end();
     411  
     412  	offset = NLMSG_ALIGN(sizeof(ifstats));
     413  	if (decode_nla && len > offset) {
     414  		tprint_array_next();
     415  		decode_nlattr(tcp, addr + offset, len - offset,
     416  			      ifstats_attrs, "IFLA_STATS_???",
     417  			      ARRSZ_PAIR(ifstatsmsg_nla_decoders), &ifstats);
     418  	}
     419  }