static NetClientInfo net_tap_info = {

    .type = NET_CLIENT_OPTIONS_KIND_TAP,

    .size = sizeof(TAPState),

    .receive = tap_receive,

    .receive_raw = tap_receive_raw,

    .receive_iov = tap_receive_iov,

    .poll = tap_poll,

    .cleanup = tap_cleanup,

};

 

finally all functions for network will call receive_raw or receive. as qemu_deliver_packet function.

ssize_t qemu_deliver_packet(NetClientState *sender,

                            unsigned flags,

                            const uint8_t *data,

                            size_t size,

                            void *opaque)

{

    NetClientState *nc = opaque; // this is a peer's state.

    ssize_t ret;

 

    if (nc->link_down) {

        return size;

    }

 

    if (nc->receive_disabled) {

        return 0;

    }

 

    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {

        ret = nc->info->receive_raw(nc, data, size);

    } else {

        ret = nc->info->receive(nc, data, size);

    }

 

    if (ret == 0) {

        nc->receive_disabled = 1;

    };

 

    return ret;

}

 

both tap_receive for receive and tap_receive_raw for receive_raw will call tap_write_packet function.

 

static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t size)

{

    TAPState *s = DO_UPCAST(TAPState, nc, nc);

    struct iovec iov[2];

    int iovcnt = 0;

    struct virtio_net_hdr_mrg_rxbuf hdr = { };

 

    if (s->host_vnet_hdr_len) {

        iov[iovcnt].iov_base = &hdr;

        iov[iovcnt].iov_len  = s->host_vnet_hdr_len;

        iovcnt++;

    }

 

    iov[iovcnt].iov_base = (char *)buf;

    iov[iovcnt].iov_len  = size;

    iovcnt++;

 

    return tap_write_packet(s, iov, iovcnt);

}

 

static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)

{

    TAPState *s = DO_UPCAST(TAPState, nc, nc);

    struct iovec iov[1];

 

    if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {

        return tap_receive_raw(nc, buf, size);

    }

 

    iov[0].iov_base = (char *)buf;

    iov[0].iov_len  = size;

 

    return tap_write_packet(s, iov, 1);

}

static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt)

{

    ssize_t len;

 

    do {

        len = writev(s->fd, iov, iovcnt);

    } while (len == -1 && errno == EINTR);

 

    if (len == -1 && errno == EAGAIN) {

        tap_write_poll(s, true);

        return 0;

    }

 

    return len;

}

 

static ssize_t readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)

{

    unsigned i = 0;

    ssize_t ret = 0;

    while (i < iov_cnt) {

        ssize_t r = do_write

            ? write(fd, iov[i].iov_base, iov[i].iov_len)

            : read(fd, iov[i].iov_base, iov[i].iov_len);

        if (r > 0) {

            ret += r;

        } else if (!r) {

            break;

        } else if (errno == EINTR) {

            continue;

        } else {

            /* else it is some "other" error,

             * only return if there was no data processed. */

            if (ret == 0) {

                ret = -1;

            }

            break;

        }

        i++;

    }

    return ret;

}

 

finally we found file descriptor network bridge use!!.

Posted by MeatNBrew
l