-
Notifications
You must be signed in to change notification settings - Fork 7k
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
Features/net pkt append memset #9393
Features/net pkt append memset #9393
Conversation
Codecov Report
@@ Coverage Diff @@
## master #9393 +/- ##
==========================================
+ Coverage 52.53% 52.55% +0.01%
==========================================
Files 212 212
Lines 25821 25855 +34
Branches 5428 5437 +9
==========================================
+ Hits 13565 13588 +23
- Misses 10071 10077 +6
- Partials 2185 2190 +5
Continue to review full report at Codecov.
|
75d5eb7
to
c5be16b
Compare
* were no free fragments in a pool to accommodate all data. | ||
*/ | ||
u16_t net_buf_append_set_bytes(struct net_buf *buf, u16_t len, | ||
const u8_t value, s32_t timeout, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like indentation is off here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, looks perfectly indented here. Checkpatch also approves. Not sure how to improve that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, my bad, no issue in this line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds so specific that I'd rather move it to the net_pkt layer. Some comments nevertheless:
- The verb used for adding stuff to the end of buffers is "add", not "append". I noticed that
net_buf_append_bytes()
has slipped past me. Was there a specific reason to change the verb for that API? - const for the
u8_t value
does nothing, so I'd leave it out. - It should be
size_t len
and notu16_t len
to be consistent throughout the API (not to mention it generates less code for our 32-bit architectures).net_buf_append_bytes()
got this wrong also - needs fixing.
include/net/net_pkt.h
Outdated
* were no free fragments in a pool to accommodate all data. | ||
*/ | ||
u16_t net_pkt_append_memset(struct net_pkt *pkt, u16_t len, const u8_t data, | ||
s32_t timeout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Could you check all the functions in this PR and make sure that indentation is correct.
subsys/net/ip/dhcpv4.c
Outdated
if (!net_pkt_append_u8(pkt, 0)) { | ||
return false; | ||
} | ||
if (net_pkt_append_memset(pkt, size, 0, K_FOREVER) != size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are trying to migrate away from K_FOREVER timeout in #9118 so please use here a proper timeout value.
subsys/net/ip/dhcpv4.c
Outdated
if (!net_pkt_append_u8(pkt, 0)) { | ||
return false; | ||
} | ||
if (net_pkt_append_memset(pkt, size, 0, K_FOREVER) != size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
c5be16b
to
c5b7235
Compare
include/net/net_pkt.h
Outdated
* were no free fragments in a pool to accommodate all data. | ||
*/ | ||
u16_t net_pkt_append_memset(struct net_pkt *pkt, u16_t len, const u8_t data, | ||
s32_t timeout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is indentation issue here.
subsys/net/buf.c
Outdated
* assumes that the buffer has at least one fragment. | ||
*/ | ||
u16_t net_buf_append_set_bytes(struct net_buf *buf, u16_t len, | ||
const u8_t value, s32_t timeout, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
subsys/net/ip/net_pkt.c
Outdated
@@ -1201,6 +1201,59 @@ u16_t net_pkt_append(struct net_pkt *pkt, u16_t len, const u8_t *data, | |||
return appended; | |||
} | |||
|
|||
u16_t net_pkt_append_memset(struct net_pkt *pkt, u16_t len, const u8_t data, | |||
s32_t timeout) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
subsys/net/ip/net_pkt.c
Outdated
} | ||
|
||
appended = net_buf_append_set_bytes(net_buf_frag_last(pkt->frags), | ||
len, data, timeout, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
tests/net/net_pkt/src/main.c
Outdated
zassert_true(ret == 50, "Linearize failed failed"); | ||
for (cur_pos = 0; cur_pos < 50; ++cur_pos) { | ||
zassert_true(read_data[cur_pos] == 0, | ||
"Byte was expected to read 0"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please indent these three lines in the main.c properly too.
tests/net/net_pkt/src/main.c
Outdated
zassert_true(ret == 128, "Linearize failed failed"); | ||
for (cur_pos = 0; cur_pos < 128; ++cur_pos) { | ||
zassert_true(read_data[cur_pos] == 255, | ||
"Byte was expected to read 255"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
tests/net/net_pkt/src/main.c
Outdated
zassert_true(ret == 128, "Linearize failed failed"); | ||
for (cur_pos = 0; cur_pos < 128; ++cur_pos) { | ||
zassert_true(read_data[cur_pos] == 0, | ||
"Byte was expected to read 0"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and also here
c5b7235
to
b4c1127
Compare
Most importantly - is this change useful? The IP stack seems to move to BSD Sockets API, which wouldn't be able to expose that functionality. And otherwise, 2 functions of 30+50 lines are used to replace cases of 5 lines of code in 2 places. That doesn't look to tally to positive befits in terms of code size, and unlikely will due to note on the emerging standard API above. |
@pfalcon My motivation for this is the wasteful handling of resources I noticed in the DHCPv4 code. Because the net_pkt API currently only allows for appending single integral types or copy from a range of memory. I thought it was a pretty glaring omission that it is not possible to efficiently fill a packet buffer with a large number of constant values (typically zero). I only converted DHCPv4 because that is where I noticed it but I'm certain it can/should be applied in a lot of other places. Code size wise it's pretty much a wash, depending on which application/example you look at. I neither see how the BSD API will fix the particular problem at hand (with buffer handling) nor how and whether all subsystems will convert to to the BSD API soon. |
I understand the motivation and agree that thinking of an abstract "the most general API", that's a useful addition. But practically, the code size is also a resource. And I have a hunch feeling that Zephyr stack is not competitive in the terms of code size, and sooner or later we'll need to address that. On the other hand, DHCPv4 is not on the critical path, so the fact that its packets are constructed "slowly" (but with less code) shouldn't be a big problem.
It doesn't, that's the point. The typical Unixy (now POSIXy) way is to have API erring on the side minimality, rather than on "abstract completeness". A POSIX way to deal with that problem would be to allocate a static buffer of size a particular application tolerates. Then either write that buffer multiple times, or write a subset of it. E.g., if you have
I only know what was posted, e.g. https://github.com/zephyrproject-rtos/zephyr /issues/7591 , and yes, I'm not sure about how soon either. All in all, I can only call for your own consideration of these matter, and not give -1, as with tests included, it's hard to argue that it does anything "bad", even if I have IMHO that it doesn't do much good either. |
It's not quite that simple. A lot of those small functions are actually inlined and the call stack is somewhat deep. I'm also not quite sure whether the single appends have any negative impact on fragmentation.
Oh, I'm quite aware how BSD sockets work, I've written a lot of small and big scale applications in my life.
The problem is: You always have to send one full datagram at a time and this is embedded, so using a regular BSD API you need to allocate the full buffer at a time which may or may not possible which is what the buf/net_pkt API is solving. Not everything is streamed TCP, in fact rather little in the embedded world is and for a reason... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor tweak still needed.
tests/net/net_pkt/src/main.c
Outdated
@@ -1152,8 +1152,6 @@ static void test_pkt_pull(void) | |||
static void test_net_pkt_append_memset(void) | |||
{ | |||
struct net_pkt *pkt; | |||
struct net_buf *read_frag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is in wrong commit, should be in "net: pkt: Added new function net_pkt_append_memset() to prefill packet"
tests/net/net_pkt/src/main.c
Outdated
zassert_true(ret == 50, "Linearize failed failed"); | ||
for (cur_pos = 0; cur_pos < 50; ++cur_pos) { | ||
zassert_true(read_data[cur_pos] == 0, | ||
"Byte was expected to read 0"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please indent these three lines in the main.c properly too.
Some locations like DHCPv4 client create a prefilled packet by appending new fragments in a loop with one byte each via net_pkt_append_u8() which is wasteful and noisy. This patch adds the new functions net_pkt_append_memset() which creates fragments as needed in the desired size and initialises it to the specified value. To facilitate this function, net/buf also receives a new net_buf_append_set_bytes() function and this also adds a unittest for the former. Prerequisite for zephyrproject-rtos#9287 Signed-off-by: Daniel Egger <daniel@eggers-club.de>
Thise uses the new net_pkt_append_memset() function to generate the required zero filling instead of calling net_pkt_append_u8() in loops. Fixes zephyrproject-rtos#9287 Signed-off-by: Daniel Egger <daniel@eggers-club.de>
b4c1127
to
83a2873
Compare
* were no free fragments in a pool to accommodate all data. | ||
*/ | ||
u16_t net_buf_append_set_bytes(struct net_buf *buf, u16_t len, | ||
const u8_t value, s32_t timeout, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds so specific that I'd rather move it to the net_pkt layer. Some comments nevertheless:
- The verb used for adding stuff to the end of buffers is "add", not "append". I noticed that
net_buf_append_bytes()
has slipped past me. Was there a specific reason to change the verb for that API? - const for the
u8_t value
does nothing, so I'd leave it out. - It should be
size_t len
and notu16_t len
to be consistent throughout the API (not to mention it generates less code for our 32-bit architectures).net_buf_append_bytes()
got this wrong also - needs fixing.
Regarding "append" vs "add", was the idea that "append" implies that it'll potentially go to new buffers created in a chain? That might be a valid reason. However, the object should be "mem" and not "bytes" to be consistent with the likes of |
One other thing: net_buf is an independent module, which should have it's own independent commit. |
The "mem" functions copy bytes from another memory location, whereas this initialises with a fixed constant, maybe just use
You mean assimilate into |
Yes. It'd then also be a private API for now, which reduces the pressure for "getting it right" from the start. If there later comes wider users we could revisit making this a net_buf API. |
Closing because alternate solution in #9438 got merged. |
Fixes #9287