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

Support config file for nuse process. #10

Closed
wants to merge 4 commits into from
Closed
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
58 changes: 30 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,52 +26,54 @@ you should see libnuse-linux.so.

## Run

Then, a wrapper script called **nuse** takes your application running with NUSE.
At 1st, please write a configuration file for nuse **nuse.conf**.
Example of nuse.conf is shown below.

```
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.
# Interface definition.
interface eth0
address 192.168.0.10
netmask 255.255.255.0
macaddr 00:01:01:01:01:01
viftype TAP

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.
interface p1p1
address 172.16.0.1
netmask 255.255.255.0
macaddr 00:01:01:01:01:02

```
sudo NUSEVIF=NETMAP NUSEDEV=eth0 nuse-eth0=192.168.209.39 ./nuse ping 192.168.209.1
# route entry definition.
route
network 0.0.0.0
netmask 0.0.0.0
gateway 192.168.0.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.
When viftype is TAP, the interface name attached to nuse process is
not restricted to be same as physical interfaces of host
stack. However, viftype RAW and NETMAP requires that an interface name
must be same as a physical interface 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)
```
The default interface will be raw socket based network i/o.


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

How to set default route of nuse process.
```
sudo NUSEVIF=TAP NUSEDEV=eth0 nuse-eth0=192.168.0.10 DEFAULTROUTE=192.168.0.1 ./nuse ping 172.16.0.1
sudo NUSECONF=nuse.conf ./nuse ping 172.16.0.2
```

And, iperf

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

should just work fine !

since the LD_PRELOAD with sudo technique requires additional copy and permission changes to the library, the script will automatically conduct such an operation.

## Tested platform
Fedora 19 64bits
Ubuntu 13.04 64bits
Ubuntu 14.04 64bits
- Fedora 19 64bits
- Ubuntu 13.04 64bits
- Ubuntu 14.04 64bits
4 changes: 2 additions & 2 deletions arch/sim/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ tap_yes=nuse-vif-tap.c
tap_no=

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

SIM_SRC=\
Expand Down
258 changes: 258 additions & 0 deletions arch/sim/nuse-config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@

#include <stdio.h>
#include <linux/socket.h>
#include <uapi/linux/in.h>
#include "nuse-config.h"

typedef unsigned int uint32_t;

/* sdlib.h */
extern void *malloc (size_t size);
extern void free (void * ptr);


/* ipaddress config */
typedef uint32_t in_addr_t;
extern in_addr_t inet_addr (const char * cp);



static int
strsplit (char * str, char ** args, int max)
{
int argc;
char * c;

for (argc = 0, c = str; *c == ' ' || *c == '\t' || *c == '\n'; c++);
while (*c && argc < max) {
args[argc++] = c;
while (*c && *c > ' ') c++;
while (*c && *c <= ' ') *c++ = '\0';
}

return argc;
}

static int
nuse_config_parse_interface (char * line, FILE * fp, struct nuse_config * cf)
{
int ret;
char buf[1024], *p, * args[2];
struct nuse_vif_config * vifcf;
struct sockaddr_in * sin;

memset (buf, 0, sizeof (buf));

vifcf = (struct nuse_vif_config *)
malloc (sizeof (struct nuse_vif_config));

memset (vifcf, 0, sizeof (struct nuse_vif_config));
vifcf->type = NUSE_VIF_RAWSOCK; // default

strsplit (line, args, sizeof (args));

strncpy (vifcf->ifname, args[1], IFNAMSIZ);

while ((p = fgets (buf, sizeof (buf), fp)) != NULL) {

ret = strsplit (buf, args, sizeof (args));

/* comment out */
if (args[0][0] == '#')
continue;

if (ret == 0) {
/* no item in the line */
break;
}

if (strncmp (args[0], "address", 7) == 0) {
strncpy (vifcf->address, args[1], NUSE_ADDR_STRLEN);
}
if (strncmp (args[0], "netmask", 7) == 0) {
strncpy (vifcf->netmask, args[1], NUSE_ADDR_STRLEN);
}
if (strncmp (args[0], "macaddr", 7) == 0) {
strncpy (vifcf->macaddr, args[1], NUSE_MACADDR_STRLEN);
}
if (strncmp (args[0], "viftype", 7) == 0) {
if (strncmp (args[1], "RAW", 3) == 0) {
vifcf->type = NUSE_VIF_RAWSOCK;
} else if (strncmp (args[1], "NETMAP", 6) == 0) {
vifcf->type = NUSE_VIF_NETMAP;
} else if (strncmp (args[1], "TAP", 3) == 0) {
vifcf->type = NUSE_VIF_TAP;
} else {
printf ("invalid vif type %s\n", args[1]);
return 0;
}
}
}

if (!p) {
printf ("Config error for interface %s\n", vifcf->ifname);
free (vifcf);
return 0;
}

/* setup ifreq */
sin = (struct sockaddr_in *)&vifcf->ifr_vif_addr.ifr_addr;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr (vifcf->address);

sin = (struct sockaddr_in *)&vifcf->ifr_vif_mask.ifr_netmask;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr (vifcf->netmask);

/* XXX: ifname attached to nuse process is same as host stck */
strncpy (vifcf->ifr_vif_addr.ifr_name, vifcf->ifname, IFNAMSIZ);
strncpy (vifcf->ifr_vif_mask.ifr_name, vifcf->ifname, IFNAMSIZ);

/* reassemble mac address */
if (sscanf (vifcf->macaddr, "%u:%u:%u:%u:%u:%u",
(unsigned int *)&vifcf->mac[0],
(unsigned int *)&vifcf->mac[1],
(unsigned int *)&vifcf->mac[2],
(unsigned int *)&vifcf->mac[3],
(unsigned int *)&vifcf->mac[4],
(unsigned int *)&vifcf->mac[5]) < 1) {
printf ("failed to parse mac address %s\n", vifcf->macaddr);
free (vifcf);
return 0;
}

cf->vifs[cf->vif_cnt++] = vifcf;

return 1;
}

static int
nuse_config_parse_route (char * line, FILE * fp, struct nuse_config * cf)
{
int ret, net, mask, gate;
char buf[1024], * p, * args[2];
struct nuse_route_config * rtcf;
struct sockaddr_in * sin;

net = 0;
mask = 0;
gate = 0;

memset (buf, 0, sizeof (buf));

rtcf = (struct nuse_route_config *)
malloc (sizeof (struct nuse_route_config));

while ((p = fgets (buf, sizeof (buf), fp)) != NULL) {

ret = strsplit (buf, args, sizeof (args));

if (ret == 0) {
/* no item in the line */
break;
}

/* comment out */
if (args[0][0] == '#')
continue;

if (strncmp (args[0], "network", 7) == 0) {
strncpy (rtcf->network, args[1], NUSE_ADDR_STRLEN);
net = 1;
}
if (strncmp (args[0], "netmask", 7) == 0) {
strncpy (rtcf->netmask, args[1], NUSE_ADDR_STRLEN);
mask = 1;
}
if (strncmp (args[0], "gateway", 7) == 0) {
strncpy (rtcf->gateway, args[1], NUSE_ADDR_STRLEN);
gate = 1;
}

if (net && mask && gate)
break;
}

if (!p) {
printf ("Config error for route entry\n");
free (rtcf);
return 0;
}

if (!net)
printf ("network is not configured !\n");
if (!mask)
printf ("netmask is not configured !\n");
if (!gate)
printf ("netmask is not configured !\n");

if (!net || !mask || !gate)
return 0;

/* setup rtentry */
sin = (struct sockaddr_in *)&rtcf->route.rt_dst;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr (rtcf->network);

sin = (struct sockaddr_in *) &rtcf->route.rt_genmask;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr (rtcf->netmask);

sin = (struct sockaddr_in *) &rtcf->route.rt_gateway;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr (rtcf->gateway);

rtcf->route.rt_flags = RTF_UP | RTF_GATEWAY;
rtcf->route.rt_metric = 0;

cf->routes[cf->route_cnt++] = rtcf;

return 1;
}


int
nuse_config_parse (struct nuse_config * cf, char * cfname)
{
FILE * fp;
int ret;
char buf[1024];

memset (cf, 0, sizeof (struct nuse_config));

if ((fp = fopen (cfname, "r")) == NULL) {
perror ("fopen");
return 0;
}

while (fgets (buf, sizeof (buf), fp) != NULL) {
if (strncmp (buf, "interface ", 10) == 0) {
ret = nuse_config_parse_interface (buf, fp, cf);
} else if (strncmp (buf, "route", 5) == 0) {
ret = nuse_config_parse_route (buf, fp, cf);
}
if (!ret)
break;
}

fclose (fp);

return ret;
}

void
nuse_config_free (struct nuse_config * cf)
{
int n;

for (n = 0; n < cf->vif_cnt; n++) {
free (cf->vifs[n]);
}

for (n = 0; n < cf->route_cnt; n++) {
free (cf->routes[n]);
}

return;
}

Loading