DM: Add macvtap support to virtio-net

This patch does the following,
1. Fix an explicit interface name check for tapX preventing
any other interface name like kata_tap to be setup.
2. Add support for macvtap interface.
3. Identify macvtap vs tap interface and
if it is macvtap, identify character device (/dev/tapXX)
to be used.

Tracked-On: #4945
Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Vijay Dhanraj 2020-06-14 14:55:16 -07:00 committed by wenlingz
parent fcc9efec8e
commit 3c9469d98a
1 changed files with 72 additions and 7 deletions

View File

@ -39,6 +39,7 @@
#include <sys/errno.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/socket.h>
#include "dm.h"
#include "pci_core.h"
@ -648,16 +649,80 @@ virtio_net_parsemac(char *mac_str, uint8_t *mac_addr)
return 0;
}
static int
virtio_net_get_ifindex(char *devname)
{
struct ifreq ifr;
int fd;
int ifindex = -1;
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
WPRINTF(("%s: Unable to open control socket", __func__));
return ifindex;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, devname, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
WPRINTF(("%s: Unable to get interface index on this platform\n", __func__));
} else {
ifindex = ifr.ifr_ifindex;
}
close(fd);
return ifindex;
}
static bool
virtio_net_is_macvtap(char *devname, int *ifindex)
{
char tempbuf[IFNAMSIZ];
int rc;
int ifidx;
ifidx = virtio_net_get_ifindex(devname);
if (ifidx < 0)
return false;
/*check if the char device exists*/
rc = snprintf(tempbuf, IFNAMSIZ, "/dev/tap%d", ifidx);
if (rc < 0 || rc >= IFNAMSIZ) {
WPRINTF(("Failed to check interface name %s\n", tempbuf));
return false;
}
if (access(tempbuf, F_OK) != 0)
return false;
*ifindex = ifidx;
return true;
}
static int
virtio_net_tap_open(char *devname)
{
int tunfd, rc;
char tbuf[IFNAMSIZ];
int tunfd, rc, macvtap_index;
struct ifreq ifr;
#define PATH_NET_TUN "/dev/net/tun"
tunfd = open(PATH_NET_TUN, O_RDWR);
/*Check if tun/tap or macvtap interface is used */
if (virtio_net_is_macvtap(devname, &macvtap_index)) {
rc = snprintf(tbuf, IFNAMSIZ, "/dev/tap%d", macvtap_index);
} else {
rc = snprintf(tbuf, IFNAMSIZ, "%s", "/dev/net/tun");
}
if (rc < 0 || rc >= IFNAMSIZ) {
WPRINTF(("Failed to set interface name %s\n", tbuf));
return -1;
}
tunfd = open(tbuf, O_RDWR);
if (tunfd < 0) {
WPRINTF(("open of tup device /dev/net/tun failed\n"));
WPRINTF(("Failed to open interface %s\n", tbuf));
return -1;
}
@ -690,7 +755,7 @@ virtio_net_tap_setup(struct virtio_net *net, char *devname)
rc = snprintf(tbuf, IFNAMSIZ, "%s", devname);
if (rc < 0 || rc >= IFNAMSIZ) /* give warning if error or truncation happens */
WPRINTF(("Fail to set tap device name %s\n", tbuf));
WPRINTF(("Failed to set tap device name %s\n", tbuf));
net->virtio_net_rx = virtio_net_tap_rx;
net->virtio_net_tx = virtio_net_tap_tx;
@ -835,8 +900,8 @@ virtio_net_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
return -1;
}
if (strncmp(devname, "tap", 3) == 0 ||
strncmp(devname, "vmnet", 5) == 0)
if ((strstr(devname, "tap") != NULL) ||
(strncmp(devname, "vmnet", 5) == 0))
virtio_net_tap_setup(net, devname);
free(devname);