Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion arch/arm/src/common/stm32/Kconfig.eth
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ config STM32_ETH_PTP_RTC_HIRES
config STM32_ETH_TIMESTAMP_RX
bool "Hardware timestamping of received packets"
depends on STM32_COMMON_LEGACY && STM32_ETH_PTP && NET_TIMESTAMP && STM32_ETH_ENHANCEDDESC
select ARCH_HAVE_NETDEV_TIMESTAMP
default n
---help---
Timestamp all received Ethernet packets.
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/src/common/stm32/stm32_eth_m3m4_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -4234,6 +4234,10 @@ int stm32_ethinitialize(int intf)
return ret;
}

#ifdef CONFIG_STM32_ETH_TIMESTAMP_RX
priv->dev.d_features |= NETDEV_RX_STAMP;
#endif

/* Register the device with the OS so that socket IOCTLs can be performed */

netdev_register(&priv->dev, NET_LL_ETHERNET);
Expand Down
75 changes: 72 additions & 3 deletions arch/sim/src/sim/sim_netdriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

#include <nuttx/debug.h>
#include <string.h>
#include <time.h>

#include <nuttx/compiler.h>
#include <nuttx/kmalloc.h>
Expand Down Expand Up @@ -109,6 +110,9 @@ struct sim_netdev_s
#endif
uint8_t buf[SIM_NETDEV_BUFSIZE]; /* Used when packet buffer is fragmented */
struct work_s work;
#ifdef CONFIG_NET_TIMESTAMP
netpkt_queue_t tstampq; /* TX timestamp loopback queue */
#endif
};

/****************************************************************************
Expand Down Expand Up @@ -163,6 +167,25 @@ static int netdriver_send(struct netdev_lowerhalf_s *dev, netpkt_t *pkt)
sim_netdev_send(DEVIDX(dev), netpkt_getdata(dev, pkt), len);
}

#ifdef CONFIG_NET_TIMESTAMP
/* If the packet is tagged for TX timestamping, generate a
* software timestamp and loop it back through the RX path
* so the protocol layer can deliver it via MSG_ERRQUEUE.
* Reuse the original pkt directly to avoid clone overhead.
*/

if (pkt->io_conn != NULL)
{
FAR struct sim_netdev_s *priv = (FAR struct sim_netdev_s *)dev;

clock_gettime(CLOCK_REALTIME, &pkt->io_time);
iob_add_queue(pkt, &priv->tstampq);
atomic_add(&dev->quota_ptr[NETPKT_TX], 1);
netdev_lower_rxready(dev);
return OK;
}
#endif

netpkt_free(dev, pkt, NETPKT_TX);
return OK;
}
Expand All @@ -172,6 +195,26 @@ static netpkt_t *netdriver_recv(struct netdev_lowerhalf_s *dev)
netpkt_t *pkt = NULL;
unsigned int len;

#ifdef CONFIG_NET_TIMESTAMP
/* Return any TX timestamp loopback packets first.
* Fast-path: skip locking when the queue is empty.
*/

FAR struct sim_netdev_s *priv = (FAR struct sim_netdev_s *)dev;

if (!IOB_QEMPTY(&priv->tstampq))
{
netdev_lock(&dev->netdev);
pkt = iob_remove_queue(&priv->tstampq);
netdev_unlock(&dev->netdev);
if (pkt != NULL)
{
atomic_sub(&dev->quota_ptr[NETPKT_RX], 1);
return pkt;
}
}
#endif

