All of lore.kernel.org
 help / color / mirror / Atom feed
From: Okash Khawaja <osk@fb.com>
To: Jakub Kicinski <jakub.kicinski@netronome.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>,
	Martin KaFai Lau <kafai@fb.com>,
	Alexei Starovoitov <ast@kernel.org>, Yonghong Song <yhs@fb.com>,
	Quentin Monnet <quentin.monnet@netronome.com>,
	"David S. Miller" <davem@davemloft.net>, <netdev@vger.kernel.org>,
	<kernel-team@fb.com>, <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH bpf-next v2 2/3] bpf: btf: add btf print functionality
Date: Wed, 4 Jul 2018 17:31:07 +0100	[thread overview]
Message-ID: <20180704163106.GA2200@w1t1fb> (raw)
In-Reply-To: <20180703152331.151d1c4b@cakuba.netronome.com>

hi,

On Tue, Jul 03, 2018 at 03:23:31PM -0700, Jakub Kicinski wrote:
> On Tue, 3 Jul 2018 22:46:00 +0100, Okash Khawaja wrote:
> > On Mon, Jul 02, 2018 at 10:06:59PM -0700, Jakub Kicinski wrote:
> > > On Mon, 2 Jul 2018 11:39:15 -0700, Okash Khawaja wrote:  
> > > > +#define BITS_PER_BYTE_MASK (BITS_PER_BYTE - 1)
> > > > +#define BITS_PER_BYTE_MASKED(bits) ((bits) & BITS_PER_BYTE_MASK)  
> > > 
> > > Perhaps it's just me but BIT_OFFSET or BIT_COUNT as a name of this macro
> > > would make it more obvious to parse in the code below.  
> > I don't mind either. However these macro names are also used inside
> > kernel for same purpose. For sake of consistency, I'd recommend we keep
> > them :)
> 
> Ugh, okay :)
> 
> > > > +	} print_num;
> > > > +
> > > > +	total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
> > > > +	data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
> > > > +	bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
> > > > +	bits_to_copy = bits + bit_offset;
> > > > +	bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
> > > > +
> > > > +	print_num.u64_num = 0;
> > > > +	memcpy(&print_num.u64_num, data, bytes_to_copy);  
> > > 
> > > This scheme is unlikely to work on big endian machines...  
> > Can you give an example how?
> 
> On BE:
> 
> Input:         [0x01, 0x82]
> Bit length:    15
> Bytes to copy:  2
> bit_offset:     0
> upper_bits:     7
> 
> print_num.u64_num = 0;
> # [0, 0, 0, 0,   0, 0, 0, 0]
> 
> memcpy(&print_num.u64_num, data, bytes_to_copy);  
> # [0x01, 0x82, 0, 0,   0, 0, 0, 0]
> 
> mask = (1 << upper_bits) - 1;
> # mask = 0x7f
> 
> print_num.u8_nums[bytes_to_copy - 1] &= mask;
> # [0x01, 0x02, 0, 0,   0, 0, 0, 0]
> 
> printf("0x%llx", print_num.u64_num);
> # 0x0102000000000000 AKA 72620543991349248
> # expected:
> # 0x0102             AKA 258
> 
> Am I missing something?
yes you're right, good catch! i'll fix this. thanks vrey much :)

