Skip to content

Conversation

@MarkWangChinese
Copy link
Contributor

change uint16_t as size_t to support large size of data.

The user case:
In USB, the net_buf is used. usb msc may transfer 64KB (65536) data in one net_buf. So the uint16_t can't handle 65536.

@MarkWangChinese MarkWangChinese marked this pull request as ready for review October 13, 2025 09:13
@zephyrbot zephyrbot added the area: Networking Buffers net_buf/net_buf_simple API & implementation label Oct 13, 2025
Copy link
Contributor

@pdgendt pdgendt left a comment

Choose a reason for hiding this comment

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

Please see https://github.com/zephyrproject-rtos/zephyr/pull/97440/files#r2425645621
Besides that, the following functions/structs need to be updated too:

uint16_t net_buf_simple_max_len(const struct net_buf_simple *buf);
struct net_buf_simple_state;
static inline void net_buf_simple_save(const struct net_buf_simple *buf,
				       struct net_buf_simple_state *state);
struct net_buf;

@pdgendt
Copy link
Contributor

pdgendt commented Oct 13, 2025

Make sure the tests in tests/lib/net_buf work with this new option, and that this is included in CI.

@MarkWangChinese MarkWangChinese force-pushed the feature/net_buf_large_size_support branch from 3a3a6a6 to 938fd0f Compare October 14, 2025 02:12
@zephyrbot zephyrbot added the area: Tests Issues related to a particular existing or missing test label Oct 14, 2025
@zephyrbot zephyrbot requested a review from nashif October 14, 2025 02:14
@MarkWangChinese
Copy link
Contributor Author

Make sure the tests in tests/lib/net_buf work with this new option, and that this is included in CI.

Tested tests\lib\net_buf\buf on one NXP platform (lpc55s69), the result is OK as follow. I tried to test tests\lib\net_buf\buf_simple too, but it can't be built successfully.

===================================================================
PROJECT EXECUTION SUCCESSFUL
*** Booting Zephyr OS build v4.2.0-5562-g3a3a6a6c7e65 ***
Running TESTSUITE net_buf_tests
===================================================================
START - test_net_buf_1
 PASS - test_net_buf_1 in 0.001 seconds
===================================================================
START - test_net_buf_2
 PASS - test_net_buf_2 in 0.001 seconds
===================================================================
START - test_net_buf_3
 PASS - test_net_buf_3 in 0.001 seconds
===================================================================
START - test_net_buf_4
 PASS - test_net_buf_4 in 0.001 seconds
===================================================================
START - test_net_buf_big_buf
 PASS - test_net_buf_big_buf in 0.001 seconds
===================================================================
START - test_net_buf_byte_order
 PASS - test_net_buf_byte_order in 0.001 seconds
===================================================================
START - test_net_buf_clone_no_ref_count
 PASS - test_net_buf_clone_no_ref_count in 0.001 seconds
===================================================================
START - test_net_buf_clone_ref_count
 PASS - test_net_buf_clone_ref_count in 0.001 seconds
===================================================================
START - test_net_buf_clone_reference_counted_zero_sized_buffer
 PASS - test_net_buf_clone_reference_counted_zero_sized_buffer in 0.001 seconds
===================================================================
START - test_net_buf_clone_user_data
 PASS - test_net_buf_clone_user_data in 0.001 seconds
===================================================================
START - test_net_buf_comparison
 PASS - test_net_buf_comparison in 0.001 seconds
===================================================================
START - test_net_buf_fixed_append
 PASS - test_net_buf_fixed_append in 0.001 seconds
===================================================================
START - test_net_buf_fixed_pool
 PASS - test_net_buf_fixed_pool in 0.001 seconds
===================================================================
START - test_net_buf_linearize
 PASS - test_net_buf_linearize in 0.001 seconds
===================================================================
START - test_net_buf_multi_frags
 PASS - test_net_buf_multi_frags in 0.001 seconds
