/**
* Generate a name for net client
*
- * Only net clients created with the legacy -net option need this. Naming is
- * mandatory for net clients created with -netdev.
+ * Only net clients created with the legacy -net option and NICs need this.
*/
static char *assign_name(NetClientState *nc1, const char *model)
{
if (nc == nc1) {
continue;
}
- /* For compatibility only bump id for net clients on a vlan */
- if (strcmp(nc->model, model) == 0 &&
- net_hub_id_for_client(nc, NULL) == 0) {
+ if (strcmp(nc->model, model) == 0) {
id++;
}
}
const char *name,
void *opaque)
{
- NetClientState *nc;
NetClientState **peers = conf->peers.ncs;
NICState *nic;
- int i;
+ int i, queues = MAX(1, conf->queues);
assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
assert(info->size >= sizeof(NICState));
- nc = qemu_new_net_client(info, peers[0], model, name);
- nc->queue_index = 0;
-
- nic = qemu_get_nic(nc);
+ nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
+ nic->ncs = (void *)nic + info->size;
nic->conf = conf;
nic->opaque = opaque;
- for (i = 1; i < conf->queues; i++) {
- qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, nc->name,
+ for (i = 0; i < queues; i++) {
+ qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
NULL);
nic->ncs[i].queue_index = i;
}
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
{
- return &nic->ncs[queue_index];
+ return nic->ncs + queue_index;
}
NetClientState *qemu_get_queue(NICState *nic)
{
NetClientState *nc0 = nc - nc->queue_index;
- return DO_UPCAST(NICState, ncs[0], nc0);
+ return (NICState *)((void *)nc0 - nc->info->size);
}
void *qemu_get_nic_opaque(NetClientState *nc)
{
QTAILQ_REMOVE(&net_clients, nc, next);
- nc->info->cleanup(nc);
+ if (nc->info->cleanup) {
+ nc->info->cleanup(nc);
+ }
}
static void qemu_free_net_client(NetClientState *nc)
void qemu_del_nic(NICState *nic)
{
- int i, queues = nic->conf->queues;
+ int i, queues = MAX(nic->conf->queues, 1);
/* If this is a peer NIC and peer has already been deleted, free it now. */
if (nic->peer_deleted) {
qemu_cleanup_net_client(nc);
qemu_free_net_client(nc);
}
+
+ g_free(nic);
}
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
{
nc->receive_disabled = 0;
+ if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
+ if (net_hub_flush(nc->peer)) {
+ qemu_notify_event();
+ }
+ return;
+ }
if (qemu_net_queue_flush(nc->send_queue)) {
/* We emptied the queue successfully, signal to the IO thread to repoll
* the file descriptor (for tap, for example).
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
int iovcnt)
{
- uint8_t buffer[4096];
+ uint8_t buffer[NET_BUFSIZE];
size_t offset;
offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));