Commit c35116cf authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

netsim_common,tap,wire: support for sync ethernet

parent d0d64b5d
......@@ -75,7 +75,7 @@ static void d2n_send(volatile struct cosim_eth_proto_d2n_send *s)
static void poll_d2n(void)
{
volatile union cosim_eth_proto_d2n *msg = netsim_d2n_poll(&nsif);
volatile union cosim_eth_proto_d2n *msg = netsim_d2n_poll(&nsif, 0);
uint8_t type;
/* message not ready */
......@@ -102,7 +102,7 @@ static void *rx_handler(void *arg)
ssize_t len;
while (1) {
msg = netsim_n2d_alloc(&nsif);
msg = netsim_n2d_alloc(&nsif, 0, 0);
if (msg == NULL) {
fprintf(stderr, "coudl not allocate message for rx\n");
abort();
......
......@@ -34,9 +34,13 @@
#include <netsim.h>
static void move_pkt(struct netsim_interface *from, struct netsim_interface *to)
#define SYNC_PERIOD (500 * 1000ULL) // 100ns
#define ETH_LATENCY (1 * 1000 * 1000ULL) // 1us
static void move_pkt(uint64_t cur_ts, struct netsim_interface *from,
struct netsim_interface *to)
{
volatile union cosim_eth_proto_d2n *msg_from = netsim_d2n_poll(from);
volatile union cosim_eth_proto_d2n *msg_from = netsim_d2n_poll(from, cur_ts);
volatile union cosim_eth_proto_n2d *msg_to;
volatile struct cosim_eth_proto_d2n_send *tx;
volatile struct cosim_eth_proto_n2d_recv *rx;
......@@ -49,7 +53,7 @@ static void move_pkt(struct netsim_interface *from, struct netsim_interface *to)
if (type == COSIM_ETH_PROTO_D2N_MSG_SEND) {
tx = &msg_from->send;
msg_to = netsim_n2d_alloc(to);
msg_to = netsim_n2d_alloc(to, cur_ts, ETH_LATENCY);
if (msg_to != NULL) {
rx = &msg_to->recv;
rx->len = tx->len;
......@@ -73,25 +77,47 @@ static void move_pkt(struct netsim_interface *from, struct netsim_interface *to)
int main(int argc, char *argv[])
{
struct netsim_interface nsif_a, nsif_b;
int sync;
uint64_t cur_ts = 0, ts_a, ts_b;
int sync_a, sync_b;
if (argc != 3) {
fprintf(stderr, "Usage: net_tap SOCKET-A SOCKET-B\n");
return EXIT_FAILURE;
}
sync = 0;
if (netsim_init(&nsif_a, argv[1], &sync) != 0) {
sync_a = sync_b = 1;
if (netsim_init(&nsif_a, argv[1], &sync_a) != 0) {
return -1;
}
if (netsim_init(&nsif_b, argv[2], &sync) != 0) {
if (netsim_init(&nsif_b, argv[2], &sync_b) != 0) {
return -1;
}
printf("start polling\n");
while (1) {
move_pkt(&nsif_a, &nsif_b);
move_pkt(&nsif_b, &nsif_a);
if (netsim_n2d_sync(&nsif_a, cur_ts, ETH_LATENCY, SYNC_PERIOD) != 0) {
fprintf(stderr, "netsim_n2d_sync(nsif_a) failed\n");
abort();
}
if (netsim_n2d_sync(&nsif_b, cur_ts, ETH_LATENCY, SYNC_PERIOD) != 0) {
fprintf(stderr, "netsim_n2d_sync(nsif_a) failed\n");
abort();
}
do {
move_pkt(cur_ts, &nsif_a, &nsif_b);
move_pkt(cur_ts, &nsif_b, &nsif_a);
ts_a = netsim_n2d_timestamp(&nsif_a);
ts_b = netsim_n2d_timestamp(&nsif_b);
} while ((sync_a && ts_a <= cur_ts) ||
(sync_b && ts_b <= cur_ts));
if (sync_a && sync_b)
cur_ts = (ts_a <= ts_b ? ts_a : ts_b);
else if (sync_a)
cur_ts = ts_a;
else if (sync_b)
cur_ts = ts_b;
}
return 0;
}
......@@ -33,11 +33,15 @@ struct netsim_interface {
size_t d2n_pos;
size_t d2n_elen;
size_t d2n_enum;
uint64_t d2n_timestamp;
uint8_t *n2d_queue;
size_t n2d_pos;
size_t n2d_elen;
size_t n2d_enum;
uint64_t n2d_timestamp;
int sync;
};
int netsim_init(struct netsim_interface *nsif,
......@@ -45,11 +49,18 @@ int netsim_init(struct netsim_interface *nsif,
void netsim_cleanup(struct netsim_interface *nsif);
volatile union cosim_eth_proto_d2n *netsim_d2n_poll(
struct netsim_interface *nsif);
struct netsim_interface *nsif, uint64_t timestamp);
void netsim_d2n_done(struct netsim_interface *nsif,
volatile union cosim_eth_proto_d2n *msg);
volatile union cosim_eth_proto_n2d *netsim_n2d_alloc(
struct netsim_interface *nsif);
struct netsim_interface *nsif, uint64_t timestamp,
uint64_t latency);
int netsim_n2d_sync(struct netsim_interface *nsif, uint64_t timestamp,
uint64_t latency, uint64_t sync_delay);
static inline uint64_t netsim_n2d_timestamp(struct netsim_interface *nsif)
{
return nsif->n2d_timestamp;
}
#endif /* ndef COSIM_NETSIM_H_ */
......@@ -62,8 +62,12 @@ int netsim_init(struct netsim_interface *nsif,
}
close(shm_fd);
if ((di.flags & COSIM_ETH_PROTO_FLAGS_DI_SYNC) == 0)
if ((di.flags & COSIM_ETH_PROTO_FLAGS_DI_SYNC) == 0) {
*sync_eth = 0;
nsif->sync = 1;
} else {
nsif->sync = *sync_eth;
}
nsif->d2n_queue = (uint8_t *) p + di.d2n_offset;
nsif->n2d_queue = (uint8_t *) p + di.n2d_offset;
......@@ -72,6 +76,7 @@ int netsim_init(struct netsim_interface *nsif,
nsif->d2n_enum = di.d2n_nentries;
nsif->n2d_enum = di.n2d_nentries;
nsif->d2n_pos = nsif->n2d_pos = 0;
nsif->d2n_timestamp = nsif->n2d_timestamp = 0;
return 0;
}
......@@ -83,7 +88,7 @@ void netsim_cleanup(struct netsim_interface *nsif)
}
volatile union cosim_eth_proto_d2n *netsim_d2n_poll(
struct netsim_interface *nsif)
struct netsim_interface *nsif, uint64_t timestamp)
{
volatile union cosim_eth_proto_d2n *msg =
(volatile union cosim_eth_proto_d2n *)
......@@ -94,6 +99,11 @@ volatile union cosim_eth_proto_d2n *netsim_d2n_poll(
COSIM_ETH_PROTO_D2N_OWN_NET)
return NULL;
/* if in sync mode, wait till message is ready */
nsif->d2n_timestamp = msg->dummy.timestamp;
if (nsif->sync && nsif->d2n_timestamp > timestamp)
return NULL;
nsif->d2n_pos = (nsif->d2n_pos + 1) % nsif->d2n_enum;
return msg;
}
......@@ -106,7 +116,8 @@ void netsim_d2n_done(struct netsim_interface *nsif,
}
volatile union cosim_eth_proto_n2d *netsim_n2d_alloc(
struct netsim_interface *nsif)
struct netsim_interface *nsif, uint64_t timestamp,
uint64_t latency)
{
volatile union cosim_eth_proto_n2d *msg =
(volatile union cosim_eth_proto_n2d *)
......@@ -118,6 +129,30 @@ volatile union cosim_eth_proto_n2d *netsim_n2d_alloc(
return NULL;
}
msg->dummy.timestamp = timestamp + latency;
nsif->n2d_timestamp = timestamp;
nsif->n2d_pos = (nsif->n2d_pos + 1) % nsif->n2d_enum;
return msg;
}
int netsim_n2d_sync(struct netsim_interface *nsif, uint64_t timestamp,
uint64_t latency, uint64_t sync_delay)
{
volatile union cosim_eth_proto_n2d *msg;
volatile struct cosim_eth_proto_n2d_sync *sync;
if (nsif->n2d_timestamp != 0 &&
timestamp - nsif->n2d_timestamp < sync_delay)
return 0;
msg = netsim_n2d_alloc(nsif, timestamp, latency);
if (msg == NULL)
return -1;
sync = &msg->sync;
// WMB();
sync->own_type = COSIM_ETH_PROTO_N2D_MSG_SYNC | COSIM_ETH_PROTO_N2D_OWN_DEV;
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment