Commit c80cd6bb authored by Greg Kurz's avatar Greg Kurz Committed by Michael S. Tsirkin
Browse files

tap: add VNET_LE/VNET_BE operations



The linux tap and macvtap backends can be told to parse vnet headers
according to little or big endian. This is done through the TUNSETVNETLE
and TUNSETVNETBE ioctls.

This patch brings all the plumbing for QEMU to use these APIs.

Signed-off-by: default avatarGreg Kurz <gkurz@linux.vnet.ibm.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 04b7a152
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ typedef bool (HasVnetHdrLen)(NetClientState *, int);
typedef void (UsingVnetHdr)(NetClientState *, bool);
typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
typedef void (SetVnetHdrLen)(NetClientState *, int);
typedef int (SetVnetLE)(NetClientState *, bool);
typedef int (SetVnetBE)(NetClientState *, bool);

typedef struct NetClientInfo {
    NetClientOptionsKind type;
@@ -73,6 +75,8 @@ typedef struct NetClientInfo {
    UsingVnetHdr *using_vnet_hdr;
    SetOffload *set_offload;
    SetVnetHdrLen *set_vnet_hdr_len;
    SetVnetLE *set_vnet_le;
    SetVnetBE *set_vnet_be;
} NetClientInfo;

struct NetClientState {
@@ -139,6 +143,8 @@ void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
                      int ecn, int ufo);
void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
int qemu_set_vnet_le(NetClientState *nc, bool is_le);
int qemu_set_vnet_be(NetClientState *nc, bool is_be);
void qemu_macaddr_default_if_unset(MACAddr *macaddr);
int qemu_show_nic_models(const char *arg, const char *const *models);
void qemu_check_nic_model(NICInfo *nd, const char *model);
+18 −0
Original line number Diff line number Diff line
@@ -510,6 +510,24 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
    nc->info->set_vnet_hdr_len(nc, len);
}

int qemu_set_vnet_le(NetClientState *nc, bool is_le)
{
    if (!nc || !nc->info->set_vnet_le) {
        return -ENOSYS;
    }

    return nc->info->set_vnet_le(nc, is_le);
}

int qemu_set_vnet_be(NetClientState *nc, bool is_be)
{
    if (!nc || !nc->info->set_vnet_be) {
        return -ENOSYS;
    }

    return nc->info->set_vnet_be(nc, is_be);
}

int qemu_can_send_packet(NetClientState *sender)
{
    int vm_running = runstate_is_running();
+34 −0
Original line number Diff line number Diff line
@@ -198,6 +198,40 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
    }
}

int tap_fd_set_vnet_le(int fd, int is_le)
{
    int arg = is_le ? 1 : 0;

    if (!ioctl(fd, TUNSETVNETLE, &arg)) {
        return 0;
    }

    /* Check if our kernel supports TUNSETVNETLE */
    if (errno == EINVAL) {
        return -errno;
    }

    error_report("TUNSETVNETLE ioctl() failed: %s.\n", strerror(errno));
    abort();
}

int tap_fd_set_vnet_be(int fd, int is_be)
{
    int arg = is_be ? 1 : 0;

    if (!ioctl(fd, TUNSETVNETBE, &arg)) {
        return 0;
    }

    /* Check if our kernel supports TUNSETVNETBE */
    if (errno == EINVAL) {
        return -errno;
    }

    error_report("TUNSETVNETBE ioctl() failed: %s.\n", strerror(errno));
    abort();
}

void tap_fd_set_offload(int fd, int csum, int tso4,
                        int tso6, int ecn, int ufo)
{
+2 −0
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
#define TUNGETVNETHDRSZ _IOR('T', 215, int)
#define TUNSETVNETHDRSZ _IOW('T', 216, int)
#define TUNSETQUEUE  _IOW('T', 217, int)
#define TUNSETVNETLE _IOW('T', 220, int)
#define TUNSETVNETBE _IOW('T', 222, int)

#endif

+16 −0
Original line number Diff line number Diff line
@@ -275,6 +275,20 @@ static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
    s->using_vnet_hdr = using_vnet_hdr;
}

static int tap_set_vnet_le(NetClientState *nc, bool is_le)
{
    TAPState *s = DO_UPCAST(TAPState, nc, nc);

    return tap_fd_set_vnet_le(s->fd, is_le);
}

static int tap_set_vnet_be(NetClientState *nc, bool is_be)
{
    TAPState *s = DO_UPCAST(TAPState, nc, nc);

    return tap_fd_set_vnet_be(s->fd, is_be);
}

static void tap_set_offload(NetClientState *nc, int csum, int tso4,
                     int tso6, int ecn, int ufo)
{
@@ -341,6 +355,8 @@ static NetClientInfo net_tap_info = {
    .using_vnet_hdr = tap_using_vnet_hdr,
    .set_offload = tap_set_offload,
    .set_vnet_hdr_len = tap_set_vnet_hdr_len,
    .set_vnet_le = tap_set_vnet_le,
    .set_vnet_be = tap_set_vnet_be,
};

static TAPState *net_tap_fd_init(NetClientState *peer,
Loading