if (sim_netdev_avail(DEVIDX(dev)))
{
pkt = netpkt_alloc(dev, NETPKT_RX);
Expand Down Expand Up @@ -237,8 +280,23 @@ static int netdriver_ifup(struct netdev_lowerhalf_s *dev)

static int netdriver_ifdown(struct netdev_lowerhalf_s *dev)
{
#ifdef CONFIG_NET_TIMESTAMP
/* Drain any pending TX timestamp loopback packets.
* Detach the entire queue under lock, then free outside.
*/

FAR struct sim_netdev_s *priv = (FAR struct sim_netdev_s *)dev;
FAR netpkt_t *pkt;

while ((pkt = iob_remove_queue(&priv->tstampq)) != NULL)
{
netpkt_free(dev, pkt, NETPKT_TX);
}
#endif

netdev_lower_carrier_off(dev);
sim_netdev_ifdown(DEVIDX(dev));

return OK;
}

Expand All @@ -259,12 +317,14 @@ static int netdriver_rmmac(struct netdev_lowerhalf_s *dev,
static void netdriver_txdone_interrupt(void *priv)
{
struct netdev_lowerhalf_s *dev = (struct netdev_lowerhalf_s *)priv;

netdev_lower_txdone(dev);
}

static void netdriver_rxready_interrupt(void *priv)
{
struct netdev_lowerhalf_s *dev = (struct netdev_lowerhalf_s *)priv;

netdev_lower_rxready(dev);
}

Expand All @@ -273,7 +333,11 @@ static void sim_netdev_work(void *arg)
struct sim_netdev_s *priv = (struct sim_netdev_s *)arg;
struct netdev_lowerhalf_s *dev = (struct netdev_lowerhalf_s *)&priv->dev;

if (sim_netdev_avail(DEVIDX(dev)))
if (sim_netdev_avail(DEVIDX(dev))
#ifdef CONFIG_NET_TIMESTAMP
|| !IOB_QEMPTY(&priv->tstampq)
#endif
)
{
netdev_lower_rxready(dev);
}
Expand Down Expand Up @@ -347,15 +411,20 @@ void sim_netdriver_setmacaddr(int devidx, unsigned char *macaddr)
void sim_netdriver_setmtu(int devidx, int mtu)
{
IDXDEV(devidx)->netdev.d_pktsize = MIN(SIM_NETDEV_BUFSIZE,
mtu + ETH_HDRLEN);
mtu + ETH_HDRLEN);
}

void sim_netdriver_loop(void)
{
int devidx;

for (devidx = 0; devidx < CONFIG_SIM_NETDEV_NUMBER; devidx++)
{
if (sim_netdev_avail(devidx))
if (sim_netdev_avail(devidx)
#ifdef CONFIG_NET_TIMESTAMP
|| !IOB_QEMPTY(&g_sim_dev[devidx].tstampq)
#endif
)
{
netdev_lower_rxready(IDXDEV(devidx));
}
Expand Down
1 change: 0 additions & 1 deletion boards/arm/imx9/imx95-evk/configs/can/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ CONFIG_NET_CAN_EXTID=y
CONFIG_NET_CAN_NOTIFIER=y
CONFIG_NET_CAN_RAW_TX_DEADLINE=y
CONFIG_NET_CAN_SOCK_OPTS=y
CONFIG_NET_LL_GUARDSIZE=14
CONFIG_NET_TIMESTAMP=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
Expand Down
16 changes: 16 additions & 0 deletions include/nuttx/mm/iob.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
# include <nuttx/wqueue.h>
#endif

#ifdef CONFIG_NET_TIMESTAMP
# include <sys/time.h>
#endif

#ifdef CONFIG_MM_IOB

/****************************************************************************
Expand Down Expand Up @@ -126,6 +130,18 @@ struct iob_s
#endif
unsigned int io_pktlen; /* Total length of the packet */

FAR struct socket_conn_s *io_conn;

#ifdef CONFIG_NET_TIMESTAMP
/* timestamp of the packet.
* d_features is the member of net_driver_s struct, if the NETDEV_RX_STAMP
* bit of d_features is set, the timestamp is provided by hardware driver.
* Otherwise it is filled in by kernel when the packet is passed into
* respective protocol layer. The timestamp is in CLOCK_REALTIME.
*/

struct timespec io_time;
#endif
#ifdef CONFIG_IOB_ALLOC
iob_free_cb_t io_free; /* Custom free callback */
FAR uint8_t *io_data;
Expand Down
6 changes: 4 additions & 2 deletions include/nuttx/net/netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@

#define NETDEV_TX_CSUM (1 << 1) /* Netdev support hardware tx checksum */
#define NETDEV_RX_CSUM (1 << 2) /* Netdev support hardware rx checksum */
#define NETDEV_RX_STAMP (1 << 3) /* Netdev support hardware timestamp */

/* Determine the largest possible address */

Expand Down Expand Up @@ -527,9 +528,10 @@ struct net_driver_s
/* Reception timestamp of packet being currently processed.
* If CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP is true, the timestamp is provided
* by hardware driver. Otherwise it is filled in by kernel when packet
* enters ipv4_input or ipv6_input.
* enters ipv4_input or ipv6_input. The timestamp is in CLOCK_REALTIME.
*
* The timestamp is in CLOCK_REALTIME.
* d_rxtime is serviced for older netdev driver.
* d_rxtime will be replaced by iob->io_tstamp in net stack.
*/

struct timespec d_rxtime;
Expand Down
30 changes: 22 additions & 8 deletions include/sys/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,22 @@
#define SO_TIMESTAMPNS 20 /* Generates a timestamp in ns for each incoming packet
* arg: integer value
*/
#define SO_TIMESTAMPING 21 /* Generates timestamp for each output packet
*/

/* Protocol-level socket options may begin with this value */

#define __SO_PROTOCOL 16

/* Timestamp generation */

#define SOF_TIMESTAMPING_TX_HARDWARE (1 << SO_TIMESTAMPING)
#define SOF_TIMESTAMPING_TX_SOFTWARE SOF_TIMESTAMPING_TX_HARDWARE

/* Timestamp reporting */

#define SOF_TIMESTAMPING_SOFTWARE SOF_TIMESTAMPING_TX_SOFTWARE
#define SOF_TIMESTAMPING_RAW_HARDWARE SOF_TIMESTAMPING_TX_HARDWARE

/* The options are unsupported but included for compatibility
* and portability
Expand All @@ -249,10 +265,6 @@

#define SOL_PACKET 19

/* Protocol-level socket options may begin with this value */

#define __SO_PROTOCOL 16

/* Values for the 'how' argument of shutdown() */

#define SHUT_RD 1 /* Bit 0: Disables further receive operations */
Expand Down Expand Up @@ -297,10 +309,12 @@

/* "Socket"-level control message types: */

#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */
#define SCM_CREDENTIALS 0x02 /* rw: struct ucred */
#define SCM_SECURITY 0x03 /* rw: security label */
#define SCM_TIMESTAMP SO_TIMESTAMP
#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */
#define SCM_CREDENTIALS 0x02 /* rw: struct ucred */
#define SCM_SECURITY 0x03 /* rw: security label */
#define SCM_TIMESTAMP SO_TIMESTAMP
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#define SCM_TIMESTAMPING SO_TIMESTAMPING

/* Desired design of maximum size and alignment (see RFC2553) */

Expand Down
22 changes: 9 additions & 13 deletions mm/iob/iob_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ static FAR struct iob_s *iob_alloc_committed(void)
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */
#ifdef CONFIG_NET_TIMESTAMPING
iob->io_conn = NULL;
#endif
}

spin_unlock_irqrestore(&g_iob_lock, flags);
Expand Down Expand Up @@ -135,6 +138,9 @@ static FAR struct iob_s *iob_tryalloc_internal(bool throttled)
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */
#ifdef CONFIG_NET_TIMESTAMPING
iob->io_conn = NULL;
#endif
return iob;
}
}
Expand Down Expand Up @@ -340,11 +346,8 @@ FAR struct iob_s *iob_alloc_dynamic(uint16_t size)
iob = kmm_memalign(IOB_ALIGNMENT, alignsize);
if (iob)
{
iob->io_flink = NULL; /* Not in a chain */
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
memset(iob, 0, offsetof(struct iob_s, io_data));
iob->io_bufsize = size; /* Total length of the iob buffer */
iob->io_pktlen = 0; /* Total length of the packet */
iob->io_free = iob_free_dynamic; /* Customer free callback */
iob->io_data = (FAR uint8_t *)ALIGN_UP((uintptr_t)(iob + 1),
IOB_ALIGNMENT);
Expand Down Expand Up @@ -383,14 +386,10 @@ FAR struct iob_s *iob_alloc_with_data(FAR void *data, uint16_t size,

DEBUGASSERT(free_cb != NULL);

iob = kmm_malloc(sizeof(struct iob_s));
iob = kmm_zalloc(sizeof(struct iob_s));
if (iob)
{
iob->io_flink = NULL; /* Not in a chain */
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_bufsize = size; /* Total length of the iob buffer */
iob->io_pktlen = 0; /* Total length of the packet */
iob->io_free = free_cb; /* Customer free callback */
iob->io_data = data;
}
Expand Down Expand Up @@ -426,10 +425,7 @@ FAR struct iob_s *iob_init_with_data(FAR void *data, uint16_t size,
{
FAR struct iob_s *iob = (FAR struct iob_s *)data;

iob->io_flink = NULL; /* Not in a chain */
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */
memset(iob, 0, offsetof(struct iob_s, io_data));
iob->io_free = free_cb; /* Customer free callback */
iob->io_data = (FAR uint8_t *)ALIGN_UP((uintptr_t)(iob + 1),
IOB_ALIGNMENT);
Expand Down
4 changes: 4 additions & 0 deletions mm/iob/iob_clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ int iob_clone_partial(FAR struct iob_s *iob1, unsigned int len,

iob2->io_pktlen = len + offset2;

#ifdef CONFIG_NET_TIMESTAMP
iob2->io_time = iob1->io_time;
#endif

/* Handle special case where there are empty buffers at the head
* the list, Skip I/O buffer containing the data offset.
*/
Expand Down
5 changes: 0 additions & 5 deletions net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ config ARCH_HAVE_NETDEV_STATISTICS
bool
default n

config ARCH_HAVE_NETDEV_TIMESTAMP
bool
default n

config NET_WRITE_BUFFERS
bool
default n
Expand Down Expand Up @@ -139,7 +135,6 @@ config NET_LL_GUARDSIZE
int "Data Link Layer(L2) Guard size of Network buffer(IOB)"
default 50 if RNDIS
default 18 if NET_VLAN
default 16 if NET_CAN && NET_TIMESTAMP
default 14 if NET_ETHERNET
default 0
---help---
Expand Down
8 changes: 0 additions & 8 deletions net/can/can_bufpool.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,9 @@
* Pre-processor Definitions
****************************************************************************/

#ifdef CONFIG_NET_TIMESTAMP
# define CAN_BUFFER_SIZE ALIGN_UP(sizeof(struct iob_s) + NET_CAN_PKTSIZE + \
CONFIG_NET_LL_GUARDSIZE + IOB_ALIGNMENT - \
1, IOB_ALIGNMENT)
#else
# define CAN_BUFFER_SIZE ALIGN_UP(sizeof(struct iob_s) + NET_CAN_PKTSIZE + \
IOB_ALIGNMENT - 1, IOB_ALIGNMENT)
#endif

/****************************************************************************
* Private Data
Expand Down Expand Up @@ -117,10 +112,7 @@ FAR struct iob_s *can_iob_clone(FAR struct net_driver_s *dev)
return NULL;
}

#ifdef CONFIG_NET_TIMESTAMP
iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE);
#endif

/* CAN data length is fixed, So when we use iob_clone_partial to copy
* data, we don't have to worry about distributing other iob.
*/
Expand Down
Loading
Loading