-
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
GNRC implementation of CoAP #5598
Conversation
I certainly think it is worthwhile if we get a RIOT coap implementation which uses the riot IPC to make it easier to get started on IoT projects. |
Thanks for the feedback. @gebart, the implementation includes client and server, but I have focused mostly on client side so far. No block support yet. RIOT's generic IP fragmentation makes block less pressing, although I have not compared the per-packet payload size between those two. Here is a summary of what's available. I would describe it as minimally useful.
|
In my opinion there are two issues with relying on the 6lo fragmentation for block transfers: the size is limited to the maximum size of a IP packet, <1280 bytes, and if one fragment is lost, the whole packet needs to be retransmitted, unless other methods such as the link-layer retransmissions manage to catch the missing fragment frame. |
@kb2ma, thanks a lot! |
@kb2ma thank you for recording and posting your presentation! I wish I had been able to attend the summit. I will listen to this later tonight! |
@kb2ma, can you point me to the function/data structure one needs to implement in order to generate a resource and give it a name? |
@OlegHahm, good to hear from you! It sounds like you want to implement a server, and register a resource to some path. I have not implemented this registration, but gcoap does have a proto-solution. All of the structs for gcoap are defined in coap.h, and there is some introductory documentation at the top of that file. See especially the Server Use section. The 'server struct' referenced there is gnrc_coap_server_t. So, the proto-solution is a callback that allows a user of gcoap to implement their own resource server. A super-simple server could be implemented in a single function. See the gcoap example for a server that only provides an empty response to /.well-known/core. Now that's simple. :-) The actual resource transferred is the gnrc_coap_transfer_t. At this point, anything more sophisticated is up to you. To date, I personally have been more focused on the client side of CoAP. However, I am starting on the goal of implementing the Observe protocol. For a working example, I plan to start with your netstats work (yes!) as a resource to serve, as I am interested in network monitoring. This area of resources is tricky, and really server-specific. Certainly we don't want unnecessary storage at the CoAP layer. At a high level, what are your expectations from a server for resource registration -- pass a pointer, a callback, store some data? Monday is RIOT day for me this week, so let me try to come up with some concrete ideas for serving up the netstats data. |
coap_type = (hdr->ver_type_tkl & 0x30) >> 4; | ||
msg_meta->tokenlen = hdr->ver_type_tkl & 0x0F; | ||
if (coap_ver != GNRC_COAP_VERSION | ||
|| coap_type != GNRC_COAP_TYPE_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.
So, only non-confirmable messages are supported right now?
@OlegHahm: yes, only non-con - as Ken mentioned above:
and during his presentation at the summit. |
Oops, sorry, too little sleep during the last days. ;) |
No worries, @OlegHahm, and thanks for stepping in, @smlng. Yes, this PR definitely is WIP. I have added timeouts in my working branch, which are essential for confirmable messaging. BTW, is there a best practice for refreshing the PR? I was planning to wait until I have some significant feature ready. My thinking on confirmable has been that any failures in the mesh mean that some link layer retries already failed. Besides, if the message is really important, an app needs a fallback strategy anyway, in case confirmable retries fail, too. I definitely agree though that the ACK confirmation is nice to have. |
@kb2ma while you have the WIP tag on the PR you should be able to push whatever you want to whenever you want to. It's always nice to see things moving ahead. You should probably rebase regularily while working on it to stay up to date with the master branch. |
I must say that I'm not sure the tight coupling of CoAP protocol handling and gnrc is good design. A proper CoAP library should sit below any gnrc layer. (I'm also working on a CoAP library here [1], functionality wise it's not further than this PR.) [1] https://github.com/kaspar030/sock/tree/master/nanocoap |
Thanks for the feedback and link to nanocoap, @kaspar030. Have you defined features and timeline for it? Are you planning to add Observe, Confirmable, or Block in the near term? |
@kaspar030 @kb2ma you should join forces, and try to unify your implementations. I think using |
While I agree with @kaspar030 and @gebart on the one hand (putting CoAP on top of conn/sock/sockets increases flexibility a lot), I see problems with that:
Moreover, CoAP cannot only run over UDP, but a plethora of protocols (the two craziest things I heard about were CoAP-over-SMS and CoAP-over-WebRTC). Hence, netapi might be a better match to enable this flexibility than conn. |
I agree that refitting this PR to work on conn/sock is hung up on #5533. Having said that, I expect refitting will be easier if conn/sock adds an async event loop, as is being discussed now. For my implementation, this feature (plus message passing) is the main appeal of GNRC. I can live with the ambiguity for now, and will see how the other PR resolves. |
Those features are planned, but I don't know when I find time.
I don't see nanocoap tied to conn/sock though. It's parsing and state handling will be independent from the used networking. I think it would make sense to at least share that code, if possible. |
Sounds like a good plan. I reviewed the nanocoap code, and I think it works well as a microcoap replacement. It definitely is the thinnest veneer over the packet data. I agree that the packet handling code should be isolated from the networking code. For example, my _coap_parse() expects a gnrc_pktsnip_t, but it just needs a buffer and length as you have done. It looks like nanocoap really is a few things:
Let me think on this list from the bottom up, for how these things can be integrated with gcoap. |
I see a way forward now with use of nanocoap for gcoap. I plan to make these migrations for the structs in gcoap. The structs don't match one-to-one, but this is the basic idea.
At least for development purposes, I plan to make nanocoap, specifically nanocoap.c/.h, into a module at the 'net' level, in This refactoring is substantial, and I plan to take some vacation time soon, so expect a few weeks for some results. |
\o/ Maybe we can merge it for this release? |
That's my goal! Working on it now. |
(feature freeze is today/tomorrow-ish ;-)) |
(I'm willing to wait a little for this PR (and others) but won't overstretch the timetable) |
USEMODULE += gnrc_netdev_default | ||
USEMODULE += auto_init_gnrc_netif | ||
# Specify the mandatory networking modules | ||
USEMODULE += gnrc_ipv6_router_default |
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 you can remove the router requirements on this, too? RPL you already commented out below anyways ;-) (see #6007).
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.
Done on top of rebase.
@miri64, I just read your 'One more day' message. To be clear, I addressed the issue you flagged about configuring the example as a host. I'm not sure what is next, but I expect that you will ask me to squash that. I will do that, and then either we are done or there will be more review. Let me know if there is anything I should do to move the process along. |
Just let me give this a quick review before squashing. Also it might be that you will require #6030 to pass Murdock :-/ |
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.
Just some questions left ;-)
|
||
USEMODULE += gcoap | ||
USEMODULE += gnrc_udp | ||
USEMODULE += gnrc_ipv6 |
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 are these modules included?
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.
- gcoap is necessary because we are testing that module. :-)
- gnrc_ipv6 is needed at least due to code in gcoap's _event_loop(), which references GNRC_NETTYPE_IPV6. This dependency is my assumption. Is there a better alternative?
- gnrc_udp is not needed, and I will fix that. It is an implicit (Makefile.dep) dependency for gcoap. Thanks for 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.
I think there are other tests already that include gnrc_ipv6
so I'm fine with that (gcoap
was clear ^^")
|
||
# Redefine request token length, max 8. | ||
#GCOAP_TOKENLEN = 2 | ||
#CFLAGS += -DGCOAP_TOKENLEN=$(GCOAP_TOKENLEN) |
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.
Can those be removed or do you plan to uncomment 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.
I left those in there intentionally to help a user. It seemed like the message token length, like the CoAP port commented out above it, is something that an implementation might want to adjust. I have an #ifndef check in coap.h for GCOAP_TOKENLEN.
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.
Could you maybe add some comment about than (like "uncomment if needed" like in the gnrc_minimal
example)?
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.
Updated; I understand the confusion.
Yes :-). |
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.
ACK, please squash!
Squashed, with gusto! |
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 are still some issues picked up by Murdock. Please address and squash immediately.
|
||
/** | ||
* @brief The entry point of this test suite. | ||
* |
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 remove trailing whitespace.
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.
Fixed, apologies for the oversight.
argv[4]); | ||
} | ||
printf("gcoap_cli: sending msg ID %u, %u bytes\n", coap_get_id(&pdu), | ||
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.
len
needs casting to (unsigned)
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.
Addressed and rebased.
/* Content-Format */ | ||
if (pdu->content_type != COAP_FORMAT_NONE) { | ||
bufpos += coap_put_option_ct(bufpos, last_optnum, pdu->content_type); | ||
last_optnum = COAP_OPT_CONTENT_FORMAT; |
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.
last_optnum is assigned but never used according to cppcheck
.
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.
Addressed and rebased.
Now seeing an error in Murdock with dtls-echo:nrf52dk. I don't understand this, as nrf52dk is blacklisted in Makefile. |
Nothing to do with your PR, so I would say ACK! |
(See #6032) |
See README.md in examples/gcoap for an overview. Includes a CLI coap command.
Why a GNRC implementation when libcoap and microcoap are out there? Well, it started for personal reasons, as an experiment with the network stack, and I have kept on hacking at it. Certainly CoAP is a key IoT protocol. IMO it's worth the effort to have a well-documented LGPL implementation based on RIOT's messaging architecture, that can be tuned to the project's needs.
To make the implementation more useful, I plan to implement Observe soon. If others agree the the goal is worthwhile and the work looks promising, I'll add unit tests for what I have so far.