-
Notifications
You must be signed in to change notification settings - Fork 2k
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/gcoap: Confirmable request with piggybacked ACK response #7337
Conversation
15e7d3f
to
20065c1
Compare
No longer WIP. I plan to rebase ASAP. |
fc8cd9f
to
e46d9c8
Compare
Rebased. This PR is a pretty significant milestone for gcoap, and I look forward to getting it merged. |
if (!_coap_state.resend_bufs[i*GCOAP_PDU_BUF_SIZE]) { | ||
memo->msg.data.pdu_buf = &_coap_state.resend_bufs[i*GCOAP_PDU_BUF_SIZE]; | ||
memcpy(memo->msg.data.pdu_buf, buf, GCOAP_PDU_BUF_SIZE); | ||
memo->msg.data.pdu_len = len; |
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.
You forgot a break;
here, didn't you?
Because if gcoap found a free receive buffer it doesn't need to look for an additional one, right? This is of cause not a problem when GCOAP_RESEND_BUFS_MAX == 1
(which is the default value) but if you increase that number the code doesn't seem to work properly.
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.
Right on, @nmeum! I just pushed your fix to my repository.
please rebase as #7336 is merged |
please rebase with #8250 merged right now |
3de19fd
to
f396227
Compare
sys/include/net/gcoap.h
Outdated
@@ -484,6 +493,10 @@ typedef struct { | |||
observe memos */ | |||
gcoap_observe_memo_t observe_memos[GCOAP_OBS_REGISTRATIONS_MAX]; | |||
/**< Observed resource registrations */ | |||
uint8_t resend_bufs[GCOAP_RESEND_BUFS_MAX * GCOAP_PDU_BUF_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.
why not uint8_t resend_bufs[GCOAP_RESEND_BUFS_MAX][GCOAP_PDU_BUF_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.
Good idea, makes the intent clearer.
/* retries remaining; double timeout and resend */ | ||
else { | ||
/* decrement send limit, and add 1 to advance the timeout */ | ||
unsigned i = COAP_MAX_RETRANSMIT - memo->send_limit-- + 1; |
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 looks IMHO a bit ugly, I would put the decrement as a separate instruction.
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.
I agree. With this update, I removed the 'decrement' comment because it's not really necessary.
else { | ||
unsigned i = COAP_MAX_RETRANSMIT - memo->send_limit + 1; | ||
uint32_t timeout = ((uint32_t)COAP_ACK_TIMEOUT << i) * US_PER_SEC; | ||
timeout = random_uint32_range(timeout, timeout * COAP_RANDOM_FACTOR); |
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.
mhm, I don't like that, bc COAP_RANDOM_FACTOR
is 1.5
thereby introducing floating point maths here. We know that timeout
is a multiple of COAP_ACK_TIMEOUT
(which is two seconds). Hence, I would rather do something like
#define COAP_TIMEOUT_VARIANCE (500U * US_PER_MS)
uint32_t timeout = ((uint32_t)COAP_ACK_TIMEOUT << i) * US_PER_SEC;
timeout = random_uint32_range(timeout - COAP_TIMEOUT_VARIANCE, timeout + COAP_TIMEOUT_VARIANCE);
} | ||
/* retries remaining; double timeout and resend */ | ||
else { | ||
unsigned i = COAP_MAX_RETRANSMIT - memo->send_limit + 1; |
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.
if you put the decrement, i.e. memo->send_limit--
, above this statement you can omit the + 1
at the end of 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.
I know its likely micro-optimisation, and the compiler will do that already. However, IMHO it makes the code also more readable.
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.
Yes, it's fine and clear with the decrement first. I had it in my head to increase timeout first, but it doesn't matter.
gcoap_request_memo_t *memo = (gcoap_request_memo_t *)msg_rcvd.content.ptr; | ||
|
||
/* no retries remaining */ | ||
if (memo->send_limit == GCOAP_SEND_LIMIT_NON |
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.
I would recommend to enclose each condition in parentheses to clearly separate them.
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.
Yes, I try to do this with new code now.
} | ||
|
||
/* validate class and type for incoming */ | ||
switch (coap_get_code_class(&pdu)) { | ||
|
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.
remove empty line
else { | ||
memo->state = GCOAP_MEMO_UNUSED; | ||
DEBUG("gcoap: can't wake up mbox; no timeout for msg\n"); | ||
unsigned msg_type = (*buf & 0x30) >> 4; |
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.
why not use coap_get_type
from nanocoap? Though the variable name indicates what you want here, its not clear why this works, the following should work (I hope):
unsigned msg_type = coap_get_type((coap_pkt_t *)buf);
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.
I agree my solution was not clear. Unfortunately, your suggestion generates a segfault. I wonder if the best appoach is to define a second set of inline functions with the prefix 'coap_hdr_get', like
coap_hdr_get_type((coap_hdr_t *)buf);
Leave this for future work? Just define this one function for now?
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.
ah, buf
is not a full packet, hence coap_get_type
fails, i.e., reads data from where it shouldn't -> segfault.
okay than leave as is (for now).
if (memo->msg.data.pdu_buf) { | ||
memo->send_limit = COAP_MAX_RETRANSMIT; | ||
timeout = (uint32_t)COAP_ACK_TIMEOUT * US_PER_SEC; | ||
timeout = random_uint32_range(timeout, timeout * COAP_RANDOM_FACTOR); |
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 as above, i.e., introduces floating point maths.
please squash, I'll test in the mean time, so this can go into release 2018.01 as planned. |
Thanks! I have squashed on my local workstation. I plan to test and upload later today. |
Looks like you need to rebase (again) to resolve the conflict, too. |
Also, create resend_bufs array to store PDU for resend.
f9cc42f
to
d67dfe7
Compare
Squashed and rebased. |
The Murdock build failed after I squashed and rebased. It revealed a type issue in a debug statement on MIPS platforms. It turns out that I was expecting a size_t response from It turns out that there are two other places in gcoap.c that expect How could this code have been wrong for so long. :-/ |
well, we recently (yesterday) merged #5166 which changed the handling of debug messages, i.e., previously they were guarded by preprocessor |
Yes, your minimal fixup seems to be enough to get this PR through Murdock. Anything on top, should be a separate PR. |
uint32_t variance = ((uint32_t)COAP_ACK_VARIANCE << i) * US_PER_SEC; | ||
timeout = random_uint32_range(timeout, timeout + variance); | ||
|
||
ssize_t res2 = sock_udp_send(&_sock, memo->msg.data.pdu_buf, |
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.
maybe bytes
or bytes_sent
would be a better name than res2
? Otherwise, looks good, please squash the fixup.
adf0a5a
to
5e1d3fe
Compare
Thanks for the review. Fixed variable name and squashed. Travis and Murdock are happy. |
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.
Re-ACK, still I'd like to run some short tests before merge. Nevertheless, this goes into the release, thx @kb2ma for acting quickly 😄
I really appreciate your feedback! Very happy to uncover the bug with handling |
I tested and saw CON and NON request on the wire(shark), looks good to me. |
This PR implements the third step in the confirmable messaging plan in #7192, and depends on #7336. The goal is to use the extended attributes in the request memo to send a confirmable request, including resends on timeout.
Presently, the PR sends the confirmable request using the extended attributes, including a buffer to store the PDU. The next steps are to validate the received response code and type, and then to resend on timeout.