Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tap interface for network i/o of nuse process #7

Merged
merged 1 commit into from
Nov 10, 2014
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,6 @@ x509.genkey

# Kconfig presets
all.config

# Core file
core
29 changes: 26 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,50 @@ for a build with netmap,
make library ARCH=sim OPT=no NETMAP=yes
```

or with tap,

```
make library ARCH=sim OPT=no NETMAP=yes TAP=yes
```

you should see libnuse-linux.so.

## Run

Then, a wrapper script called **nuse** takes your application running with NUSE.

```
sudo nuse-eth0=192.168.209.39 ./nuse ping 192.168.209.1
sudo NUSEDEV=eth0 nuse-eth0=192.168.209.39 ./nuse ping 192.168.209.1
```

where an environmental variable **nuse-(interface name)** indicates an IPv4 address for an interface under NUSE, instead of host OS's one.

and if you want to use netmap for network i/o, specify **NUSEVIF=NETMAP** as an env variable. The default interface will be raw socket based network i/o.

```
sudo NUSEVIF=NETMAP nuse-eth0=192.168.209.39 ./nuse ping 192.168.209.1
sudo NUSEVIF=NETMAP NUSEDEV=eth0 nuse-eth0=192.168.209.39 ./nuse ping 192.168.209.1
```

And if you want to use tun/tap driver for network i/o, **NUSEVIF=TAP** is offered. When NUSEVIF is TAP, a name of interface attached to a nuse process is not restricted to existing interface names of host stack.

```
sudo NUSEVIF=TAP NUSEDEV=eth0 nuse-eth0=192.168.209.39 ./nuse ping 192.168.209.1

