On Wed, Mar 05, 2025 at 03:31 PM +01, arthur@xxxxxxxxxxxxxxx wrote: > From: Arthur Fabre <afabre@xxxxxxxxxxxxxx> > > A (very limited) KV store to support storing KVs in the packet headroom, > with: > - 64 keys (0-63). > - 2, 4 or 8 byte values. > - O(1) lookup > - O(n) insertion > - A fixed 16 byte header. > > Values are stored ordered by key, immediately following the fixed > header. > > This could be extended in the future, for now it implements the smallest > possible API. The API intentionally uses u64 keys to not impose > restrictions on the implementation in the future. > > I picked 2¸ 4, and 8 bytes arbitrarily. We could also support 0 sized > values for use as flags. > A 16 byte value could be useful to store UUIDs and IPv6 addresses. > If we want more than 3 sizes, we can add a word to the header (for a > total of 24 bytes) to support 7 sizes. > > We could also allow users to set several consecutive keys in one > trait_set() call to support storing larger values. > > Implemented in the header file so functions are always inlinable. > > Signed-off-by: Arthur Fabre <afabre@xxxxxxxxxxxxxx> > --- [...] > +/** > + * trait_get() - Get a trait key. > + * @traits: Start of trait store area. > + * @key: The key to get. > + * @val: Where to put stored value. > + * @val_len: The length of val. > + * > + * Return: > + * * %>0 - Actual size of value. > + * * %-EINVAL - Key or length invalid. > + * * %-ENOENT - Key has not been set with trait_set() previously. > + * * %-ENOSPC - Val is not big enough to hold stored value. > + */ > +static __always_inline > +int trait_get(void *traits, u64 key, void *val, u64 val_len) Hmm. I think that passing void *val will bite us on big endian. Seems I can't pass an u64 * if you don't know the value size up front. For values under 8 bytes I would end up with bytes shifted to the left. No? Take u64 *val instead and copy it in at the right offset? > +{ > + if (!__trait_valid_key(key)) > + return -EINVAL; > + > + struct __trait_hdr h = *(struct __trait_hdr *)traits; > + > + /* Check key is set */ > + if (!((h.high & (1ull << key)) || (h.low & (1ull << key)))) > + return -ENOENT; > + > + /* Offset of value of this key */ > + int off = __trait_offset(h, key); > + > + /* Figure out our length */ > + int real_len = __trait_total_length(__trait_and(h, (1ull << key))); > + > + if (real_len > val_len) > + return -ENOSPC; > + > + memcpy(val, traits + off, real_len); > + return real_len; > +}