`Option<NonZeroUsize>` is guaranteed to have the same size as `usize`,
which is not guarnateed for `Result`. This is a minor optimization, but
also results in simpler code.
Some of these functions fail to compile when not inlined, so we should
be explicit.
Before deciding on this approach I tried various ways of making all
these functions #[inline(never)] to save instructions but I ran into
blockers:
- These functions currently return Result, which is a structure. This is
not permitted in BPF.
- I tried inventing a newtype that is a #[repr(transparent)] wrapper of
u16, and having these functions return that; however it seems that
even if the object code is legal, the verifier will reject such
functions because the BTF (if present, and it was in my local
experiments) would indicate that the return is a structure.
- I tried having these functions return a plain u16 where 0 means error,
but the verifier still rejected the BTF because the receiver (even if
made into &self) is considered a structure, and forbidden.
We can eventually overcome these problems by "lying" in our BTF once
support for it matures in the bpf-linker repo (e.g. Option<NonZeroU16>
should be perfectly legal as it is guaranteed to be word-sized), but we
aren't there yet, and this is the safest thing we can do for now.
- Remove `TagLenValue`; this type has a single method, which is now a
function.
- Remove generics from `TagLenValue::write` (now `write`). The tag is
always `u8`, and the value is always a sequence of bytes.
- Replace slicing operations which can panic with calls to `get` which
explicit check bounds.
Before this change:
```
error[E0382]: use of moved value: `no_copy`
--> test/integration-ebpf/src/log.rs:35:9
|
33 | let no_copy = NoCopy {};
| ------- move occurs because `no_copy` has type `NoCopy`, which does not implement the `Copy` trait
34 |
35 | debug!(&ctx, "{:x}", no_copy.consume());
| ^^^^^^^^^^^^^^^^^^^^^-------^---------^
| | | |
| | | `no_copy` moved due to this method call
| | use occurs due to use in closure
| value used here after move
|
note: `NoCopy::consume` takes ownership of the receiver `self`, which moves `no_copy`
--> test/integration-ebpf/src/log.rs:28:24
|
28 | fn consume(self) -> u64 {
| ^^^^
= note: this error originates in the macro `debug` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0382`.
error: could not compile `integration-ebpf` (bin "log") due to previous error
```
aya-log-ebpf-macros was failing to compile because it was referencing
a couple of `DisplayHint` variants that no longer exist. These were
removed in #599.
```
Compiling aya-log-ebpf-macros v0.1.0 (/home/robert/aya/aya-log-ebpf-macros)
error[E0599]: no variant or associated item named `Ipv4` found for enum `DisplayHint` in the current scope
--> aya-log-ebpf-macros/src/expand.rs:93:22
|
93 | DisplayHint::Ipv4 => parse_str("::aya_log_ebpf::macro_support::check_impl_ipv4"),
| ^^^^ variant or associated item not found in `DisplayHint`
error[E0599]: no variant or associated item named `Ipv6` found for enum `DisplayHint` in the current scope
--> aya-log-ebpf-macros/src/expand.rs:94:22
|
94 | DisplayHint::Ipv6 => parse_str("::aya_log_ebpf::macro_support::check_impl_ipv6"),
| ^^^^ variant or associated item not found in `DisplayHint`
For more information about this error, try `rustc --explain E0599`.
```
Having separate format hints and tokens per IP address family is
unnecessary, since they are represented by different types and we handle
format hints for each type separately. So we can just have one format
hint.
Also, we should be consistent with the format strings grammar in
Rust[0]. The `type` token, which is mapped to formatting traits, usually
consists of one letter[1] (and optional `?` for `Debug` trait, but that
doesn't matter for us). It shouldn't consist of multiple letters. Our
`:ipv4` and `:ipv6` tokens were clearly breaking that convention, so we
should rather switch to something with one letter - hence `:i`.
[0] https://doc.rust-lang.org/std/fmt/#syntax
[1] https://doc.rust-lang.org/std/fmt/#formatting-traits
- Replace all `#[repr(usize)]` with `#[repr(u8)]`; this saves
3*(sizeof(word)-1) bytes per log message.
- Encode payload length as u16 rather than usize; this saves
sizeof(word)-1 bytes per log message. This is safe because the maximum
size of a log message is less than (1 << 16 - 1).
This changes `level` to a require field in every log message. It was
already always present, but was treated as optional when reading.
Keeping the `Pod` implementations and optional dependency on aya in
aya-log-common breaks the clippy checks (which are made on the entire
workspace).
The reason is that when different crates inside the workspace have the
same dependency with different features, that dependency is built only
once with the sum of features needed by all crates. It's **not** being
built separately with different feature sets.
That's why, before this change, aya-log-common was built once for the
entire workspace with `userspace` feature enabled. That made importing
aya-log-ebpf inside integration-ebpf impossible. The aya-log-common
build, with `userspace` feature enabled, was pulling std as a
dependency. Therefore, importing aya-log-ebpf inside integration-ebpf
resulted in including std and errors like:
```
error[E0152]: found duplicate lang item `panic_impl`
--> test/integration-ebpf/src/log.rs:23:1
|
23 | fn panic(_info: &core::panic::PanicInfo) -> ! {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the lang item is first defined in crate `std` (which `aya` depends on)
```
This change fixes the problem by removing the `userspace` feature from
aya-log-common and moving the `Pod` implementations to aya-log.
Add `{:mac}` (for lower-case hex representation) and `{:MAC}` (for
upper-case hex representation) format hints for the `[u8; 6]` type,
which is the standard one in Linux to store physical addresses in.
Tested with: https://github.com/vadorovsky/aya-examples/tree/main/xdp-mac
Signed-off-by: Michal Rostecki <vadorovsky@gmail.com>
This change adds optional display hints:
* `{:x}`, `{:X}` - for hex representation of numbers
* `{:ipv4}`, `{:IPv4}` - for IPv4 addresses
* `{:ipv6}`, `{:IPv6}` - for IPv6 addresses
It also gets rid of dyn-fmt and instead comes with our own parser
implementation.
Tested on: https://github.com/vadorovsky/aya-examples/tree/main/tc
Signed-off-by: Michal Rostecki <vadorovsky@gmail.com>
This commit moves the aya-log projects from the subtree and adds them to
the main cargo workspace. It also brings the BPF crates into the
workspace and moves the macro crates up a level since they aren't BPF
code.
Miri was disabled for aya-bpf as the previous config wasn't actually
checking anything.
CI, clippy, fmt and release configurations have all been adjusted
appropriately.
CI was not properly running for other supported arches which was also
ixed here.
Signed-off-by: Dave Tucker <dave@dtucker.co.uk>