[PATCH v4 08/10] netlink: decode AF_INET diag attributes

Dmitry V. Levin ldv at altlinux.org
Sun Jun 25 23:31:04 UTC 2017


On Tue, Jun 20, 2017 at 05:23:53PM +0800, JingPiao Chen wrote:
> * netlink_sock_diag.c: Include  <linux/sock_diag.h>.
> (inet_decoders): New array.
> (decode_inet_diag_msg): Use it.
> * linux/inet_diag.h (inet_diag_meminfo, tcpvegas_info,
> tcp_dctcp_info, tcp_bbr_info): New structures.
> * linux/sock_diag.h (SK_MEMINFO_VARS): New macro.

As this implements decoding of inet_diag_msg attributes only, let's
reflect this fact in the commit message, i.e. replace "diag attributes"
with "inet_diag_msg attributes".

> ---
>  linux/inet_diag.h   |  34 ++++++++++++++
>  linux/sock_diag.h   |   2 +
>  netlink_sock_diag.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 161 insertions(+), 1 deletion(-)
> 
> diff --git a/linux/inet_diag.h b/linux/inet_diag.h
> index e1df3bb..24302db 100644
> --- a/linux/inet_diag.h
> +++ b/linux/inet_diag.h
> @@ -76,4 +76,38 @@ enum {
>  	INET_DIAG_BBRINFO,
>  };
>  
> +/* INET_DIAG_MEM */
> +struct inet_diag_meminfo {
> +	uint32_t idiag_rmem;
> +	uint32_t idiag_wmem;
> +	uint32_t idiag_fmem;
> +	uint32_t idiag_tmem;
> +};
> +
> +/* INET_DIAG_VEGASINFO */
> +struct tcpvegas_info {
> +	uint32_t tcpv_enabled;
> +	uint32_t tcpv_rttcnt;
> +	uint32_t tcpv_rtt;
> +	uint32_t tcpv_minrtt;
> +};
> +
> +/* INET_DIAG_DCTCPINFO */
> +struct tcp_dctcp_info {
> +	uint16_t dctcp_enabled;
> +	uint16_t dctcp_ce_state;
> +	uint32_t dctcp_alpha;
> +	uint32_t dctcp_ab_ecn;
> +	uint32_t dctcp_ab_tot;
> +};
> +
> +/* INET_DIAG_BBRINFO */
> +struct tcp_bbr_info {
> +	uint32_t bbr_bw_lo;
> +	uint32_t bbr_bw_hi;
> +	uint32_t bbr_min_rtt;
> +	uint32_t bbr_pacing_gain;
> +	uint32_t bbr_cwnd_gain;
> +};
> +
>  #endif /* !STRACE_LINUX_INET_DIAG_H */
> diff --git a/linux/sock_diag.h b/linux/sock_diag.h
> index 83daf35..f69c385 100644
> --- a/linux/sock_diag.h
> +++ b/linux/sock_diag.h
> @@ -4,6 +4,8 @@
>  #define SOCK_DIAG_BY_FAMILY 20
>  #define SOCK_DESTROY 21
>  
> +#define SK_MEMINFO_VARS		9
> +
>  struct sock_diag_req {
>  	uint8_t	sdiag_family;
>  	uint8_t	sdiag_protocol;
> diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c
> index 57c2439..dab0f1a 100644
> --- a/netlink_sock_diag.c
> +++ b/netlink_sock_diag.c
> @@ -39,6 +39,7 @@
>  #ifdef AF_SMC
>  # include <linux/smc_diag.h>
>  #endif
> +#include <linux/sock_diag.h>
>  #include <linux/unix_diag.h>
>  
>  #include "xlat/inet_diag_attrs.h"
> @@ -112,6 +113,31 @@ decode_unix_diag_req(struct tcb *const tcp,
>  	tprints("}");
>  }
>  
> +static bool
> +print_meminfo(struct tcb *tcp, void *elem_buf,
> +	      size_t elem_size, void *opaque_data)
> +{
> +	tprintf("%" PRIu32, *(uint32_t *) elem_buf);
> +
> +	return true;
> +}
> +
> +static bool
> +decode_meminfo(struct tcb *tcp, kernel_ulong_t addr,
> +	       kernel_ulong_t len, void *const opaque_data)
> +{
> +	uint32_t mem;
> +	int nmemb = len / sizeof(mem);
> +

If len < sizeof(mem), nmemb is set to 0.
Invoking print_array with nmemb == 0 would print [] that means an empty array,
which is not the case here.

I suggest to "return false" instead.

> +	if (nmemb > SK_MEMINFO_VARS)
> +		nmemb = SK_MEMINFO_VARS;
> +
> +	print_array(tcp, addr, nmemb, &mem, sizeof(mem),
> +		    umoven_or_printaddr, print_meminfo, 0);
> +
> +	return true;
> +}
> +
>  static void
>  decode_unix_diag_msg(struct tcb *const tcp,
>  		     const struct nlmsghdr *const nlmsghdr,
> @@ -442,6 +468,104 @@ decode_inet_diag_req(struct tcb *const tcp,
>  					       family, addr, len);
>  }
>  
> +static bool
> +decode_inet_diag_meminfo(struct tcb *tcp, kernel_ulong_t addr,
> +			 kernel_ulong_t len, void *const opaque_data)
> +{
> +	struct inet_diag_meminfo minfo;
> +
> +	if (len < sizeof(minfo))
> +		return false;
> +	if (umove_or_printaddr(tcp, addr, &minfo))
> +		return true;
> +
> +	tprintf("{idiag_rmem=%" PRIu32 ", idiag_wmem=%" PRIu32
> +		", idiag_fmem=%" PRIu32 ", idiag_tmem=%" PRIu32 "}",
> +		minfo.idiag_rmem, minfo.idiag_wmem,
> +		minfo.idiag_fmem, minfo.idiag_tmem);
> +
> +	return true;
> +}
> +
> +static bool
> +decode_tcpvegas_info(struct tcb *tcp, kernel_ulong_t addr,
> +		     kernel_ulong_t len, void *const opaque_data)
> +{
> +	struct tcpvegas_info vegas;
> +
> +	if (len < sizeof(vegas))
> +		return false;
> +	if (umove_or_printaddr(tcp, addr, &vegas))
> +		return true;
> +
> +	tprintf("{tcpv_enabled=%" PRIu32 ", tcpv_rttcnt=%" PRIu32
> +		", tcpv_rtt=%" PRIu32 ", tcpv_minrtt=%" PRIu32 "}",
> +		vegas.tcpv_enabled, vegas.tcpv_rttcnt,
> +		vegas.tcpv_rtt, vegas.tcpv_minrtt);
> +
> +	return true;
> +}
> +
> +static bool
> +decode_tcp_dctcp_info(struct tcb *tcp, kernel_ulong_t addr,
> +		      kernel_ulong_t len, void *const opaque_data)
> +{
> +	struct tcp_dctcp_info dctcp;
> +
> +	if (len < sizeof(dctcp))
> +		return false;
> +	if (umove_or_printaddr(tcp, addr, &dctcp))
> +		return true;
> +
> +	tprintf("{dctcp_enabled=%" PRIu16 ", dctcp_ce_state=%" PRIu16
> +		", dctcp_alpha=%" PRIu32 ", dctcp_ab_ecn=%" PRIu32
> +		", dctcp_ab_tot=%" PRIu32 "}",
> +		dctcp.dctcp_enabled, dctcp.dctcp_ce_state,
> +		dctcp.dctcp_alpha, dctcp.dctcp_ab_ecn,
> +		dctcp.dctcp_ab_tot);
> +
> +	return true;
> +}
> +
> +static bool
> +decode_tcp_bbr_info(struct tcb *tcp, kernel_ulong_t addr,
> +		    kernel_ulong_t len, void *const opaque_data)
> +{
> +	struct tcp_bbr_info bbr;
> +
> +	if (len < sizeof(bbr))
> +		return false;
> +	if (umove_or_printaddr(tcp, addr, &bbr))
> +		return true;
> +
> +	tprintf("{bbr_bw_lo=%#" PRIx32 ", bbr_bw_hi=%#" PRIx32
> +		", bbr_min_rtt=%" PRIu32 ", bbr_pacing_gain=%" PRIu32
> +		", bbr_cwnd_gain=%" PRIu32 "}",
> +		bbr.bbr_bw_lo, bbr.bbr_bw_hi, bbr.bbr_min_rtt,
> +		bbr.bbr_pacing_gain, bbr.bbr_cwnd_gain);
> +
> +	return true;
> +}
> +
> +static nla_decoder_t inet_decoders[] = {

static const nla_decoder_t.  You can add const qualifiers in many more
places of this file, but here it is important because it signals the
compiler that the whole array is constant.

btw, there are going to be other inet decoders, so please make the name
more specific, e.g. inet_diag_msg_nla_decoders.

> +	[INET_DIAG_MEMINFO]	= decode_inet_diag_meminfo,
> +	[INET_DIAG_INFO]	= NULL,			/* unimplemented */
> +	[INET_DIAG_VEGASINFO]	= decode_tcpvegas_info,
> +	[INET_DIAG_CONG]	= decode_nla_str,
> +	[INET_DIAG_TOS]		= decode_nla_u8,
> +	[INET_DIAG_TCLASS]	= decode_nla_u8,
> +	[INET_DIAG_SKMEMINFO]	= decode_meminfo,
> +	[INET_DIAG_SHUTDOWN]	= decode_nla_u8,
> +	[INET_DIAG_DCTCPINFO]	= decode_tcp_dctcp_info,
> +	[INET_DIAG_PROTOCOL]	= decode_nla_u8,
> +	[INET_DIAG_SKV6ONLY]	= decode_nla_u8,
> +	[INET_DIAG_LOCALS]	= NULL,			/* unimplemented */
> +	[INET_DIAG_PEERS]	= NULL,			/* unimplemented */
> +	[INET_DIAG_PAD]		= NULL,
> +	[INET_DIAG_MARK]	= decode_nla_u32,
> +	[INET_DIAG_BBRINFO]	= decode_tcp_bbr_info
> +};
> +
>  static void
>  decode_inet_diag_msg(struct tcb *const tcp,
>  		     const struct nlmsghdr *const nlmsghdr,

-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170626/0e95789c/attachment.bin>


More information about the Strace-devel mailing list