mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #15560 from maribu/gnrc-aux-rx-timestamps
net/gnrc/sock: Implement sock_aux_timestamp for RX
This commit is contained in:
commit
08d86295d2
@ -43,6 +43,7 @@ PSEUDOMODULES += gnrc_netapi_callbacks
|
||||
PSEUDOMODULES += gnrc_netapi_mbox
|
||||
PSEUDOMODULES += gnrc_netif_bus
|
||||
PSEUDOMODULES += gnrc_netif_events
|
||||
PSEUDOMODULES += gnrc_netif_timestamp
|
||||
PSEUDOMODULES += gnrc_pktbuf_cmd
|
||||
PSEUDOMODULES += gnrc_netif_6lo
|
||||
PSEUDOMODULES += gnrc_netif_ipv6
|
||||
|
@ -185,6 +185,9 @@ endif
|
||||
|
||||
ifneq (,$(filter gnrc_sock_%,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sock
|
||||
ifneq (,$(filter sock_aux_timestamp,$(USEMODULE)))
|
||||
USEMODULE += gnrc_netif_timestamp
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sock_async,$(USEMODULE)))
|
||||
|
@ -88,6 +88,17 @@ extern "C" {
|
||||
* @ref IEEE802154_FCF_FRAME_PEND
|
||||
*/
|
||||
#define GNRC_NETIF_HDR_FLAGS_MORE_DATA (0x10)
|
||||
|
||||
/**
|
||||
* @brief Indicate presence of a valid timestamp
|
||||
*
|
||||
* @details If (and only if) module `gnrc_netif_timestamp` is used and the
|
||||
* network device supplied the timestamp of reception of a frame, this
|
||||
* timestamp is passed up the network stack through
|
||||
* @ref gnrc_netif_hdr_t::timestamp and this flag is set. This flag
|
||||
* can be used to check for presence of a valid timestamp.
|
||||
*/
|
||||
#define GNRC_NETIF_HDR_FLAGS_TIMESTAMP (0x08)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -105,6 +116,24 @@ typedef struct {
|
||||
uint8_t flags; /**< flags as defined above */
|
||||
uint8_t lqi; /**< lqi of received packet (optional) */
|
||||
int16_t rssi; /**< rssi of received packet in dBm (optional) */
|
||||
#if IS_USED(MODULE_GNRC_NETIF_TIMESTAMP) || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Timestamp of reception in nanoseconds since epoch
|
||||
*
|
||||
* @note Only when @ref GNRC_NETIF_HDR_FLAGS_TIMESTAMP is set, this
|
||||
* field contains valid info.
|
||||
*
|
||||
* This field is only provided if module `gnrc_netif_timestamp` is used.
|
||||
* Keep in mind that when the hardware does not provide timestamping, the
|
||||
* network device driver could choose to provide this in software, which
|
||||
* adds the delay and jitter of the ISR handling to the timestamp. Please
|
||||
* keep also in mind that a hardware implementation might not be able to
|
||||
* reliable timestamp every frame - e.g. a full-duplex wired interface might
|
||||
* be unable to timestamp a received frame while timestamping an outgoing
|
||||
* frame.
|
||||
*/
|
||||
uint64_t timestamp;
|
||||
#endif /* MODULE_GNRC_NETIF_TIMESTAMP */
|
||||
} gnrc_netif_hdr_t;
|
||||
|
||||
/**
|
||||
@ -201,6 +230,50 @@ static inline void gnrc_netif_hdr_set_dst_addr(gnrc_netif_hdr_t *hdr,
|
||||
memcpy(((uint8_t *)(hdr + 1)) + hdr->src_l2addr_len, addr, addr_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the timestamp in the netif header
|
||||
* @param[out] hdr Header to set the timestamp in
|
||||
* @param[in] timestamp Timestamp to set (nanoseconds since epoch)
|
||||
*
|
||||
* @details If the module gnrc_netif_timestamp is not used, a call to this
|
||||
* function become a non-op (and will be fully optimized out by the
|
||||
* compiler)
|
||||
*/
|
||||
static inline void gnrc_netif_hdr_set_timestamp(gnrc_netif_hdr_t *hdr,
|
||||
uint64_t timestamp)
|
||||
{
|
||||
(void)hdr;
|
||||
(void)timestamp;
|
||||
#if IS_USED(MODULE_GNRC_NETIF_TIMESTAMP)
|
||||
hdr->timestamp = timestamp;
|
||||
hdr->flags |= GNRC_NETIF_HDR_FLAGS_TIMESTAMP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the timestamp of the frame in nanoseconds since epoch
|
||||
* @param[in] hdr Header to read the timestamp from
|
||||
* @param[out] dest The timestamp will be stored here
|
||||
* @retval 0 The timestamp was stored in @p dest
|
||||
* @retval -1 No timestamp available, @p dest is unchanged
|
||||
*
|
||||
* @details If the module gnrc_netif_timestamp is not used, this will always
|
||||
* return 0
|
||||
*/
|
||||
static inline int gnrc_netif_hdr_get_timestamp(const gnrc_netif_hdr_t *hdr,
|
||||
uint64_t *dest)
|
||||
{
|
||||
(void)hdr;
|
||||
(void)dest;
|
||||
#if IS_USED(MODULE_GNRC_NETIF_TIMESTAMP)
|
||||
if (hdr->flags & GNRC_NETIF_HDR_FLAGS_TIMESTAMP) {
|
||||
*dest = hdr->timestamp;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(MODULE_GNRC_IPV6) || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Converts the source address of a given @ref net_gnrc_netif_hdr to
|
||||
|
@ -90,7 +90,7 @@ 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,
|
||||
uint32_t timeout, sock_ip_ep_t *remote,
|
||||
gnrc_sock_recv_aux_t aux)
|
||||
gnrc_sock_recv_aux_t *aux)
|
||||
{
|
||||
/* only used when some sock_aux_% module is used */
|
||||
(void)aux;
|
||||
@ -154,9 +154,9 @@ ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out,
|
||||
memcpy(&remote->addr, &ipv6_hdr->src, sizeof(ipv6_addr_t));
|
||||
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;
|
||||
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);
|
||||
@ -167,6 +167,13 @@ ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out,
|
||||
gnrc_netif_hdr_t *netif_hdr = netif->data;
|
||||
/* TODO: use API in #5511 */
|
||||
remote->netif = (uint16_t)netif_hdr->if_pid;
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP)
|
||||
if (aux->timestamp != NULL) {
|
||||
if (gnrc_netif_hdr_get_timestamp(netif_hdr, aux->timestamp) == 0) {
|
||||
aux->flags |= GNRC_SOCK_RECV_AUX_FLAG_TIMESTAMP;
|
||||
}
|
||||
}
|
||||
#endif /* MODULE_SOCK_AUX_TIMESTAMP */
|
||||
}
|
||||
*pkt_out = pkt; /* set out parameter */
|
||||
|
||||
|
@ -70,18 +70,17 @@ typedef struct {
|
||||
*/
|
||||
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;
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP) || DOXYGEN
|
||||
uint64_t *timestamp; /**< timestamp PDU was received at in nanoseconds */
|
||||
#endif
|
||||
/**
|
||||
* @brief Flags
|
||||
*/
|
||||
uint8_t flags;
|
||||
} gnrc_sock_recv_aux_t;
|
||||
|
||||
#define GNRC_SOCK_RECV_AUX_FLAG_TIMESTAMP 0x01 /**< Timestamp valid */
|
||||
|
||||
/**
|
||||
* @brief Internal helper functions for GNRC
|
||||
* @internal
|
||||
@ -143,7 +142,7 @@ void gnrc_sock_create(gnrc_sock_reg_t *reg, gnrc_nettype_t type, uint32_t demux_
|
||||
* @internal
|
||||
*/
|
||||
ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt, uint32_t timeout,
|
||||
sock_ip_ep_t *remote, gnrc_sock_recv_aux_t aux);
|
||||
sock_ip_ep_t *remote, gnrc_sock_recv_aux_t *aux);
|
||||
|
||||
/**
|
||||
* @brief Send a packet internally
|
||||
|
@ -135,7 +135,12 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
|
||||
_aux.local = &aux->local;
|
||||
}
|
||||
#endif
|
||||
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, _aux);
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP)
|
||||
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_TIMESTAMP)) {
|
||||
_aux.timestamp = &aux->timestamp;
|
||||
}
|
||||
#endif
|
||||
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, &_aux);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
@ -156,6 +161,16 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
|
||||
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
|
||||
aux->flags &= ~(SOCK_AUX_GET_LOCAL);
|
||||
}
|
||||
#endif
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP)
|
||||
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_TIMESTAMP)) {
|
||||
/* check if network interface did provide a timestamp; this depends on
|
||||
* hardware support. A timestamp of zero is used to indicate a missing
|
||||
* timestamp */
|
||||
if (aux->timestamp > 0) {
|
||||
aux->flags &= ~SOCK_AUX_GET_TIMESTAMP;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*data = pkt->data;
|
||||
*buf_ctx = pkt;
|
||||
|
@ -224,7 +224,12 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
|
||||
_aux.local = (sock_ip_ep_t *)&aux->local;
|
||||
}
|
||||
#endif
|
||||
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, _aux);
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP)
|
||||
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_TIMESTAMP)) {
|
||||
_aux.timestamp = &aux->timestamp;
|
||||
}
|
||||
#endif
|
||||
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, &_aux);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
@ -251,6 +256,16 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
|
||||
aux->flags &= ~SOCK_AUX_GET_LOCAL;
|
||||
aux->local.port = sock->local.port;
|
||||
}
|
||||
#endif
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP)
|
||||
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_TIMESTAMP)) {
|
||||
/* check if network interface did provide a timestamp; this depends on
|
||||
* hardware support. A timestamp of zero is used to indicate a missing
|
||||
* timestamp */
|
||||
if (_aux.flags & GNRC_SOCK_RECV_AUX_FLAG_TIMESTAMP) {
|
||||
aux->flags &= ~SOCK_AUX_GET_TIMESTAMP;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*data = pkt->data;
|
||||
*buf_ctx = pkt;
|
||||
|
@ -1,11 +1,16 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
AUX_LOCAL ?= 1
|
||||
AUX_TIMESTAMP ?= 1
|
||||
|
||||
ifeq (1, $(AUX_LOCAL))
|
||||
USEMODULE += sock_aux_local
|
||||
endif
|
||||
|
||||
ifeq (1, $(AUX_LOCAL))
|
||||
USEMODULE += sock_aux_timestamp
|
||||
endif
|
||||
|
||||
USEMODULE += sock_ip
|
||||
USEMODULE += gnrc_ipv6
|
||||
USEMODULE += ps
|
||||
|
@ -349,13 +349,16 @@ 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 };
|
||||
static const inject_aux_t inject_aux = { .timestamp = 42 };
|
||||
sock_ip_ep_t result;
|
||||
sock_ip_aux_rx_t aux = { .flags = SOCK_AUX_GET_LOCAL };
|
||||
sock_ip_aux_rx_t aux = {
|
||||
.flags = SOCK_AUX_GET_LOCAL | SOCK_AUX_GET_TIMESTAMP
|
||||
};
|
||||
|
||||
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(_inject_packet_aux(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||
sizeof("ABCD"), _TEST_NETIF, &inject_aux));
|
||||
expect(sizeof("ABCD") == sock_ip_recv_aux(&_sock, _test_buffer,
|
||||
sizeof(_test_buffer), 0, &result,
|
||||
&aux));
|
||||
@ -367,6 +370,12 @@ static void test_sock_ip_recv__aux(void)
|
||||
expect(memcmp(&aux.local.addr, &dst_addr, sizeof(dst_addr)) == 0);
|
||||
#else
|
||||
expect(aux.flags & SOCK_AUX_GET_LOCAL);
|
||||
#endif
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP)
|
||||
expect(!(aux.flags & SOCK_AUX_GET_TIMESTAMP));
|
||||
expect(aux.timestamp == inject_aux.timestamp);
|
||||
#else
|
||||
expect(aux.flags & SOCK_AUX_GET_TIMESTAMP);
|
||||
#endif
|
||||
expect(_check_net());
|
||||
}
|
||||
|
@ -41,9 +41,10 @@ void _prepare_send_checks(void)
|
||||
static gnrc_pktsnip_t *_build_ipv6_packet(const ipv6_addr_t *src,
|
||||
const ipv6_addr_t *dst, uint8_t nh,
|
||||
void *data, size_t data_len,
|
||||
uint16_t netif)
|
||||
uint16_t netif,
|
||||
const inject_aux_t *aux)
|
||||
{
|
||||
gnrc_pktsnip_t *netif_hdr, *ipv6, *payload;
|
||||
gnrc_pktsnip_t *netif_hdr_snip, *ipv6, *payload;
|
||||
ipv6_hdr_t *ipv6_hdr;
|
||||
|
||||
if ((netif > INT16_MAX) || (data_len > UINT16_MAX)) {
|
||||
@ -63,21 +64,25 @@ static gnrc_pktsnip_t *_build_ipv6_packet(const ipv6_addr_t *src,
|
||||
ipv6_hdr->nh = nh;
|
||||
ipv6_hdr->hl = 64;
|
||||
payload = gnrc_pkt_append(payload, ipv6);
|
||||
netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
|
||||
if (netif_hdr == NULL) {
|
||||
netif_hdr_snip = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
|
||||
if (netif_hdr_snip == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = (kernel_pid_t)netif;
|
||||
return gnrc_pkt_append(payload, netif_hdr);
|
||||
gnrc_netif_hdr_t *netif_hdr = netif_hdr_snip->data;
|
||||
netif_hdr->if_pid = (kernel_pid_t)netif;
|
||||
if (aux) {
|
||||
gnrc_netif_hdr_set_timestamp(netif_hdr, aux->timestamp);
|
||||
}
|
||||
return gnrc_pkt_append(payload, netif_hdr_snip);
|
||||
}
|
||||
|
||||
|
||||
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint8_t proto, void *data, size_t data_len,
|
||||
uint16_t netif)
|
||||
bool _inject_packet_aux(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint8_t proto, void *data, size_t data_len,
|
||||
uint16_t netif, const inject_aux_t *aux)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = _build_ipv6_packet(src, dst, proto, data, data_len,
|
||||
netif);
|
||||
netif, aux);
|
||||
|
||||
if (pkt == NULL) {
|
||||
return false;
|
||||
|
@ -39,6 +39,31 @@ void _net_init(void);
|
||||
*/
|
||||
void _prepare_send_checks(void);
|
||||
|
||||
/**
|
||||
* @brief Structure containing auxiliary data to inject
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t timestamp; /**< Timestamp of reception */
|
||||
} inject_aux_t;
|
||||
|
||||
/**
|
||||
* @brief Injects a received IPv6 packet into the stack
|
||||
*
|
||||
* @param[in] src The source address of the IPv6 packet
|
||||
* @param[in] dst The destination address of the IPv6 packet
|
||||
* @param[in] proto The next header field of the IPv6 packet
|
||||
* @param[in] data The payload of the IPv6 packet
|
||||
* @param[in] data_len The payload length of the IPv6 packet
|
||||
* @param[in] netif The interface the packet came over
|
||||
* @param[in] aux Auxiliary data to inject
|
||||
*
|
||||
* @return true, if packet was successfully injected
|
||||
* @return false, if an error occurred during injection
|
||||
*/
|
||||
bool _inject_packet_aux(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint8_t proto, void *data, size_t data_len,
|
||||
uint16_t netif, const inject_aux_t *aux);
|
||||
|
||||
/**
|
||||
* @brief Injects a received IPv6 packet into the stack
|
||||
*
|
||||
@ -52,9 +77,13 @@ void _prepare_send_checks(void);
|
||||
* @return true, if packet was successfully injected
|
||||
* @return false, if an error occurred during injection
|
||||
*/
|
||||
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint8_t proto, void *data, size_t data_len,
|
||||
uint16_t netif);
|
||||
static inline bool _inject_packet(const ipv6_addr_t *src,
|
||||
const ipv6_addr_t *dst,
|
||||
uint8_t proto, void *data, size_t data_len,
|
||||
uint16_t netif)
|
||||
{
|
||||
return _inject_packet_aux(src, dst, proto, data, data_len, netif, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks networking state (e.g. packet buffer state)
|
||||
|
@ -1,11 +1,16 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
AUX_LOCAL ?= 1
|
||||
AUX_TIMESTAMP ?= 1
|
||||
|
||||
ifeq (1, $(AUX_LOCAL))
|
||||
USEMODULE += sock_aux_local
|
||||
endif
|
||||
|
||||
ifeq (1, $(AUX_LOCAL))
|
||||
USEMODULE += sock_aux_timestamp
|
||||
endif
|
||||
|
||||
USEMODULE += gnrc_sock_check_reuse
|
||||
USEMODULE += sock_udp
|
||||
USEMODULE += gnrc_ipv6
|
||||
|
@ -429,13 +429,16 @@ static void test_sock_udp_recv__aux(void)
|
||||
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 };
|
||||
static const inject_aux_t inject_aux = { .timestamp = 1337 };
|
||||
sock_udp_ep_t result;
|
||||
sock_udp_aux_rx_t aux = { .flags = SOCK_AUX_GET_LOCAL };
|
||||
sock_udp_aux_rx_t aux = {
|
||||
.flags = SOCK_AUX_GET_LOCAL | SOCK_AUX_GET_TIMESTAMP
|
||||
};
|
||||
|
||||
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(_inject_packet_aux(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||
_TEST_NETIF, &inject_aux));
|
||||
expect(sizeof("ABCD") == sock_udp_recv_aux(&_sock, _test_buffer,
|
||||
sizeof(_test_buffer), 0,
|
||||
&result, &aux));
|
||||
@ -449,6 +452,12 @@ static void test_sock_udp_recv__aux(void)
|
||||
expect(_TEST_PORT_LOCAL == aux.local.port);
|
||||
#else
|
||||
expect(aux.flags & SOCK_AUX_GET_LOCAL);
|
||||
#endif
|
||||
#if IS_USED(MODULE_SOCK_AUX_TIMESTAMP)
|
||||
expect(!(aux.flags & SOCK_AUX_GET_TIMESTAMP));
|
||||
expect(inject_aux.timestamp == aux.timestamp);
|
||||
#else
|
||||
expect(aux.flags & SOCK_AUX_GET_TIMESTAMP);
|
||||
#endif
|
||||
expect(_check_net());
|
||||
}
|
||||
|
@ -47,9 +47,10 @@ static gnrc_pktsnip_t *_build_udp_packet(const ipv6_addr_t *src,
|
||||
const ipv6_addr_t *dst,
|
||||
uint16_t src_port, uint16_t dst_port,
|
||||
void *data, size_t data_len,
|
||||
uint16_t netif)
|
||||
uint16_t netif,
|
||||
const inject_aux_t *aux)
|
||||
{
|
||||
gnrc_pktsnip_t *netif_hdr, *ipv6, *udp;
|
||||
gnrc_pktsnip_t *netif_hdr_snip, *ipv6, *udp;
|
||||
udp_hdr_t *udp_hdr;
|
||||
ipv6_hdr_t *ipv6_hdr;
|
||||
uint16_t csum = 0;
|
||||
@ -86,21 +87,25 @@ static gnrc_pktsnip_t *_build_udp_packet(const ipv6_addr_t *src,
|
||||
udp_hdr->checksum = byteorder_htons(~csum);
|
||||
}
|
||||
udp = gnrc_pkt_append(udp, ipv6);
|
||||
netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
|
||||
if (netif_hdr == NULL) {
|
||||
netif_hdr_snip = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
|
||||
if (netif_hdr_snip == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = (kernel_pid_t)netif;
|
||||
return gnrc_pkt_append(udp, netif_hdr);
|
||||
gnrc_netif_hdr_t *netif_hdr = netif_hdr_snip->data;
|
||||
netif_hdr->if_pid = (kernel_pid_t)netif;
|
||||
if (aux) {
|
||||
gnrc_netif_hdr_set_timestamp(netif_hdr, aux->timestamp);
|
||||
}
|
||||
return gnrc_pkt_append(udp, netif_hdr_snip);
|
||||
}
|
||||
|
||||
|
||||
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint16_t src_port, uint16_t dst_port,
|
||||
void *data, size_t data_len, uint16_t netif)
|
||||
bool _inject_packet_aux(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint16_t src_port, uint16_t dst_port,
|
||||
void *data, size_t data_len, uint16_t netif,
|
||||
const inject_aux_t *aux)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = _build_udp_packet(src, dst, src_port, dst_port,
|
||||
data, data_len, netif);
|
||||
data, data_len, netif, aux);
|
||||
|
||||
if (pkt == NULL) {
|
||||
return false;
|
||||
|
@ -39,6 +39,13 @@ void _net_init(void);
|
||||
*/
|
||||
void _prepare_send_checks(void);
|
||||
|
||||
/**
|
||||
* @brief Auxiliary data to inject
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t timestamp; /**< Timestamp of reception */
|
||||
} inject_aux_t;
|
||||
|
||||
/**
|
||||
* @brief Injects a received UDP packet into the stack
|
||||
*
|
||||
@ -53,9 +60,33 @@ void _prepare_send_checks(void);
|
||||
* @return true, if packet was successfully injected
|
||||
* @return false, if an error occurred during injection
|
||||
*/
|
||||
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint16_t src_port, uint16_t dst_port,
|
||||
void *data, size_t data_len, uint16_t netif);
|
||||
bool _inject_packet_aux(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||
uint16_t src_port, uint16_t dst_port,
|
||||
void *data, size_t data_len, uint16_t netif,
|
||||
const inject_aux_t *aux);
|
||||
|
||||
/**
|
||||
* @brief Injects a received UDP packet into the stack
|
||||
*
|
||||
* @param[in] src The source address of the UDP packet
|
||||
* @param[in] dst The destination address of the UDP packet
|
||||
* @param[in] src_port The source port of the UDP packet
|
||||
* @param[in] dst_port The destination port of the UDP packet
|
||||
* @param[in] data The payload of the UDP packet
|
||||
* @param[in] data_len The payload length of the UDP packet
|
||||
* @param[in] netif The interface the packet came over
|
||||
*
|
||||
* @return true, if packet was successfully injected
|
||||
* @return false, if an error occurred during injection
|
||||
*/
|
||||
static inline bool _inject_packet(const ipv6_addr_t *src,
|
||||
const ipv6_addr_t *dst,
|
||||
uint16_t src_port, uint16_t dst_port,
|
||||
void *data, size_t data_len, uint16_t netif)
|
||||
{
|
||||
return _inject_packet_aux(src, dst, src_port, dst_port, data, data_len,
|
||||
netif, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks networking state (e.g. packet buffer state)
|
||||
|
Loading…
Reference in New Issue
Block a user