Merge pull request #14704 from maribu/sock-aux-gnrc

net/gnrc/sock: Implement sock_aux_local
This commit is contained in:
Martine Lenders 2020-12-04 13:55:27 +01:00 committed by GitHub
commit ba89d8641e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 134 additions and 4 deletions

View File

@ -89,8 +89,11 @@ void gnrc_sock_create(gnrc_sock_reg_t *reg, gnrc_nettype_t type, uint32_t demux_
} }
ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out, ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out,
uint32_t timeout, sock_ip_ep_t *remote) uint32_t timeout, sock_ip_ep_t *remote,
gnrc_sock_recv_aux_t aux)
{ {
/* only used when some sock_aux_% module is used */
(void)aux;
gnrc_pktsnip_t *pkt, *netif; gnrc_pktsnip_t *pkt, *netif;
msg_t msg; msg_t msg;
@ -150,6 +153,12 @@ ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out,
assert(ipv6_hdr != NULL); assert(ipv6_hdr != NULL);
memcpy(&remote->addr, &ipv6_hdr->src, sizeof(ipv6_addr_t)); memcpy(&remote->addr, &ipv6_hdr->src, sizeof(ipv6_addr_t));
remote->family = AF_INET6; remote->family = AF_INET6;
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
if (aux.local != NULL) {
memcpy(&aux.local->addr, &ipv6_hdr->dst, sizeof(ipv6_addr_t));
aux.local->family = AF_INET6;
}
#endif /* MODULE_SOCK_AUX_LOCAL */
netif = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); netif = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF);
if (netif == NULL) { if (netif == NULL) {
remote->netif = SOCK_ADDR_ANY_NETIF; remote->netif = SOCK_ADDR_ANY_NETIF;

View File

@ -55,6 +55,33 @@ extern "C" {
*/ */
#define GNRC_SOCK_DYN_PORTRANGE_ERR (0) #define GNRC_SOCK_DYN_PORTRANGE_ERR (0)
/**
* @brief Structure to retrieve auxiliary data from @ref gnrc_sock_recv
*
* @details The members of this function depend on the modules used
* @internal
*/
typedef struct {
#if IS_USED(MODULE_SOCK_AUX_LOCAL) || DOXYGEN
/**
* @brief local IP address PDU was received on
*
* This member is only present if module `sock_aux_local` is used.
*/
sock_ip_ep_t *local;
#endif
#if !IS_USED(MODULE_SOCK_AUX_LOCAL) || DOXYGEN
/**
* @brief Workaround in case no `sock_aux_%` module is used
*
* Empty structures are only allowed with a GNU extension. For portability,
* this member is present if and only if this structure would be otherwise
* empty.
*/
uint8_t this_struct_is_not_empty;
#endif
} gnrc_sock_recv_aux_t;
/** /**
* @brief Internal helper functions for GNRC * @brief Internal helper functions for GNRC
* @internal * @internal
@ -116,7 +143,7 @@ void gnrc_sock_create(gnrc_sock_reg_t *reg, gnrc_nettype_t type, uint32_t demux_
* @internal * @internal
*/ */
ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt, uint32_t timeout, ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt, uint32_t timeout,
sock_ip_ep_t *remote); sock_ip_ep_t *remote, gnrc_sock_recv_aux_t aux);
/** /**
* @brief Send a packet internally * @brief Send a packet internally

View File

@ -117,6 +117,7 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
gnrc_pktsnip_t *pkt; gnrc_pktsnip_t *pkt;
sock_ip_ep_t tmp; sock_ip_ep_t tmp;
int res; int res;
gnrc_sock_recv_aux_t _aux = { 0 };
assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL)); assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL));
if (*buf_ctx != NULL) { if (*buf_ctx != NULL) {
@ -129,7 +130,12 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
tmp.family = sock->local.family; tmp.family = sock->local.family;
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp); #if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
_aux.local = &aux->local;
}
#endif
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, _aux);
if (res < 0) { if (res < 0) {
return res; return res;
} }
@ -146,6 +152,11 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return -EPROTO; return -EPROTO;
} }
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
aux->flags &= ~(SOCK_AUX_GET_LOCAL);
}
#endif
*data = pkt->data; *data = pkt->data;
*buf_ctx = pkt; *buf_ctx = pkt;
res = (int)pkt->size; res = (int)pkt->size;

View File

@ -206,6 +206,7 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
udp_hdr_t *hdr; udp_hdr_t *hdr;
sock_ip_ep_t tmp; sock_ip_ep_t tmp;
int res; int res;
gnrc_sock_recv_aux_t _aux = { 0 };
assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL)); assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL));
if (*buf_ctx != NULL) { if (*buf_ctx != NULL) {
@ -218,7 +219,12 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
tmp.family = sock->local.family; tmp.family = sock->local.family;
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp); #if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
_aux.local = (sock_ip_ep_t *)&aux->local;
}
#endif
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, _aux);
if (res < 0) { if (res < 0) {
return res; return res;
} }
@ -240,6 +246,12 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return -EPROTO; return -EPROTO;
} }
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
aux->flags &= ~SOCK_AUX_GET_LOCAL;
aux->local.port = sock->local.port;
}
#endif
*data = pkt->data; *data = pkt->data;
*buf_ctx = pkt; *buf_ctx = pkt;
res = (int)pkt->size; res = (int)pkt->size;

View File

@ -1,5 +1,11 @@
include ../Makefile.tests_common include ../Makefile.tests_common
AUX_LOCAL ?= 1
ifeq (1, $(AUX_LOCAL))
USEMODULE += sock_aux_local
endif
USEMODULE += sock_ip USEMODULE += sock_ip
USEMODULE += gnrc_ipv6 USEMODULE += gnrc_ipv6
USEMODULE += ps USEMODULE += ps

View File

@ -344,6 +344,33 @@ static void test_sock_ip_recv__non_blocking(void)
expect(_check_net()); expect(_check_net());
} }
static void test_sock_ip_recv__aux(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_ip_ep_t local = { .family = AF_INET6 };
sock_ip_ep_t result;
sock_ip_aux_rx_t aux = { .flags = SOCK_AUX_GET_LOCAL };
expect(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
sizeof("ABCD"), _TEST_NETIF));
expect(sizeof("ABCD") == sock_ip_recv_aux(&_sock, _test_buffer,
sizeof(_test_buffer), 0, &result,
&aux));
expect(AF_INET6 == result.family);
expect(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
expect(_TEST_NETIF == result.netif);
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
expect(!(aux.flags & SOCK_AUX_GET_LOCAL));
expect(memcmp(&aux.local.addr, &dst_addr, sizeof(dst_addr)) == 0);
#else
expect(aux.flags & SOCK_AUX_GET_LOCAL);
#endif
expect(_check_net());
}
static void test_sock_ip_recv_buf__success(void) static void test_sock_ip_recv_buf__success(void)
{ {
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
@ -650,6 +677,7 @@ int main(void)
CALL(test_sock_ip_recv__unsocketed_with_remote()); CALL(test_sock_ip_recv__unsocketed_with_remote());
CALL(test_sock_ip_recv__with_timeout()); CALL(test_sock_ip_recv__with_timeout());
CALL(test_sock_ip_recv__non_blocking()); CALL(test_sock_ip_recv__non_blocking());
CALL(test_sock_ip_recv__aux());
CALL(test_sock_ip_recv_buf__success()); CALL(test_sock_ip_recv_buf__success());
_prepare_send_checks(); _prepare_send_checks();
CALL(test_sock_ip_send__EAFNOSUPPORT_INET()); CALL(test_sock_ip_send__EAFNOSUPPORT_INET());

View File

@ -1,5 +1,11 @@
include ../Makefile.tests_common include ../Makefile.tests_common
AUX_LOCAL ?= 1
ifeq (1, $(AUX_LOCAL))
USEMODULE += sock_aux_local
endif
USEMODULE += gnrc_sock_check_reuse USEMODULE += gnrc_sock_check_reuse
USEMODULE += sock_udp USEMODULE += sock_udp
USEMODULE += gnrc_ipv6 USEMODULE += gnrc_ipv6

View File

@ -423,6 +423,36 @@ static void test_sock_udp_recv__non_blocking(void)
expect(_check_net()); expect(_check_net());
} }
static void test_sock_udp_recv__aux(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
sock_udp_ep_t result;
sock_udp_aux_rx_t aux = { .flags = SOCK_AUX_GET_LOCAL };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
_TEST_NETIF));
expect(sizeof("ABCD") == sock_udp_recv_aux(&_sock, _test_buffer,
sizeof(_test_buffer), 0,
&result, &aux));
expect(AF_INET6 == result.family);
expect(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
expect(_TEST_PORT_REMOTE == result.port);
expect(_TEST_NETIF == result.netif);
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
expect(!(aux.flags & SOCK_AUX_GET_LOCAL));
expect(memcmp(&aux.local.addr, &dst_addr, sizeof(dst_addr)) == 0);
expect(_TEST_PORT_LOCAL == aux.local.port);
#else
expect(aux.flags & SOCK_AUX_GET_LOCAL);
#endif
expect(_check_net());
}
static void test_sock_udp_recv_buf__success(void) static void test_sock_udp_recv_buf__success(void)
{ {
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
@ -751,6 +781,7 @@ int main(void)
CALL(test_sock_udp_recv__unsocketed_with_remote()); CALL(test_sock_udp_recv__unsocketed_with_remote());
CALL(test_sock_udp_recv__with_timeout()); CALL(test_sock_udp_recv__with_timeout());
CALL(test_sock_udp_recv__non_blocking()); CALL(test_sock_udp_recv__non_blocking());
CALL(test_sock_udp_recv__aux());
CALL(test_sock_udp_recv_buf__success()); CALL(test_sock_udp_recv_buf__success());
_prepare_send_checks(); _prepare_send_checks();
CALL(test_sock_udp_send__EAFNOSUPPORT()); CALL(test_sock_udp_send__EAFNOSUPPORT());