> 
> > > > +	upper_bits = BITS_PER_BYTE_MASKED(bits_to_copy);
> > > > +	if (upper_bits) {
> > > > +		uint8_t mask = (1 << upper_bits) - 1;
> > > > +
> > > > +		print_num.u8_nums[bytes_to_copy - 1] &= mask;
> > > > +	}
> > > > +
> > > > +	print_num.u64_num >>= bit_offset;
> > > > +
> > > > +	if (is_plain_text)
> > > > +		jsonw_printf(jw, "0x%llx", print_num.u64_num);
> > > > +	else
> > > > +		jsonw_printf(jw, "%llu", print_num.u64_num);
> > > > +}
> > > > +
> > > > +static int btf_dumper_int(const struct btf_type *t, uint8_t bit_offset,
> > > > +			  const void *data, json_writer_t *jw,
> > > > +			  bool is_plain_text)
> > > > +{
> > > > +	uint32_t *int_type = (uint32_t *)(t + 1);
> > > > +	uint32_t bits = BTF_INT_BITS(*int_type);
> > > > +	int ret = 0;
> > > > +
> > > > +	/* if this is bit field */
> > > > +	if (bit_offset || BTF_INT_OFFSET(*int_type) ||
> > > > +	    BITS_PER_BYTE_MASKED(bits)) {
> > > > +		btf_dumper_int_bits(*int_type, bit_offset, data, jw,
> > > > +				    is_plain_text);
> > > > +		return ret;
> > > > +	}
> > > > +
> > > > +	switch (BTF_INT_ENCODING(*int_type)) {
> > > > +	case 0:
> > > > +		if (BTF_INT_BITS(*int_type) == 64)
> > > > +			jsonw_printf(jw, "%lu", *((uint64_t *)data));
> > > > +		else if (BTF_INT_BITS(*int_type) == 32)
> > > > +			jsonw_printf(jw, "%u", *((uint32_t *)data));
> > > > +		else if (BTF_INT_BITS(*int_type) == 16)
> > > > +			jsonw_printf(jw, "%hu", *((uint16_t *)data));
> > > > +		else if (BTF_INT_BITS(*int_type) == 8)
> > > > +			jsonw_printf(jw, "%hhu", *((uint8_t *)data));
> > > > +		else
> > > > +			btf_dumper_int_bits(*int_type, bit_offset, data, jw,
> > > > +					    is_plain_text);
> > > > +		break;
> > > > +	case BTF_INT_SIGNED:
> > > > +		if (BTF_INT_BITS(*int_type) == 64)
> > > > +			jsonw_printf(jw, "%ld", *((int64_t *)data));
> > > > +		else if (BTF_INT_BITS(*int_type) == 32)
> > > > +			jsonw_printf(jw, "%d", *((int32_t *)data));
> > > > +		else if (BTF_INT_BITS(*int_type) ==  16)  
> > > 
> > > Please drop the double space.  Both for 16 where it makes no sense and
> > > for 8 where it's marginally useful but not really.
> > >   
> > > > +			jsonw_printf(jw, "%hd", *((int16_t *)data));
> > > > +		else if (BTF_INT_BITS(*int_type) ==  8)
> > > > +			jsonw_printf(jw, "%hhd", *((int8_t *)data));
> > > > +		else
> > > > +			btf_dumper_int_bits(*int_type, bit_offset, data, jw,
> > > > +					    is_plain_text);
> > > > +		break;
> > > > +	case BTF_INT_CHAR:
> > > > +		if (*((char *)data) == '\0')
> > > > +			jsonw_null(jw);  
> > > 
> > > Mm.. I don't think 0 char is equivalent to null.  
> > Yes, thanks. Will fix.
> > 
> > >   
> > > > +		else if (isprint(*((char *)data)))
> > > > +			jsonw_printf(jw, "\"%c\"", *((char *)data));  
> > > 
> > > This looks very suspicious.  So if I see a "6" for a char field it's
> > > either a 6 ('\u0006') or a 54 ('6')...  
> > It will always be 54. May be I missed your point. Could you explain why
> > it would be other than 54?
> 
> Ah, I think I missed that %c is in quotes...
> 
> > > > +		else
> > > > +			if (is_plain_text)
> > > > +				jsonw_printf(jw, "%hhx", *((char *)data));
> 
> This seems to be missing a "0x" prefix?
yes it does. will add 0x.

> 
> > > > +			else
> > > > +				jsonw_printf(jw, "%hhd", *((char *)data));  
> > > 
> > > ... I think you need to always print a string, and express it as
> > > \u00%02hhx for non-printable.  
> > Okay that makes sense
> 
> Yeah, IDK, char can be used as a byte as well as a string.  In eBPF
> it may actually be more likely to just be used as a raw byte buffer...
> Either way I think it may be nice to keep it consistent, at least for
> the JSON output could we do either always ints or always characters?
yes, makes sense. i'll keep them always characters.

  parent reply	other threads:[~2018-07-04 16:31 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-02 18:39 [PATCH bpf-next v2 0/3] bpf: btf: print bpftool map data with btf Okash Khawaja
2018-07-02 18:39 ` [PATCH bpf-next v2 2/3] bpf: btf: add btf print functionality Okash Khawaja
2018-07-03  5:06   ` Jakub Kicinski
2018-07-03 21:46     ` Okash Khawaja
2018-07-03 22:23       ` Jakub Kicinski
2018-07-03 22:38         ` Jakub Kicinski
2018-07-03 23:33           ` Martin KaFai Lau
2018-07-07 13:30             ` Okash Khawaja
2018-07-07 18:49               ` Jakub Kicinski
2018-07-04 16:31         ` Okash Khawaja [this message]
2018-07-02 18:39 ` [PATCH bpf-next v2 3/3] bpf: btf: print map dump and lookup with btf info Okash Khawaja
2018-07-03  5:29   ` Jakub Kicinski
     [not found] ` <20180702191324.476855192@fb.com>
2018-07-03  4:07   ` [PATCH bpf-next v2 1/3] bpf: btf: export btf types and name by offset from lib Jakub Kicinski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180704163106.GA2200@w1t1fb \
    --to=osk@fb.com \
    --cc=ast@kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=jakub.kicinski@netronome.com \
    --cc=kafai@fb.com \
    --cc=kernel-team@fb.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=quentin.monnet@netronome.com \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.