mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys/net/gnrc/sock: Add support for RX timestamp
This commit is contained in:
parent
599c2a145e
commit
d95192e97b
@ -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
|
||||
|
@ -179,6 +179,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;
|
||||
|
Loading…
Reference in New Issue
Block a user