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) ...@@ -75,7 +75,7 @@ static void d2n_send(volatile struct cosim_eth_proto_d2n_send *s)
static void poll_d2n(void) 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; uint8_t type;
/* message not ready */ /* message not ready */
...@@ -102,7 +102,7 @@ static void *rx_handler(void *arg) ...@@ -102,7 +102,7 @@ static void *rx_handler(void *arg)
ssize_t len; ssize_t len;
while (1) { while (1) {
msg = netsim_n2d_alloc(&nsif); msg = netsim_n2d_alloc(&nsif, 0, 0);
if (msg == NULL) { if (msg == NULL) {
fprintf(stderr, "coudl not allocate message for rx\n"); fprintf(stderr, "coudl not allocate message for rx\n");
abort(); abort();
......
...@@ -34,9 +34,13 @@ ...@@ -34,9 +34,13 @@
#include <netsim.h> #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 union cosim_eth_proto_n2d *msg_to;
volatile struct cosim_eth_proto_d2n_send *tx; volatile struct cosim_eth_proto_d2n_send *tx;
volatile struct cosim_eth_proto_n2d_recv *rx; volatile struct cosim_eth_proto_n2d_recv *rx;
...@@ -49,7 +53,7 @@ static void move_pkt(struct netsim_interface *from, struct netsim_interface *to) ...@@ -49,7 +53,7 @@ static void move_pkt(struct netsim_interface *from, struct netsim_interface *to)
if (type == COSIM_ETH_PROTO_D2N_MSG_SEND) { if (type == COSIM_ETH_PROTO_D2N_MSG_SEND) {
tx = &msg_from->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) { if (msg_to != NULL) {
rx = &msg_to->recv; rx = &msg_to->recv;
rx->len = tx->len; rx->len = tx->len;
...@@ -73,25 +77,47 @@ static void move_pkt(struct netsim_interface *from, struct netsim_interface *to) ...@@ -73,25 +77,47 @@ static void move_pkt(struct netsim_interface *from, struct netsim_interface *to)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct netsim_interface nsif_a, nsif_b; 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) { if (argc != 3) {
fprintf(stderr, "Usage: net_tap SOCKET-A SOCKET-B\n"); fprintf(stderr, "Usage: net_tap SOCKET-A SOCKET-B\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
sync = 0; sync_a = sync_b = 1;
if (netsim_init(&nsif_a, argv[1], &sync) != 0) { if (netsim_init(&nsif_a, argv[1], &sync_a) != 0) {
return -1; return -1;
} }
if (netsim_init(&nsif_b, argv[2], &sync) != 0) { if (netsim_init(&nsif_b, argv[2], &sync_b) != 0) {
return -1; return -1;
} }
printf("start polling\n"); printf("start polling\n");
while (1) { while (1) {
move_pkt(&nsif_a, &nsif_b); if (netsim_n2d_sync(&nsif_a, cur_ts, ETH_LATENCY, SYNC_PERIOD) != 0) {
move_pkt(&nsif_b, &nsif_a); 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; return 0;
} }
...@@ -33,11 +33,15 @@ struct netsim_interface { ...@@ -33,11 +33,15 @@ struct netsim_interface {
size_t d2n_pos; size_t d2n_pos;
size_t d2n_elen; size_t d2n_elen;
size_t d2n_enum; size_t d2n_enum;
uint64_t d2n_timestamp;
uint8_t *n2d_queue; uint8_t *n2d_queue;
size_t n2d_pos; size_t n2d_pos;
size_t n2d_elen; size_t n2d_elen;
size_t n2d_enum; size_t n2d_enum;
uint64_t n2d_timestamp;
int sync;
}; };
int netsim_init(struct netsim_interface *nsif, int netsim_init(struct netsim_interface *nsif,
...@@ -45,11 +49,18 @@ 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); void netsim_cleanup(struct netsim_interface *nsif);
volatile union cosim_eth_proto_d2n *netsim_d2n_poll( 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, void netsim_d2n_done(struct netsim_interface *nsif,
volatile union cosim_eth_proto_d2n *msg); volatile union cosim_eth_proto_d2n *msg);
volatile union cosim_eth_proto_n2d *netsim_n2d_alloc( 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_ */ #endif /* ndef COSIM_NETSIM_H_ */
...@@ -62,8 +62,12 @@ int netsim_init(struct netsim_interface *nsif, ...@@ -62,8 +62,12 @@ int netsim_init(struct netsim_interface *nsif,
} }
close(shm_fd); 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; *sync_eth = 0;
nsif->sync = 1;
} else {
nsif->sync = *sync_eth;
}
nsif->d2n_queue = (uint8_t *) p + di.d2n_offset; nsif->d2n_queue = (uint8_t *) p + di.d2n_offset;
nsif->n2d_queue = (uint8_t *) p + di.n2d_offset; nsif->n2d_queue = (uint8_t *) p + di.n2d_offset;
...@@ -72,6 +76,7 @@ int netsim_init(struct netsim_interface *nsif, ...@@ -72,6 +76,7 @@ int netsim_init(struct netsim_interface *nsif,
nsif->d2n_enum = di.d2n_nentries; nsif->d2n_enum = di.d2n_nentries;
nsif->n2d_enum = di.n2d_nentries; nsif->n2d_enum = di.n2d_nentries;
nsif->d2n_pos = nsif->n2d_pos = 0; nsif->d2n_pos = nsif->n2d_pos = 0;
nsif->d2n_timestamp = nsif->n2d_timestamp = 0;
return 0; return 0;
} }
...@@ -83,7 +88,7 @@ void netsim_cleanup(struct netsim_interface *nsif) ...@@ -83,7 +88,7 @@ void netsim_cleanup(struct netsim_interface *nsif)
} }
volatile union cosim_eth_proto_d2n *netsim_d2n_poll( 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 *msg =
(volatile union cosim_eth_proto_d2n *) (volatile union cosim_eth_proto_d2n *)
...@@ -94,6 +99,11 @@ volatile union cosim_eth_proto_d2n *netsim_d2n_poll( ...@@ -94,6 +99,11 @@ volatile union cosim_eth_proto_d2n *netsim_d2n_poll(
COSIM_ETH_PROTO_D2N_OWN_NET) COSIM_ETH_PROTO_D2N_OWN_NET)
return NULL; 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; nsif->d2n_pos = (nsif->d2n_pos + 1) % nsif->d2n_enum;
return msg; return msg;
} }
...@@ -106,7 +116,8 @@ void netsim_d2n_done(struct netsim_interface *nsif, ...@@ -106,7 +116,8 @@ void netsim_d2n_done(struct netsim_interface *nsif,
} }
volatile union cosim_eth_proto_n2d *netsim_n2d_alloc( 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 *msg =
(volatile union cosim_eth_proto_n2d *) (volatile union cosim_eth_proto_n2d *)
...@@ -118,6 +129,30 @@ volatile union cosim_eth_proto_n2d *netsim_n2d_alloc( ...@@ -118,6 +129,30 @@ volatile union cosim_eth_proto_n2d *netsim_n2d_alloc(
return NULL; return NULL;
} }
msg->dummy.timestamp = timestamp + latency;
nsif->n2d_timestamp = timestamp;
nsif->n2d_pos = (nsif->n2d_pos + 1) % nsif->n2d_enum; nsif->n2d_pos = (nsif->n2d_pos + 1) % nsif->n2d_enum;
return msg; 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