===================================================================
START - test_net_buf_user_data
 PASS - test_net_buf_user_data in 0.001 seconds
===================================================================
START - test_net_buf_user_data_copy
 PASS - test_net_buf_user_data_copy in 0.001 seconds
===================================================================
START - test_net_buf_var_pool
 PASS - test_net_buf_var_pool in 0.001 seconds
===================================================================
START - test_net_buf_var_pool_aligned
 PASS - test_net_buf_var_pool_aligned in 0.001 seconds
===================================================================
TESTSUITE net_buf_tests succeeded

------ TESTSUITE SUMMARY START ------

SUITE PASS - 100.00% [net_buf_tests]: pass = 19, fail = 0, skip = 0, total = 19 duration = 0.019 seconds
 - PASS - [net_buf_tests.test_net_buf_1] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_2] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_3] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_4] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_big_buf] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_byte_order] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_clone_no_ref_count] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_clone_ref_count] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_clone_reference_counted_zero_sized_buffer] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_clone_user_data] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_comparison] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_fixed_append] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_fixed_pool] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_linearize] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_multi_frags] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_user_data] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_user_data_copy] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_var_pool] duration = 0.001 seconds
 - PASS - [net_buf_tests.test_net_buf_var_pool_aligned] duration = 0.001 seconds

------ TESTSUITE SUMMARY END ------

===================================================================
PROJECT EXECUTION SUCCESSFUL

jukkar
jukkar previously approved these changes Oct 14, 2025

#if defined(CONFIG_NET_BUF_LARGE_SIZE)
/** @brief net buf size type */
typedef size_t net_buf_size_t;
Copy link
Contributor

@pdgendt pdgendt Oct 14, 2025

Choose a reason for hiding this comment

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

If we look at #96903, should we prefer uint32_t?

Not blocking, just a question.

@pdgendt pdgendt dismissed their stale review October 14, 2025 06:37

Comment addressed

pdgendt
pdgendt previously approved these changes Oct 14, 2025
Comment on lines 76 to 83
#if defined(CONFIG_NET_BUF_LARGE_SIZE)
/** @brief net buf size type */
typedef size_t net_buf_size_t;
#else
/** @brief net buf size type */
typedef uint16_t net_buf_size_t;
#endif

Copy link
Contributor

Choose a reason for hiding this comment

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

I do not think that it makes any sense to have it configurable, nor use size_t. This will introduce a lot of mess because no one would know what actual maximal size is. Either it remains uint16_t, or we change it to uint32_t. And USB in Zephyr for sure does not require it to be larger than uint16_t.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And USB in Zephyr for sure does not require it to be larger than uint16_t.

Could you explain more about it?
Windows will write/read 64KiB data to/from usb disk. If the buffer of msc is configured as 64KiB and give the 64KiB buffer to controller at one time, then the controller can transfer all the 64 KiB bytes without host stack and msc class involved.

Copy link
Member

Choose a reason for hiding this comment

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

I do not think that it makes any sense to have it configurable, nor use size_t. This will introduce a lot of mess because no one would know what actual maximal size is.

@jfischer-no I agree about not using size_t, since it needs to be more explicit than that, however no code should be using the struct member types for doing any "maximal size" derminations. net_buf offers separate APIs like net_buf_max_len(), net_buf_headroom() and net_buf_tailroom() to determine how much storage space is available.

Copy link
Member

Choose a reason for hiding this comment

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

If the entity (controller?) reading or writing the data could support scatter-gather API like readv/writev, then we would not need to do any of these changes as it would be possible to setup net_buf so that they are chained together and the reads/writes would happen to correct net_buf "automatically". Anyway, just some idea to think about.

Comment on lines 941 to 949
uint16_t net_buf_simple_max_len(const struct net_buf_simple *buf);
net_buf_size_t net_buf_simple_max_len(const struct net_buf_simple *buf);
Copy link
Member

Choose a reason for hiding this comment

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

