Skip to content

Conversation

maribu
Copy link
Member

@maribu maribu commented Jun 30, 2020

Contribution description

Motivation / Background

In some use cases where a socket is bound to multiple IP addresses, it is useful to know on which address a datagram was received. The current sock API makes it hard to retrieve this information: sock_udp_get_local() will return whatever IP the interface was bound to; which in the use case of multiple IP addresses often is SOCK_IPV6_EP_ANY.

E.g. lets say we have a RIOT border router connected to the Internet via Ethernet and to an IEEE 802.15.4 network. A CoAP server running additionally on this border router might provide access to its resources without access control, DTLS, OSCORE, ... over IEEE 802.15.4, as Layer 2 security might be considered as sufficient in that scenario. However, for requests received from the Internet, additional security measures seem to be a good idea.

There are likely many other use cases for virtual hosting there.

Proposed solution

Add an sock_udp_recv2() function, which in addition to sock_udp_ep_t *remote also takes an sock_udp_ep_t *local as optional argument (optional = "pass NULL if you don't care). The existing sock_udp_recv() is implemented as static inline wrapper on top of sock_udp_recv2(), passing NULL for local. Thus, sock implementations don't need to provide both functions and existing code can keep using sock_udp_recv().

A proof of concept implementation was added for GNRC, lwIP, and emb6.

Testing procedure

TBD

Issues/PRs references

None

maribu added 5 commits June 30, 2020 21:11
Add `sock_udp_recv2()` and `sock_udp_recv_buf2()` that also provide the local
address a datagram was received on. This is particularly useful if a socket
is bound to multiple addresses or to all local addresses. This can be used
to implement virtual hosting.
Parenthesis around numbers boolean defined (e.g. `#define LWIP_IPV6 (1)` rather
than `#define LWIP_IPV6 1`) prevents using IS_ACTIVE() / IS_USED() macros. Thus,
this commit drops the parenthesis.
@maribu maribu added Area: network Area: Networking Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. State: demonstrator State: This PR (loosely) demonstrates a concept and is not necessarily meant to be merged. labels Jun 30, 2020
@maribu maribu requested a review from miri64 June 30, 2020 19:43
@miri64
Copy link
Member

miri64 commented Jun 30, 2020

A proof of concept implementation was added for GNRC, lwIP, and emb6.

Since emb6 is slated to be removed after the release, I think you can safely drop support for it here as well ;-)

@miri64
Copy link
Member

miri64 commented Jun 30, 2020

I no PoC and WIP, but whatever the final solution is should also provide similar solutions for the other sock APIs.

@@ -225,6 +229,13 @@ ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **buf_ctx,
memcpy(remote, &tmp, sizeof(tmp));
remote->port = byteorder_ntohs(hdr->src_port);
}
if (local != NULL) {
gnrc_pktsnip_t *ipv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6);
Copy link
Member

Choose a reason for hiding this comment

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

Might be worth to extend gnrc_sock_recv() to also provide the destination. Otherwise, we iterate pkt unnecessary twice.

@maribu
Copy link
Member Author

maribu commented Jul 24, 2020

I now have a different use case that again needs extension of the SOCK API. This makes me wonder if a more generalized solution would be better. E.g.

int sock_udp_recv_aux(sock_udp_t *sock, void *data, size_t max_len,
                      uint32_t timeout, sock_udp_ep_t *remote,
                      sock_aux_recv_udp_t *auxiliary_data);

ssize_t sock_udp_send_aux(sock_udp_t *sock, const void *data, size_t len,
                          const sock_udp_ep_t *remote,
                          sock_aux_send_udp_t *auxiliary_data);

And sock_aux_t would be a struct in which additional auxiliary data can be "unlocked" by pulling in pseudo modules. E.g. it could look like this:

enum {
    SOCK_AUX_FLAG_HAS_LOCAL_ENDPOINT = (1UL << 0),
    SOCK_AUX_FLAG_HAS_TIMESTAMP      = (1UL << 1),
};

typedef struct {
#ifdef MODULE_SOCK_AUX_LOCAL_ENDPOINT
    sock_udp_ep_t local;
#endif /* MODULE_SOCK_AUX_RECEIVED_ENDPOINT */
#ifdef MODULE_SOCK_TIMESTAMP
    uint64_t received_at;
#endif /* MODULE_SOCK_TIMESTAMP */
    unsigned flags; /**< Bitmask identifying which auxiliary data is present */
} sock_aux_recv_udp_t;

typedef struct {
#ifdef MODULE_SOCK_TIMESTAMP
    uint64_t send_at;
#endif /* MODULE_SOCK_TIMESTAMP */
    unsigned flags; /**< Bitmask identifying which auxiliary data is present */
} sock_aux_send_udp_t;

The use case for the time stamp is btw. time synchronization. By having the correct time a frame was received and send, jitter in the message processing does no longer influence precision of time synchronization. E.g. the low level network driver should already be able to get a pretty accurate time stamp. In addition some hardware (e.g. Ethernet with PTP support) will create the timestamp in hardware, so that even the jitter in the ISR can be avoided. The timestamp for sending is needed in context of PTP in server mode for the Fellow_up message or as client for the Delay_Req message.

Those time stamps could be provided outside of the SOCK API e.g. by having get_last_tx_timestamp() and get_last_rx_timestamp(), but those would be racy if multiple frames are send/received almost simultaneously.

@maribu
Copy link
Member Author

maribu commented Jul 27, 2020

Closing in favor of #14622

@maribu maribu closed this Jul 27, 2020
@maribu maribu deleted the sock_udp_api branch January 25, 2021 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: network Area: Networking Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. State: demonstrator State: This PR (loosely) demonstrates a concept and is not necessarily meant to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants