Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: buf: resolve issues with fixed size network buffer pool #68413

Merged

Conversation

kderda
Copy link
Contributor

@kderda kderda commented Feb 1, 2024

This PR fixes issue discussed in #66870 (fix proposed by @jhedberg) with new test case.
Additionally, it resolves an additional issue where fixed buffer would set it's size to requested length instead of the actual size (with additional check in existing unit test) .

Fixes #66870

Copy link
Member

@jhedberg jhedberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good, thanks! Do take a look at my inline comments, however.

Also, I think this might justify a mention in doc/releases/migration-guide-3.6.rst since it's a change to a public API (even though custom out-of-tree net_buf_pool implementations are likely quite rare)

subsys/net/buf.c Outdated
@@ -203,6 +203,7 @@ static const struct net_buf_data_cb net_buf_heap_cb = {

const struct net_buf_data_alloc net_buf_heap_alloc = {
.cb = &net_buf_heap_cb,
.max_alloc_size = K_HEAP_MEM_POOL_SIZE
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: add a , to the end. It's not needed now, but if this ever gets extended with another struct member, then you just need to add another line instead of also modifying this existing one.

I was also thinking that maybe 0 could have been used to mean "unrestricted" but then again since we do have this define for the system heap I guess we can use that here. Actually, now that I think about it, maybe we anyway want 0 to have this special meaning, since that would give some backwards compatibility to any existing definitions of custom allocators, since any not explicitly initialized struct members are 0 by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my mind, using 0 as the special value is great. I was thinking about using a max value but it could confuse someone. The solution with holding an initial value seemed better but was still a lie as in theory this value could be interpreted as maximum contiguous memory block. With 0 it is also easy to use in net_buf_append_bytes().

@kderda kderda force-pushed the net_buf_fixed_fixed branch from d2133b9 to d344db6 Compare February 1, 2024 19:15
@zephyrbot zephyrbot added the Release Notes To be mentioned in the release notes label Feb 1, 2024
@kderda
Copy link
Contributor Author

kderda commented Feb 1, 2024

@jhedberg I have added a point to the migration guide

@kderda kderda requested a review from jhedberg February 1, 2024 19:19
jhedberg
jhedberg previously approved these changes Feb 2, 2024
@jhedberg
Copy link
Member

jhedberg commented Feb 2, 2024

@konradderda please fix the CI failure:

/__w/zephyr/zephyr/subsys/net/buf.c:681:15: error: variable 'pool' is uninitialized when used here [-Werror,-Wuninitialized]
                        max_size = pool->alloc->max_alloc_size;
                                   ^~~~
/__w/zephyr/zephyr/subsys/net/buf.c:676:29: note: initialize the variable 'pool' to silence this warning
                        struct net_buf_pool *pool;
                                                 ^
                                                  = NULL
1 error generated.

@kderda
Copy link
Contributor Author

kderda commented Feb 2, 2024

@jhedberg fixed

@kderda kderda requested a review from jhedberg February 2, 2024 13:05
@kderda
Copy link
Contributor Author

kderda commented Feb 2, 2024

It seems that I need also to align few test cases for net_pkt as few asserts assume the requested size, not the actual one.

From change 47eb592c28b9e7dfbdd25fedbf07a528ad240084 net_buf structures
allocated from pools defined with NET_BUF_POOL_FIXED_DEFINE() will keep
their `size` member set to the actual fixed size and not requested
size like before.

For this set of tests NET_BUF_POOL_FIXED_DEFINE() for several test
cases. These tests check the several values based on a fact that the
network buffer's size was set to the requested size.

This commit changes definition of the buffer pool to
NET_BUF_POOL_FIXED_DEFINE() in order to satisfy these expectations.
This change does not impact the tests themselves.

Signed-off-by: Konrad Derda <[email protected]>
Previously, there was no way to determine maximum number of bytes
that can be allocated using only net_buf structure. This commit
introduces such field.

Moreover, this commit fixes an issue where allocation of less than
maximum number of bytes from a fixed buffer pool would set buffer's
size to this number instead of the whole buffer size.

Signed-off-by: Konrad Derda <[email protected]>
This commit introduces two changes:
- veryfing fixed buffer's size and length after allocation to existing
  test case
- new test veryfing appending bytes to a network buffer from a fixed
  size pool

Signed-off-by: Konrad Derda <[email protected]>
Add point about moving maximum allocation size from fixed buffer pool's
internal structure to a common one.

Signed-off-by: Konrad Derda <[email protected]>
@kderda kderda force-pushed the net_buf_fixed_fixed branch from 2169b76 to f42b836 Compare February 5, 2024 12:22
@kderda
Copy link
Contributor Author

kderda commented Feb 5, 2024

@jhedberg I have added a commit that changes failing tests so they use VAR pool instead of FIXED as it does not impact the test cases. I moved it to the beginning of commits in this PR so Zephyr build and tests will pass at every commit.

@henrikbrixandersen
Copy link
Member

@jhedberg Is this targeting v3.6.0? If so, please add it as milestone.

@jhedberg jhedberg added this to the v3.6.0 milestone Feb 6, 2024
@jhedberg
Copy link
Member

jhedberg commented Feb 6, 2024

@jhedberg Is this targeting v3.6.0? If so, please add it as milestone.

Done. It's fixing an issue with allocations from fixed-size buffer pools, so I think it'd be good to get it merged. There's also the appropriate bug report reference.

@henrikbrixandersen henrikbrixandersen merged commit e46fbd9 into zephyrproject-rtos:main Feb 6, 2024
21 checks passed
@M1cha
Copy link
Contributor

M1cha commented Oct 22, 2024

@konradderda

Moreover, this commit fixes an issue where allocation of less than
maximum number of bytes from a fixed buffer pool would set buffer's
size to this number instead of the whole buffer size.

But why is that in issue? If I allocate 2 bytes, I expect the allocation to be 2 bytes, no matter how large the internal(fixed) buffer is.

@M1cha
Copy link
Contributor

M1cha commented Oct 23, 2024

Mh I just learned about the implementation of net_buf_alloc. That function does not take a length parameter and simplfy forwards to net_buf_alloc_fixed, so that function would be unsafe to call, if you don't know the pool type.

While that kinda makes sense and would fit your expectations, the weird part is, that net_buf_alloc_fixed internally calls the generic API net_buf_alloc_len, but with the fixed chunk length. So a fixed-specific function uses a generic function to do the allocation and by doing so has to pass a parameter that's conceptionally not needed.

I always thought, net_buf_alloc would just allocate a buffer without data, because that's actually supported by calling net_buf_alloc_len with a size of 0.

To me this looks like the allocator API went through some changes and that these functions implement the old behavior for compatibility reasons.

@kderda
Copy link
Contributor Author

kderda commented Oct 23, 2024

@M1cha please do not edit my comments...

It makes sense to have more memory allocated then requested for example in case of network packets when someone write fields one by one (addresses, options etc.) using Zephyr's net_pkt_* API it would end up with a chain of small buffer fragments instead of larger one.

Before this PR such behavior led to:

  1. Unnecessary number of memory allocation
  2. Slower packet processing
  3. Higher memory consumption - any packet write would allocate a new fixed buffer.

You can checkout the commit before this PR was merged and play with unit tests and printk() or GDB to better understand the change. Other than that if you would like discuss something related to the design of implementation of buffers please open a new issue instead.

@M1cha
Copy link
Contributor

M1cha commented Oct 23, 2024

@konradderda

@M1cha please do not edit my comments...

Sorry about that, I don't know how that happened. I wanted to restore your comment, but currently can't see your original comment at all. Do you know what happened to it?

It makes sense to have more memory allocated then requested for example in case of network packets when someone write fields one by one (addresses, options etc.) using Zephyr's net_pkt_* API it would end up with a chain of small buffer fragments instead of larger one.

Before this PR such behavior led to:

1. Unnecessary number of memory allocation

2. Slower packet processing

3. Higher memory consumption - any packet write would allocate a new fixed buffer.

You can checkout the commit before this PR was merged and play with unit tests and printk() or GDB to better understand the change. Other than that if you would like discuss something related to the design of implementation of buffers please open a new issue instead.

I didn't know about that use-case. That makes sense, thx.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Networking Buffers net_buf/net_buf_simple API & implementation area: Networking Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

net_buf_append_bytes() usage may cause a failed assertion
7 participants