[PATCH v3 1/8] rtnl_link: decode ifinfomsg netlink attributes
JingPiao Chen
chenjingpiao at gmail.com
Sun Aug 27 17:44:36 UTC 2017
* configure.ac (AC_CHECK_HEADERS): Add linux/if_link.h.
(AC_CHECK_TYPES): Check for
struct rtnl_link_stats64 in <linux/if_link.h>.
(AC_CHECK_MEMBERS): Check for
rx_nohandler field in struct rtnl_link_stats/rtnl_link_stats64.
* rtnl_link.c: Include <linux/if_link.h>.
(decode_rtnl_link_stats, decode_rtnl_link_ifmap,
decode_rtnl_link_stats64): New functions.
(ifinfomsg_nla_decoders): New array.
(decode_ifinfomsg): Use it.
---
configure.ac | 7 +++
rtnl_link.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 189 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 4522b2e..f09ae5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -382,6 +382,7 @@ AC_CHECK_HEADERS(m4_normalize([
linux/genetlink.h
linux/hiddev.h
linux/if_addr.h
+ linux/if_link.h
linux/ip_vs.h
linux/ipc.h
linux/mmtimer.h
@@ -452,6 +453,12 @@ AC_CHECK_TYPES(m4_normalize([
struct rtvia
]),,, [#include <linux/rtnetlink.h>])
+AC_CHECK_TYPES([struct rtnl_link_stats64],,, [#include <linux/if_link.h>])
+AC_CHECK_MEMBERS(m4_normalize([
+ struct rtnl_link_stats.rx_nohandler,
+ struct rtnl_link_stats64.rx_nohandler
+]),,, [#include <linux/if_link.h>])
+
AC_CHECK_TYPES([struct statfs], [
AC_CHECK_MEMBERS(m4_normalize([
struct statfs.f_frsize,
diff --git a/rtnl_link.c b/rtnl_link.c
index 18897f3..227a452 100644
--- a/rtnl_link.c
+++ b/rtnl_link.c
@@ -33,10 +33,189 @@
#include "print_fields.h"
#include "netlink.h"
+#ifdef HAVE_LINUX_IF_LINK_H
+# include <linux/if_link.h>
+#endif
#include <linux/rtnetlink.h>
#include "xlat/rtnl_link_attrs.h"
+static bool
+decode_rtnl_link_stats(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const unsigned int len,
+ const void *const opaque_data)
+{
+ struct rtnl_link_stats st;
+ const unsigned int min_size =
+ offsetofend(struct rtnl_link_stats, tx_compressed);
+ const unsigned int size = len < sizeof(st) ? min_size : sizeof(st);
+
+ if (len < min_size)
+ return false;
+ else if (!umoven_or_printaddr(tcp, addr, size, &st)) {
+ PRINT_FIELD_U("{", st, rx_packets);
+ PRINT_FIELD_U(", ", st, tx_packets);
+ PRINT_FIELD_U(", ", st, rx_bytes);
+ PRINT_FIELD_U(", ", st, tx_bytes);
+ PRINT_FIELD_U(", ", st, rx_errors);
+ PRINT_FIELD_U(", ", st, tx_errors);
+ PRINT_FIELD_U(", ", st, rx_dropped);
+ PRINT_FIELD_U(", ", st, tx_dropped);
+ PRINT_FIELD_U(", ", st, multicast);
+ PRINT_FIELD_U(", ", st, collisions);
+
+ PRINT_FIELD_U(", ", st, rx_length_errors);
+ PRINT_FIELD_U(", ", st, rx_over_errors);
+ PRINT_FIELD_U(", ", st, rx_crc_errors);
+ PRINT_FIELD_U(", ", st, rx_frame_errors);
+ PRINT_FIELD_U(", ", st, rx_fifo_errors);
+ PRINT_FIELD_U(", ", st, rx_missed_errors);
+
+ PRINT_FIELD_U(", ", st, tx_aborted_errors);
+ PRINT_FIELD_U(", ", st, tx_carrier_errors);
+ PRINT_FIELD_U(", ", st, tx_fifo_errors);
+ PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
+ PRINT_FIELD_U(", ", st, tx_window_errors);
+
+ PRINT_FIELD_U(", ", st, rx_compressed);
+ PRINT_FIELD_U(", ", st, tx_compressed);
+#ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER
+ if (len >= sizeof(st))
+ PRINT_FIELD_U(", ", st, rx_nohandler);
+#endif
+ tprints("}");
+ }
+
+ return true;
+}
+
+static bool
+decode_rtnl_link_ifmap(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const unsigned int len,
+ const void *const opaque_data)
+{
+ struct rtnl_link_ifmap map;
+ const unsigned int sizeof_ifmap =
+ offsetofend(struct rtnl_link_ifmap, port);
+
+ if (len < sizeof_ifmap)
+ return false;
+ else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) {
+ PRINT_FIELD_X("{", map, mem_start);
+ PRINT_FIELD_X(", ", map, mem_end);
+ PRINT_FIELD_X(", ", map, base_addr);
+ PRINT_FIELD_U(", ", map, irq);
+ PRINT_FIELD_U(", ", map, dma);
+ PRINT_FIELD_U(", ", map, port);
+ tprints("}");
+ }
+
+ return true;
+}
+
+static bool
+decode_rtnl_link_stats64(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const unsigned int len,
+ const void *const opaque_data)
+{
+#ifdef HAVE_STRUCT_RTNL_LINK_STATS64
+ struct rtnl_link_stats64 st;
+ const unsigned int min_size =
+ offsetofend(struct rtnl_link_stats64, tx_compressed);
+ const unsigned int size = len < sizeof(st) ? min_size : sizeof(st);
+
+ if (len < min_size)
+ return false;
+ else if (!umoven_or_printaddr(tcp, addr, size, &st)) {
+ PRINT_FIELD_U("{", st, rx_packets);
+ PRINT_FIELD_U(", ", st, tx_packets);
+ PRINT_FIELD_U(", ", st, rx_bytes);
+ PRINT_FIELD_U(", ", st, tx_bytes);
+ PRINT_FIELD_U(", ", st, rx_errors);
+ PRINT_FIELD_U(", ", st, tx_errors);
+ PRINT_FIELD_U(", ", st, rx_dropped);
+ PRINT_FIELD_U(", ", st, tx_dropped);
+ PRINT_FIELD_U(", ", st, multicast);
+ PRINT_FIELD_U(", ", st, collisions);
+
+ PRINT_FIELD_U(", ", st, rx_length_errors);
+ PRINT_FIELD_U(", ", st, rx_over_errors);
+ PRINT_FIELD_U(", ", st, rx_crc_errors);
+ PRINT_FIELD_U(", ", st, rx_frame_errors);
+ PRINT_FIELD_U(", ", st, rx_fifo_errors);
+ PRINT_FIELD_U(", ", st, rx_missed_errors);
+
+ PRINT_FIELD_U(", ", st, tx_aborted_errors);
+ PRINT_FIELD_U(", ", st, tx_carrier_errors);
+ PRINT_FIELD_U(", ", st, tx_fifo_errors);
+ PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
+ PRINT_FIELD_U(", ", st, tx_window_errors);
+
+ PRINT_FIELD_U(", ", st, rx_compressed);
+ PRINT_FIELD_U(", ", st, tx_compressed);
+#ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER
+ if (len >= sizeof(st))
+ PRINT_FIELD_U(", ", st, rx_nohandler);
+#endif
+ tprints("}");
+ }
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+static const nla_decoder_t ifinfomsg_nla_decoders[] = {
+ [IFLA_ADDRESS] = NULL, /* unimplemented */
+ [IFLA_BROADCAST] = NULL, /* unimplemented */
+ [IFLA_IFNAME] = decode_nla_str,
+ [IFLA_MTU] = decode_nla_u32,
+ [IFLA_LINK] = decode_nla_u32,
+ [IFLA_QDISC] = decode_nla_str,
+ [IFLA_STATS] = decode_rtnl_link_stats,
+ [IFLA_COST] = NULL, /* unused */
+ [IFLA_PRIORITY] = NULL, /* unused */
+ [IFLA_MASTER] = decode_nla_u32,
+ [IFLA_WIRELESS] = NULL, /* unimplemented */
+ [IFLA_PROTINFO] = NULL, /* unimplemented */
+ [IFLA_TXQLEN] = decode_nla_u32,
+ [IFLA_MAP] = decode_rtnl_link_ifmap,
+ [IFLA_WEIGHT] = decode_nla_u32,
+ [IFLA_OPERSTATE] = decode_nla_u8,
+ [IFLA_LINKMODE] = decode_nla_u8,
+ [IFLA_LINKINFO] = NULL, /* unimplemented */
+ [IFLA_NET_NS_PID] = decode_nla_u32,
+ [IFLA_IFALIAS] = decode_nla_str,
+ [IFLA_NUM_VF] = decode_nla_u32,
+ [IFLA_VFINFO_LIST] = NULL, /* unimplemented */
+ [IFLA_STATS64] = decode_rtnl_link_stats64,
+ [IFLA_VF_PORTS] = NULL, /* unimplemented */
+ [IFLA_PORT_SELF] = NULL, /* unimplemented */
+ [IFLA_AF_SPEC] = NULL, /* unimplemented */
+ [IFLA_GROUP] = decode_nla_u32,
+ [IFLA_NET_NS_FD] = decode_nla_u32,
+ [IFLA_EXT_MASK] = decode_nla_u32,
+ [IFLA_PROMISCUITY] = decode_nla_u32,
+ [IFLA_NUM_TX_QUEUES] = decode_nla_u32,
+ [IFLA_NUM_RX_QUEUES] = decode_nla_u32,
+ [IFLA_CARRIER] = decode_nla_u8,
+ [IFLA_PHYS_PORT_ID] = NULL, /* default parser */
+ [IFLA_CARRIER_CHANGES] = decode_nla_u32,
+ [IFLA_PHYS_SWITCH_ID] = NULL, /* default parser */
+ [IFLA_LINK_NETNSID] = decode_nla_s32,
+ [IFLA_PHYS_PORT_NAME] = decode_nla_str,
+ [IFLA_PROTO_DOWN] = decode_nla_u8,
+ [IFLA_GSO_MAX_SEGS] = decode_nla_u32,
+ [IFLA_GSO_MAX_SIZE] = decode_nla_u32,
+ [IFLA_PAD] = NULL,
+ [IFLA_XDP] = NULL, /* unimplemented */
+ [IFLA_EVENT] = decode_nla_u32
+};
+
DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)
{
struct ifinfomsg ifinfo = { .ifi_family = family };
@@ -66,6 +245,8 @@ DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)
if (decode_nla && len > offset) {
tprints(", ");
decode_nlattr(tcp, addr + offset, len - offset,
- rtnl_link_attrs, "IFLA_???", NULL, 0, NULL);
+ rtnl_link_attrs, "IFLA_???",
+ ifinfomsg_nla_decoders,
+ ARRAY_SIZE(ifinfomsg_nla_decoders), NULL);
}
}
--
2.7.4
More information about the Strace-devel
mailing list