I think this is an oversight in the API. The public API has strived to keep the uint16_t as much of an internal detail as possible, while using size_t for both input and return parameters. I think this one should probably just be changed to size_t to be consistent with the rest of the API.

As for the point @jfischer-no raised regarding the predictability of what the buffer can actually contain, I agree that internal (within the structure) a fixed size type (e.g. uint32_t) makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @jhedberg , I do the changes, please help to review whether it is your thought.

@MarkWangChinese MarkWangChinese dismissed stale reviews from pdgendt and jukkar via e78e3dc October 16, 2025 08:49
@MarkWangChinese MarkWangChinese force-pushed the feature/net_buf_large_size_support branch from 938fd0f to e78e3dc Compare October 16, 2025 08:49
Comment on lines 98 to 101
uint16_t len;
uint32_t len;

/** Amount of data that net_buf_simple#__buf can store. */
uint16_t size;
uint32_t size;
Copy link
Member

Choose a reason for hiding this comment

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

I think you misunderstood me a little bit. I wasn't proposing to change this unconditionally to uint32_t, rather you'd need some explicit enabling of the larger size, through Kconfig, like you had before. Otherwise you're causing memory overflows to platforms what are very constrained (we have at least some build configurations for 16k platforms where even just a few bytes increase in RAM consumption will cause the build to fail).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

* @return Number of bytes usable behind the net_buf_simple::data pointer.
*/
uint16_t net_buf_simple_max_len(const struct net_buf_simple *buf);
size_t net_buf_simple_max_len(const struct net_buf_simple *buf);
Copy link
Member

Choose a reason for hiding this comment

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

This should be in a separate commit, with the commit message explaining that it's just aligning this with the rest of the net_buf APIs.

Copy link
Member

Choose a reason for hiding this comment

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

This is still a breaking API change, though.

Comment on lines 952 to 954
uint16_t offset;
uint32_t offset;
/** Length of data */
uint16_t len;
uint32_t len;
Copy link
Member

Choose a reason for hiding this comment

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

Same here. This should be build-time conditional.

Copy link
Contributor Author

@MarkWangChinese MarkWangChinese Oct 16, 2025

Choose a reason for hiding this comment

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

Got it, I will add back the net_buf_size_t too. Do you have concern about using typedef? IMO, both are OK.

#if defined(CONFIG_NET_BUF_LARGE_SIZE)
/** @brief net buf size type */
typedef uint32_t net_buf_size_t;
#else
/** @brief net buf size type */
typedef uint16_t net_buf_size_t;
#endif

...
	net_buf_size_t len;
...

or

...
#if defined(CONFIG_NET_BUF_LARGE_SIZE)
	uint16_t len;
#else
	uint32_t len;
#endif
...

Copy link
Member

Choose a reason for hiding this comment

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

Considering that you need to have the correct type in multiple structs and multiple member variables, I think the typedef would be the simplest option.

Copy link
Member

Choose a reason for hiding this comment

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

That said, I'd appreciate some more thoughts from @jfischer-no, since he seemed to be against this. @jfischer-no changing unconditionally to a larger size will not work without also finding a solution for our memory constrained platforms that can't currently take any additional memory hit wrt to net_buf sizes.

Comment on lines 1035 to 1038
uint16_t len;
uint32_t len;

/** Amount of data that this buffer can store. */
uint16_t size;
uint32_t size;
Copy link
Member

Choose a reason for hiding this comment

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

And here.

Initially I think we should make the larger size opt in. We can then discuss if eventually it'd be opt-out, and then we make the memory-constrained configurations explicitly select the smaller size.

* @return Number of bytes usable behind the net_buf::data pointer.
*/
static inline uint16_t net_buf_max_len(const struct net_buf *buf)
static inline size_t net_buf_max_len(const struct net_buf *buf)
Copy link
Member

Choose a reason for hiding this comment

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

Separate commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

}

