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
8 changes: 8 additions & 0 deletions drivers/ethernet/Kconfig.native_posix
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ config ETH_NATIVE_POSIX_DEV_NAME
help
This option sets the TUN/TAP device name in your host system.

config ETH_NATIVE_POSIX_PTP_CLOCK
bool "PTP clock driver support"
default n
select PTP_CLOCK
depends on NET_GPTP
help
Enable PTP clock support.

config ETH_NATIVE_POSIX_RANDOM_MAC
bool "Random MAC address"
depends on ENTROPY_GENERATOR
Expand Down
212 changes: 211 additions & 1 deletion drivers/ethernet/eth_native_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#include <net/net_if.h>
#include <net/ethernet.h>

#if defined(CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK)
#include <ptp_clock.h>
#include <net/gptp.h>
#endif

#include "eth_native_posix_priv.h"
#include "ethernet/eth_stats.h"

Expand Down Expand Up @@ -57,6 +62,9 @@ struct eth_context {
#if defined(CONFIG_NET_STATISTICS_ETHERNET)
struct net_stats_eth stats;
#endif
#if defined(CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK)
struct device *ptp_clock;
#endif
};

NET_STACK_DEFINE(RX_ZETH, eth_rx_stack,
Expand All @@ -72,6 +80,99 @@ static struct eth_context *get_context(struct net_if *iface)
return net_if_get_device(iface)->driver_data;
}

#if defined(CONFIG_NET_GPTP)
static bool need_timestamping(struct gptp_hdr *hdr)
{
switch (hdr->message_type) {
case GPTP_SYNC_MESSAGE:
case GPTP_PATH_DELAY_RESP_MESSAGE:
return true;
default:
return false;
}
}

static struct gptp_hdr *check_gptp_msg(struct net_if *iface,
struct net_pkt *pkt)
{
struct gptp_hdr *gptp_hdr;
u8_t *msg_start;

if (net_pkt_ll_reserve(pkt)) {
msg_start = net_pkt_ll(pkt);
} else {
msg_start = net_pkt_ip_data(pkt);
}

#if defined(CONFIG_NET_VLAN)
if (net_eth_get_vlan_status(iface)) {
struct net_eth_vlan_hdr *hdr_vlan;

hdr_vlan = (struct net_eth_vlan_hdr *)msg_start;
if (ntohs(hdr_vlan->type) != NET_ETH_PTYPE_PTP) {
return NULL;
}

gptp_hdr = (struct gptp_hdr *)(msg_start +
sizeof(struct net_eth_vlan_hdr));
} else
#endif
{
struct net_eth_hdr *hdr;

hdr = (struct net_eth_hdr *)msg_start;
if (ntohs(hdr->type) != NET_ETH_PTYPE_PTP) {
return NULL;
}

gptp_hdr = (struct gptp_hdr *)(msg_start +
sizeof(struct net_eth_hdr));
}

return gptp_hdr;
}

static void update_pkt_priority(struct gptp_hdr *hdr, struct net_pkt *pkt)
{
if (GPTP_IS_EVENT_MSG(hdr->message_type)) {
net_pkt_set_priority(pkt, NET_PRIORITY_CA);
} else {
net_pkt_set_priority(pkt, NET_PRIORITY_IC);
}
}

static void update_gptp(struct net_if *iface, struct net_pkt *pkt,
bool send)
{
struct net_ptp_time timestamp;
struct gptp_hdr *hdr;
int ret;

ret = eth_clock_gettime(&timestamp);
if (ret < 0) {
return;
}

net_pkt_set_timestamp(pkt, &timestamp);

hdr = check_gptp_msg(iface, pkt);
if (!hdr) {
return;
}

if (send) {
ret = need_timestamping(hdr);
if (ret) {
net_if_add_tx_timestamp(pkt);
}
} else {
update_pkt_priority(hdr, pkt);
}
}
#else
#define update_gptp(iface, pkt, send)
#endif /* CONFIG_NET_GPTP */

static int eth_send(struct net_if *iface, struct net_pkt *pkt)
{
struct eth_context *ctx = get_context(iface);
Expand Down Expand Up @@ -105,6 +206,8 @@ static int eth_send(struct net_if *iface, struct net_pkt *pkt)
}
}

update_gptp(iface, pkt, true);

SYS_LOG_DBG("Send pkt %p len %d", pkt, count);

eth_write_data(ctx->dev_fd, ctx->send, count);
Expand Down Expand Up @@ -193,6 +296,15 @@ static int read_data(struct eth_context *ctx, int fd)
net_pkt_set_vlan_tci(pkt, ntohs(hdr_vlan->vlan.tci));
vlan_tag = net_pkt_vlan_tag(pkt);
}

#if CONFIG_NET_TC_RX_COUNT > 1
{
enum net_priority prio;

prio = net_vlan2priority(net_pkt_vlan_priority(pkt));
net_pkt_set_priority(pkt, prio);
}
#endif
}
#endif

Expand All @@ -215,6 +327,8 @@ static int read_data(struct eth_context *ctx, int fd)

SYS_LOG_DBG("Recv pkt %p len %d", pkt, pkt_len);

update_gptp(iface, pkt, false);

if (net_recv_data(iface, pkt) < 0) {
net_pkt_unref(pkt);
}
Expand Down Expand Up @@ -311,9 +425,22 @@ enum ethernet_hw_caps eth_posix_native_get_capabilities(struct device *dev)
{
ARG_UNUSED(dev);

return ETHERNET_HW_VLAN;
return ETHERNET_HW_VLAN
#if defined(CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK)
| ETHERNET_PTP
#endif
;
}

#if defined(CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK)
static struct device *eth_get_ptp_clock(struct device *dev)
{
struct eth_context *context = dev->driver_data;

return context->ptp_clock;
}
#endif

static const struct ethernet_api eth_if_api = {
.iface_api.init = eth_iface_init,
.iface_api.send = eth_send,
Expand All @@ -323,9 +450,92 @@ static const struct ethernet_api eth_if_api = {
#if defined(CONFIG_NET_STATISTICS_ETHERNET)
.stats = &eth_context_data.stats,
#endif
#if defined(CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK)
.get_ptp_clock = eth_get_ptp_clock,
#endif
};

ETH_NET_DEVICE_INIT(eth_native_posix, CONFIG_ETH_NATIVE_POSIX_DRV_NAME,
eth_init, &eth_context_data, NULL,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &eth_if_api,
_ETH_MTU);

#if defined(CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK)
struct ptp_context {
struct eth_context *eth_context;
};

static struct ptp_context ptp_0_context;


static int ptp_clock_set_native_posix(struct device *clk,
struct net_ptp_time *tm)
{
ARG_UNUSED(clk);
ARG_UNUSED(tm);

/* We cannot set the host device time so this function
* does nothing.
*/
Copy link
Member

@aescolar aescolar Jun 28, 2018

Choose a reason for hiding this comment

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

It would not be too difficult to provide you a version of the host device time which could be offset. If you want tell, and I can add you a couple of functions in the timer driver. Same about the 2 functions below

Copy link
Member Author

Choose a reason for hiding this comment

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

Setting the host device time is probably not needed here, at least for now. The reason being that the native_posix target is typically used when testing things and it might not be ok to change the host time in this case. Of course we could make this optional if someone really wishes to have this kind of feature. I am ok if you send a PR that adds this kind of support thou.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, but note that I did not mean that we would change the real host time, but instead that we would provide you a fake time which would be offset compared to the real host one.

Copy link
Member Author

Choose a reason for hiding this comment

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

I misunderstood you then. That kind of fake time would be much welcomed feature so if you have time to add such a feature, I would appreciate that.

Copy link
Member

@aescolar aescolar Jun 29, 2018

Choose a reason for hiding this comment

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

Roger. I added a note in #6044 about it. Hopefully I will have time in the following days to add it.


return 0;
}

static int ptp_clock_get_native_posix(struct device *clk,
struct net_ptp_time *tm)
{
ARG_UNUSED(clk);

return eth_clock_gettime(tm);
}

static int ptp_clock_adjust_native_posix(struct device *clk,
int increment)
{
ARG_UNUSED(clk);
ARG_UNUSED(increment);

/* We cannot adjust the host device time so this function
* does nothing.
*/

return 0;
}

static int ptp_clock_rate_adjust_native_posix(struct device *clk,
float ratio)
{
ARG_UNUSED(clk);
ARG_UNUSED(ratio);

/* We cannot adjust the host device time so this function
* does nothing.
*/

return 0;
}

static const struct ptp_clock_driver_api api = {
.set = ptp_clock_set_native_posix,
.get = ptp_clock_get_native_posix,
.adjust = ptp_clock_adjust_native_posix,
.rate_adjust = ptp_clock_rate_adjust_native_posix,
};

static int ptp_init(struct device *port)
{
struct device *eth_dev = DEVICE_GET(eth_native_posix);
struct eth_context *context = eth_dev->driver_data;
struct ptp_context *ptp_context = port->driver_data;

context->ptp_clock = port;
ptp_context->eth_context = context;

return 0;
}

DEVICE_AND_API_INIT(eth_native_posix_ptp_clock_0, PTP_CLOCK_NAME,
ptp_init, &ptp_0_context, NULL, POST_KERNEL,
CONFIG_APPLICATION_INIT_PRIORITY, &api);

#endif /* CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK */
23 changes: 23 additions & 0 deletions drivers/ethernet/eth_native_posix_adapt.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <time.h>

#ifdef __linux
#include <linux/if_tun.h>
Expand All @@ -38,6 +39,10 @@
#include <sys_clock.h>
#include <logging/sys_log.h>

#if defined(CONFIG_NET_GPTP)
#include <net/gptp.h>
#endif

#include "eth_native_posix_priv.h"

/* Note that we cannot create the TUN/TAP device from the setup script
Expand Down Expand Up @@ -138,3 +143,21 @@ ssize_t eth_write_data(int fd, void *buf, size_t buf_len)
{
return write(fd, buf, buf_len);
}

#if defined(CONFIG_NET_GPTP)
int eth_clock_gettime(struct net_ptp_time *time)
{
struct timespec tp;
int ret;

ret = clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
Copy link
Member

@aescolar aescolar Jun 28, 2018

Choose a reason for hiding this comment

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

looking at this, I would actually think it would be better to not access the host time directly, but to have the timer driver provide you the host time, to have just 1 central place for it.

if (ret < 0) {
return -errno;
}

time->second = tp.tv_sec;
time->nanosecond = tp.tv_nsec;

return 0;
}
#endif /* CONFIG_NET_GPTP */
4 changes: 4 additions & 0 deletions drivers/ethernet/eth_native_posix_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ int eth_wait_data(int fd);
ssize_t eth_read_data(int fd, void *buf, size_t buf_len);
ssize_t eth_write_data(int fd, void *buf, size_t buf_len);

#if defined(CONFIG_NET_GPTP)
int eth_clock_gettime(struct net_ptp_time *time);
#endif

#endif /* _ETH_NATIVE_POSIX_PRIV_H */
6 changes: 6 additions & 0 deletions samples/net/gptp/boards/native_posix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Settings for native_posix ethernet driver
CONFIG_SYS_LOG_ETHERNET_LEVEL=1
CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK=y

#CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y
CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a"