~ host stack ~
ifconfig nuse-eth0
nuse-eth0 Link encap:Ethernet HWaddr d6:d6:86:74:bf:5e
inet6 addr: fe80::d4d6:86ff:fe74:bf5e/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:462 (462.0 B) TX bytes:648 (648.0 B)
```

And, iperf

```
sudo nuse-eth0=192.168.209.39 ./nuse iperf -c 192.168.209.1 -u
sudo NUSEDEV=eth0 nuse-eth0=192.168.209.39 ./nuse iperf -c 192.168.209.1 -u
```

should just work fine !
Expand All @@ -47,3 +69,4 @@ since the LD_PRELOAD with sudo technique requires additional copy and permission
## Tested platform
Fedora 19 64bits
Ubuntu 13.04 64bits
Ubuntu 14.04 64bits
6 changes: 5 additions & 1 deletion arch/sim/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ NETMAP?=no
netmap_yes=nuse-vif-netmap.c
netmap_no=

TAP?=no
tap_yes=nuse-vif-tap.c
tap_no=

NUSE_SRC=\
nuse.c nuse-fiber.c nuse-vif.c \
nuse-vif-rawsock.c nuse-glue.c nuse-hostcalls.c \
$(netmap_$(NETMAP))
$(netmap_$(NETMAP)) $(tap_$(TAP))

SIM_SRC=\
fs.c random.c softirq.c time.c \
Expand Down
194 changes: 194 additions & 0 deletions arch/sim/nuse-vif-tap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@



#include <stdio.h>
#include <linux/if_tun.h>
#include <linux/netdevice.h>


#include "nuse.h"
#include "sim.h"
#include "sim-types.h"

extern struct SimDevicePacket sim_dev_create_packet (struct SimDevice *dev,
int size);
extern void sim_dev_rx (struct SimDevice *device,
struct SimDevicePacket packet);
extern void *sim_dev_get_private (struct SimDevice *);
extern void sim_softirq_wakeup (void);
extern void *sim_malloc (unsigned long size);

/* socket for TAP interfaces */
extern ssize_t (*host_write)(int fd, const void *buf, size_t count);
extern ssize_t (*host_read)(int fd, void *buf, size_t count);
extern int (*host_open) (const char *pathname, int flags);
extern int (*host_close)(int fd);
extern int (*host_socket) (int fd, int type, int proto);
extern int (*host_ioctl)(int d, int request, ...);


static int
tap_alloc (const char * dev)
{
/* create tunnel interface */
int fd;
struct ifreq ifr;

if ((fd = host_open ("/dev/net/tun", O_RDWR)) < 0) {
printf ("failed to open /dev/tun\n");
return -1;
}

memset (&ifr, 0, sizeof (ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
snprintf (ifr.ifr_name, IFNAMSIZ, "%s", dev);

if (host_ioctl (fd, TUNSETIFF, (void *) &ifr) < 0) {
printf ("failed to create tap interface \"%s\"\n",
ifr.ifr_name);
return -1;
}

printf ("%s: alloc tap interface %s\n", __func__, dev);

return fd;
}


int
tap_up (char * dev)
{
int udp_fd;
struct ifreq ifr;

/* Make Tunnel interface up state */

if ((udp_fd = host_socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
printf ("failt to create control socket of tap interface.\n");
return -1;
}

memset (&ifr, 0, sizeof (ifr));
ifr.ifr_flags = IFF_UP;
strncpy (ifr.ifr_name, dev, IFNAMSIZ);

if (host_ioctl (udp_fd, SIOCSIFFLAGS, (void *)&ifr) < 0) {
printf ("failed to make %s up.\n", dev);
host_close (udp_fd);
return -1;
}

host_close (udp_fd);

return 1;
}

void
nuse_vif_tap_read (struct nuse_vif * vif, struct SimDevice * dev)
{
int sock = vif->sock;
char buf[8192];

while (1) {
ssize_t size = host_read (sock, buf, sizeof (buf));
if (size < 0) {
perror ("read");
host_close (sock);
return;
} else if (size == 0) {
host_close (sock);
return;
}

struct ethhdr
{
unsigned char h_dest[6];
unsigned char h_source[6];
uint16_t h_proto;
} *hdr = (struct ethhdr *)buf;

/* check dest mac for promisc */
if (memcmp (hdr->h_dest,
((struct net_device *)dev)->dev_addr, 6) &&
memcmp (hdr->h_dest,
((struct net_device *)dev)->broadcast, 6)) {
sim_softirq_wakeup ();
continue;
}

struct SimDevicePacket packet;
packet = sim_dev_create_packet (dev, size);
/* XXX: FIXME should not copy */
memcpy (packet.buffer, buf, size);

sim_dev_rx (dev, packet);
sim_softirq_wakeup ();
}

return;
}

void
nuse_vif_tap_write (struct nuse_vif * vif, struct SimDevice * dev,
unsigned char * data, int len)
{
int sock = vif->sock;
int ret = host_write (sock, data, len);
if (ret == -1)
perror ("write");

return;
}


void *
nuse_vif_tap_create (const char * ifname)
{
int sock;
char dev[IFNAMSIZ];
struct nuse_vif * vif;

snprintf (dev, sizeof (dev), "nuse-%s", ifname);

sock = tap_alloc (dev);
if (sock < 0) {
perror ("tap_alloc");
return NULL;
}

if (tap_up (dev) < 0) {
perror ("tap_up");
return NULL;
}

vif = sim_malloc (sizeof (struct nuse_vif));
vif->sock = sock;
vif->type = NUSE_VIF_TAP;

return vif;
}

void
nuse_vif_tap_delete (struct nuse_vif * vif)
{
int sock = vif->sock;
host_close (sock);
return;
}

static struct nuse_vif_impl nuse_vif_tap = {
.read = nuse_vif_tap_read,
.write = nuse_vif_tap_write,
.create = nuse_vif_tap_create,
.delete = nuse_vif_tap_delete,
};


extern struct nuse_vif_impl *nuse_vif[NUSE_VIF_MAX];

int nuse_vif_tap_init (void)
{
nuse_vif[NUSE_VIF_TAP] = &nuse_vif_tap;
return 0;
}
__define_initcall(nuse_vif_tap_init, 1);
4 changes: 3 additions & 1 deletion arch/sim/nuse-vif.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ nuse_vif_create (enum viftype type, const char *ifname)
struct nuse_vif_impl *impl = nuse_vif[type];

/* configure promiscus */
nuse_set_if_promisc (ifname);
if (type != NUSE_VIF_TAP)
nuse_set_if_promisc (ifname);

return impl->create (ifname);
}

Expand Down
1 change: 1 addition & 0 deletions arch/sim/nuse-vif.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ enum viftype
NUSE_VIF_RAWSOCK = 0,
NUSE_VIF_NETMAP, /* not yet */
NUSE_VIF_DPDK, /* not yet */
NUSE_VIF_TAP, /* not yet */
NUSE_VIF_MAX
};

Expand Down
21 changes: 20 additions & 1 deletion arch/sim/nuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ nuse_netdev_create (const char *ifname, int ifindex)
type = NUSE_VIF_RAWSOCK;
else if (strncmp (nusevif, "NETMAP", 6) == 0)
type = NUSE_VIF_NETMAP;
else if (strncmp (nusevif, "TAP", 3) == 0)
type = NUSE_VIF_TAP;
}

struct nuse_vif *vif = nuse_vif_create (type, ifname);
Expand All @@ -303,10 +305,12 @@ nuse_netdev_create (const char *ifname, int ifindex)
/* create new net_device (sim%d FIXME: nuse%d). */
struct SimDevice *dev = sim_dev_create (vif, 0);
/* assign new hw address */
hwaddr_base[4] = getpid ();
sim_dev_set_address (dev, hwaddr_base);
hwaddr_base[5]++;
ether_setup ((struct net_device *)dev);


struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
printf ("assign nuse interface %s IPv4 address %s\n", ifnamebuf, ifv4addr);
sin->sin_family = AF_INET;
Expand Down Expand Up @@ -380,6 +384,21 @@ nuse_netdevs_create (void)
return;
}

void
nuse_netdevs_create2 (void)
{
char * ifname;

ifname = getenv ("NUSEDEV");
if (!ifname) {
printf ("interface name does not specified\n");
return;
}

nuse_netdev_create (ifname, 2);
return;
}


void __attribute__((constructor))
nuse_init (void)
Expand Down Expand Up @@ -417,5 +436,5 @@ nuse_init (void)
memset (g_fd_table, 0, sizeof (g_fd_table));

/* create netdev sim%s corresponding to underlying netdevs */
nuse_netdevs_create ();
nuse_netdevs_create2 ();
}
1 change: 0 additions & 1 deletion arch/sim/sim-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ static const struct ethtool_ops sim_ethtool_ops = {
static const struct net_device_ops sim_dev_ops = {
.ndo_start_xmit = kernel_dev_xmit,
.ndo_set_mac_address = eth_mac_addr,

};

static void sim_dev_setup(struct net_device *dev)
Expand Down