uint16_t net_buf_simple_max_len(const struct net_buf_simple *buf)
size_t net_buf_simple_max_len(const struct net_buf_simple *buf)
Copy link
Member

Choose a reason for hiding this comment

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

Separate commit

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@MarkWangChinese MarkWangChinese force-pushed the feature/net_buf_large_size_support branch from e78e3dc to 9b3c27a Compare October 20, 2025 08:17
@zephyrbot zephyrbot requested a review from ssharks October 20, 2025 08:18
Comment on lines 62 to 65
config NET_BUF_LARGE_SIZE
bool "Network buffer large size"
help
Enable support for large network buffers.
Copy link
Member

Choose a reason for hiding this comment

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

IMO this should specify exactly what the larger size is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I add the uint32_t in the description. If the config name needs to be changed too, please let me know.

Copy link
Member

Choose a reason for hiding this comment

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

I must admit I am not a fan of Kconfig like this for changing an API. What happens when another subsystem in Zephyr relies on a specific maximum size, but the user selects the Kconfig, changing the size? We been through similar constructs in the past, none turned out to work very well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree with Johan's thought as #97440 (comment).
IMO, today's MCUs all seems to have quite a bit of RAM. and this change only increase 4 bytes for every net buf. 🙂

Copy link
Member

Choose a reason for hiding this comment

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

As discussed on Discord, a cleaner (and hopefully less controversial) way forward would be to introduce accessor functions to the net_buf parsing state (i.e. data pointer & length), something like:

size_t net_buf_len(struct net_buf *buf)
{
	return buf->b.len;
}

void *net_buf_data(struct net_buf)
{
	return buf->b.data;
}

The above would also pave the way to remove the union from within net_buf, which only exists as a convenience to avoid having to access fields through the embedded net_buf_simple.

Since this is a rather big effort, it's not realistic to consider it for Zephyr 4.3 anymore. However, size_t return value fix in this PR is still valid, IMO (along with a migration guide entry), so I think it would be good to get that separated and merged for the next release.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, thanks. It can hide the len of the struct net_buf from the users, users only use size_t.
But we still need to change the type of 'len' by CONFIG_NET_BUF_LARGE_SIZE option to support large data size, right?

Sure, I will create another pr to change the return value of net_buf_max_len.

Copy link
Member

Choose a reason for hiding this comment

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

I really do not think we need a Kconfig for this. What do others think?

Copy link
Member

Choose a reason for hiding this comment

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

I really do not think we need a Kconfig for this. What do others think?

The current uint16_t types are a memory footprint optimization. I don't feel confident to claim that no one needs or wants that optimization anymore. And if we don't make that claim I can't think of other reasonable options besides being able to enable or disable the optimization through Kconfig.

tags:
- net_buf
libraries.net_buf.large_buf:
min_ram: 16
Copy link
Member

Choose a reason for hiding this comment

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

Not so sure this will help. One memory constrained platform which uses net_bufs (for Bluetooth) is nRF51 with 16k RAM, so the above wouldn't exclude it. I'd propose to use 32.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated as 32.

@henrikbrixandersen henrikbrixandersen added the Breaking API Change Breaking changes to stable, public APIs label Oct 20, 2025
@MarkWangChinese MarkWangChinese force-pushed the feature/net_buf_large_size_support branch from 9b3c27a to 5a67648 Compare October 21, 2025 02:17
change uint16_t as uint32_t to support large size of data with one Kconfig.

Signed-off-by: Mark Wang <yichang.wang@nxp.com>
add test through testcase.yaml.

Signed-off-by: Mark Wang <yichang.wang@nxp.com>
@MarkWangChinese MarkWangChinese force-pushed the feature/net_buf_large_size_support branch from 5a67648 to 56a7aaf Compare November 19, 2025 07:25
@sonarqubecloud
Copy link

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 area: Tests Issues related to a particular existing or missing test Breaking API Change Breaking changes to stable, public APIs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants