Commit 4e06e719 authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

factor out netsim_common library

parent ce156723
CPPFLAGS += -I../proto CPPFLAGS += -I../proto -I../netsim_common/include
CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3 CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3
LDLIBS += -lpthread LDLIBS += -lpthread
net_tap: net_tap.o net_tap: net_tap.o ../netsim_common/libnetsim_common.a
all: net_tap all: net_tap
......
...@@ -28,109 +28,15 @@ ...@@ -28,109 +28,15 @@
#include <string.h> #include <string.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <cosim_eth_proto.h> #include <netsim.h>
static uint8_t *d2n_queue;
static size_t d2n_pos;
static size_t d2n_elen;
static size_t d2n_enum;
static uint8_t *n2d_queue;
static size_t n2d_pos;
static size_t n2d_elen;
static size_t n2d_enum;
static struct netsim_interface nsif;
static int tap_fd; static int tap_fd;
int uxsocket_connect(const char *path)
{
int fd;
struct sockaddr_un saun;
/* prepare and connect socket */
memset(&saun, 0, sizeof(saun));
saun.sun_family = AF_UNIX;
strcpy(saun.sun_path, path);
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket failed");
return -1;
}
if (connect(fd, (struct sockaddr *) &saun, sizeof(saun)) != 0) {
perror("connect failed");
return -1;
}
return fd;
}
int uxsocket_recv(int fd, void *data, size_t len, int *pfd)
{
int *ppfd;
ssize_t ret;
struct cmsghdr *cmsg;
union {
char buf[CMSG_SPACE(sizeof(int))];
struct cmsghdr align;
} u;
struct iovec iov = {
.iov_base = data,
.iov_len = len,
};
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = u.buf,
.msg_controllen = sizeof(u.buf),
.msg_flags = 0,
};
if ((ret = recvmsg(fd, &msg, 0)) != (ssize_t) len) {
perror("recvmsg failed");
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
ppfd = (int *) CMSG_DATA(cmsg);
if (msg.msg_controllen <= 0 || cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
fprintf(stderr, "accessing ancillary data failed\n");
return -1;
}
*pfd = *ppfd;
return 0;
}
void *shm_map(int shm_fd)
{
void *p;
struct stat statbuf;
if (fstat(shm_fd, &statbuf) != 0) {
perror("shm_map: fstat failed");
return NULL;
}
p = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd,
0);
if (p == MAP_FAILED) {
perror("shm_map: mmap failed");
return NULL;
}
return p;
}
static int tap_open(const char *name) static int tap_open(const char *name)
{ {
struct ifreq ifr; struct ifreq ifr;
...@@ -165,14 +71,11 @@ static void d2n_send(volatile struct cosim_eth_proto_d2n_send *s) ...@@ -165,14 +71,11 @@ 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);
uint8_t type; uint8_t type;
volatile union cosim_eth_proto_d2n *msg =
(volatile union cosim_eth_proto_d2n *)
(d2n_queue + d2n_pos * d2n_elen);
/* message not ready */ /* message not ready */
if ((msg->dummy.own_type & COSIM_ETH_PROTO_D2N_OWN_MASK) != if (msg == NULL)
COSIM_ETH_PROTO_D2N_OWN_NET)
return; return;
type = msg->dummy.own_type & COSIM_ETH_PROTO_D2N_MSG_MASK; type = msg->dummy.own_type & COSIM_ETH_PROTO_D2N_MSG_MASK;
...@@ -185,9 +88,7 @@ static void poll_d2n(void) ...@@ -185,9 +88,7 @@ static void poll_d2n(void)
fprintf(stderr, "poll_d2n: unsupported type=%u\n", type); fprintf(stderr, "poll_d2n: unsupported type=%u\n", type);
} }
msg->dummy.own_type = (msg->dummy.own_type & COSIM_ETH_PROTO_D2N_MSG_MASK) netsim_d2n_done(&nsif, msg);
| COSIM_ETH_PROTO_D2N_OWN_DEV;
d2n_pos = (d2n_pos + 1) % d2n_enum;
} }
static void *rx_handler(void *arg) static void *rx_handler(void *arg)
...@@ -197,18 +98,14 @@ static void *rx_handler(void *arg) ...@@ -197,18 +98,14 @@ static void *rx_handler(void *arg)
ssize_t len; ssize_t len;
while (1) { while (1) {
msg = (volatile union cosim_eth_proto_n2d *) msg = netsim_n2d_alloc(&nsif);
(n2d_queue + n2d_pos * n2d_elen); if (msg == NULL) {
if ((msg->dummy.own_type & COSIM_ETH_PROTO_N2D_OWN_MASK) !=
COSIM_ETH_PROTO_N2D_OWN_NET)
{
fprintf(stderr, "coudl not allocate message for rx\n"); fprintf(stderr, "coudl not allocate message for rx\n");
abort(); abort();
} }
rx = &msg->recv; rx = &msg->recv;
len = read(tap_fd, (void *) rx->data, n2d_elen - sizeof(*msg)); len = read(tap_fd, (void *) rx->data, nsif.n2d_elen - sizeof(*msg));
if (len <= 0) { if (len <= 0) {
perror("rx handler: read failed"); perror("rx handler: read failed");
} }
...@@ -219,16 +116,12 @@ static void *rx_handler(void *arg) ...@@ -219,16 +116,12 @@ static void *rx_handler(void *arg)
// WMB(); // WMB();
rx->own_type = COSIM_ETH_PROTO_N2D_MSG_RECV | rx->own_type = COSIM_ETH_PROTO_N2D_MSG_RECV |
COSIM_ETH_PROTO_N2D_OWN_DEV; COSIM_ETH_PROTO_N2D_OWN_DEV;
n2d_pos = (n2d_pos + 1) % n2d_enum;
} }
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct cosim_eth_proto_dev_intro di; int sync;
struct cosim_eth_proto_net_intro ni;
int cfd, shm_fd;
void *p;
if (argc != 2) { if (argc != 2) {
fprintf(stderr, "Usage: net_tap TAP_DEVICE_NAME\n"); fprintf(stderr, "Usage: net_tap TAP_DEVICE_NAME\n");
...@@ -239,33 +132,12 @@ int main(int argc, char *argv[]) ...@@ -239,33 +132,12 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
if ((cfd = uxsocket_connect("/tmp/cosim-eth")) < 0) { sync = 0;
return -1; if (netsim_init(&nsif, "/tmp/cosim-eth", &sync) != 0) {
} close(tap_fd);
memset(&ni, 0, sizeof(ni));
if (send(cfd, &ni, sizeof(ni), 0) != sizeof(ni)) {
perror("sending net intro failed");
return -1; return -1;
} }
if (uxsocket_recv(cfd, &di, sizeof(di), &shm_fd)) {
return -1;
}
if ((p = shm_map(shm_fd)) == NULL) {
return -1;
}
close(shm_fd);
d2n_queue = (uint8_t *) p + di.d2n_offset;
n2d_queue = (uint8_t *) p + di.n2d_offset;
d2n_elen = di.d2n_elen;
n2d_elen = di.n2d_elen;
d2n_enum = di.d2n_nentries;
n2d_enum = di.n2d_nentries;
d2n_pos = n2d_pos = 0;
pthread_t worker; pthread_t worker;
if (pthread_create(&worker, NULL, rx_handler, NULL) != 0) { if (pthread_create(&worker, NULL, rx_handler, NULL) != 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
......
CPPFLAGS += -I include/ -I../proto/
CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3
all: libnetsim_common.a
libnetsim_common.a: netsim.o utils.o
$(AR) rcs $@ $^
clean:
rm -rf libnetsim_common.a *.o
/*
* Copyright 2020 Max Planck Institute for Software Systems
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef COSIM_NETSIM_H_
#define COSIM_NETSIM_H_
#include <stddef.h>
#include <stdint.h>
#include <cosim_eth_proto.h>
struct netsim_interface {
uint8_t *d2n_queue;
size_t d2n_pos;
size_t d2n_elen;
size_t d2n_enum;
uint8_t *n2d_queue;
size_t n2d_pos;
size_t n2d_elen;
size_t n2d_enum;
};
int netsim_init(struct netsim_interface *nsif,
const char *eth_socket_path, int *sync_eth);
void netsim_cleanup(struct netsim_interface *nsif);
volatile union cosim_eth_proto_d2n *netsim_d2n_poll(
struct netsim_interface *nsif);
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);
#endif /* ndef COSIM_NETSIM_H_ */
/*
* Copyright 2020 Max Planck Institute for Software Systems
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stddef.h>
#include <stdio.h>
int uxsocket_connect(const char *path);
int uxsocket_recv(int fd, void *data, size_t len, int *pfd);
void *shm_map(int shm_fd);
/*
* Copyright 2020 Max Planck Institute for Software Systems
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netsim.h>
#include "internal.h"
int netsim_init(struct netsim_interface *nsif,
const char *eth_socket_path, int *sync_eth)
{
struct cosim_eth_proto_dev_intro di;
struct cosim_eth_proto_net_intro ni;
int cfd, shm_fd;
void *p;
if ((cfd = uxsocket_connect(eth_socket_path)) < 0) {
return -1;
}
memset(&ni, 0, sizeof(ni));
if (*sync_eth)
ni.flags |= COSIM_ETH_PROTO_FLAGS_NI_SYNC;
if (send(cfd, &ni, sizeof(ni), 0) != sizeof(ni)) {
perror("sending net intro failed");
return -1;
}
if (uxsocket_recv(cfd, &di, sizeof(di), &shm_fd)) {
return -1;
}
if ((p = shm_map(shm_fd)) == NULL) {
return -1;
}
close(shm_fd);
if ((di.flags & COSIM_ETH_PROTO_FLAGS_DI_SYNC) == 0)
*sync_eth = 0;
nsif->d2n_queue = (uint8_t *) p + di.d2n_offset;
nsif->n2d_queue = (uint8_t *) p + di.n2d_offset;
nsif->d2n_elen = di.d2n_elen;
nsif->n2d_elen = di.n2d_elen;
nsif->d2n_enum = di.d2n_nentries;
nsif->n2d_enum = di.n2d_nentries;
nsif->d2n_pos = nsif->n2d_pos = 0;
return 0;
}
void netsim_cleanup(struct netsim_interface *nsif)
{
fprintf(stderr, "netsim_cleanup: TODO\n");
abort();
}
volatile union cosim_eth_proto_d2n *netsim_d2n_poll(
struct netsim_interface *nsif)
{
volatile union cosim_eth_proto_d2n *msg =
(volatile union cosim_eth_proto_d2n *)
(nsif->d2n_queue + nsif->d2n_pos * nsif->d2n_elen);
/* message not ready */
if ((msg->dummy.own_type & COSIM_ETH_PROTO_D2N_OWN_MASK) !=
COSIM_ETH_PROTO_D2N_OWN_NET)
return NULL;
nsif->d2n_pos = (nsif->d2n_pos + 1) % nsif->d2n_enum;
return msg;
}
void netsim_d2n_done(struct netsim_interface *nsif,
volatile union cosim_eth_proto_d2n *msg)
{
msg->dummy.own_type = (msg->dummy.own_type & COSIM_ETH_PROTO_D2N_MSG_MASK)
| COSIM_ETH_PROTO_D2N_OWN_DEV;
}
volatile union cosim_eth_proto_n2d *netsim_n2d_alloc(
struct netsim_interface *nsif)
{
volatile union cosim_eth_proto_n2d *msg =
(volatile union cosim_eth_proto_n2d *)
(nsif->n2d_queue + nsif->n2d_pos * nsif->n2d_elen);
if ((msg->dummy.own_type & COSIM_ETH_PROTO_N2D_OWN_MASK) !=
COSIM_ETH_PROTO_N2D_OWN_NET)
{
return NULL;
}
nsif->n2d_pos = (nsif->n2d_pos + 1) % nsif->n2d_enum;
return msg;
}
/*
* Copyright 2020 Max Planck Institute for Software Systems
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include "internal.h"
int uxsocket_connect(const char *path)
{
int fd;
struct sockaddr_un saun;
/* prepare and connect socket */
memset(&saun, 0, sizeof(saun));
saun.sun_family = AF_UNIX;
strcpy(saun.sun_path, path);
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket failed");
return -1;
}
if (connect(fd, (struct sockaddr *) &saun, sizeof(saun)) != 0) {
perror("connect failed");
return -1;
}
return fd;
}
int uxsocket_recv(int fd, void *data, size_t len, int *pfd)
{
int *ppfd;
ssize_t ret;
struct cmsghdr *cmsg;
union {
char buf[CMSG_SPACE(sizeof(int))];
struct cmsghdr align;
} u;
struct iovec iov = {
.iov_base = data,
.iov_len = len,
};
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = u.buf,
.msg_controllen = sizeof(u.buf),
.msg_flags = 0,
};
if ((ret = recvmsg(fd, &msg, 0)) != (ssize_t) len) {
perror("recvmsg failed");
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
ppfd = (int *) CMSG_DATA(cmsg);
if (msg.msg_controllen <= 0 || cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
fprintf(stderr, "accessing ancillary data failed\n");
return -1;
}
*pfd = *ppfd;
return 0;
}
void *shm_map(int shm_fd)
{
void *p;
struct stat statbuf;
if (fstat(shm_fd, &statbuf) != 0) {
perror("shm_map: fstat failed");
return NULL;
}
p = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd,
0);
if (p == MAP_FAILED) {
perror("shm_map: mmap failed");
return NULL;
}
return p;
}
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