*
*/
-#include "monitor.h"
-#include "net.h"
+#include "qemu/osdep.h"
+#include "monitor/monitor.h"
+#include "net/net.h"
+#include "clients.h"
#include "hub.h"
+#include "qemu/iov.h"
/*
* A hub broadcasts incoming packets to all its ports except the source port.
const struct iovec *iov, int iovcnt)
{
NetHubPort *port;
- ssize_t ret = 0;
+ ssize_t len = iov_size(iov, iovcnt);
QLIST_FOREACH(port, &hub->ports, next) {
if (port == source_port) {
continue;
}
- ret = qemu_sendv_packet(&port->nc, iov, iovcnt);
+ qemu_sendv_packet(&port->nc, iov, iovcnt);
}
- return ret;
+ return len;
}
static NetHub *net_hub_new(int id)
return hub;
}
+static int net_hub_port_can_receive(NetClientState *nc)
+{
+ NetHubPort *port;
+ NetHubPort *src_port = DO_UPCAST(NetHubPort, nc, nc);
+ NetHub *hub = src_port->hub;
+
+ QLIST_FOREACH(port, &hub->ports, next) {
+ if (port == src_port) {
+ continue;
+ }
+
+ if (qemu_can_send_packet(&port->nc)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static ssize_t net_hub_port_receive(NetClientState *nc,
const uint8_t *buf, size_t len)
{
}
static NetClientInfo net_hub_port_info = {
- .type = NET_CLIENT_OPTIONS_KIND_HUBPORT,
+ .type = NET_CLIENT_DRIVER_HUBPORT,
.size = sizeof(NetHubPort),
+ .can_receive = net_hub_port_can_receive,
.receive = net_hub_port_receive,
.receive_iov = net_hub_port_receive_iov,
.cleanup = net_hub_port_cleanup,
QLIST_FOREACH(hub, &hubs, next) {
monitor_printf(mon, "hub %d\n", hub->id);
QLIST_FOREACH(port, &hub->ports, next) {
- monitor_printf(mon, " port %d peer %s\n", port->id,
- port->nc.peer ? port->nc.peer->name : "<none>");
+ monitor_printf(mon, " \\ %s", port->nc.name);
+ if (port->nc.peer) {
+ monitor_printf(mon, ": ");
+ print_net_client(mon, port->nc.peer);
+ } else {
+ monitor_printf(mon, "\n");
+ }
}
}
}
/**
* Get the hub id that a client is connected to
*
- * @id Pointer for hub id output, may be NULL
+ * @id: Pointer for hub id output, may be NULL
*/
int net_hub_id_for_client(NetClientState *nc, int *id)
{
NetHubPort *port;
- if (nc->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
+ if (nc->info->type == NET_CLIENT_DRIVER_HUBPORT) {
port = DO_UPCAST(NetHubPort, nc, nc);
} else if (nc->peer != NULL && nc->peer->info->type ==
- NET_CLIENT_OPTIONS_KIND_HUBPORT) {
+ NET_CLIENT_DRIVER_HUBPORT) {
port = DO_UPCAST(NetHubPort, nc, nc->peer);
} else {
return -ENOENT;
return 0;
}
-int net_init_hubport(const NetClientOptions *opts, const char *name,
- NetClientState *peer)
+int net_init_hubport(const Netdev *netdev, const char *name,
+ NetClientState *peer, Error **errp)
{
const NetdevHubPortOptions *hubport;
- assert(opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);
- hubport = opts->hubport;
-
- /* Treat hub port like a backend, NIC must be the one to peer */
- if (peer) {
- return -EINVAL;
- }
+ assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
+ assert(!peer);
+ hubport = &netdev->u.hubport;
net_hub_add_port(hubport->hubid, name);
return 0;
}
switch (peer->info->type) {
- case NET_CLIENT_OPTIONS_KIND_NIC:
+ case NET_CLIENT_DRIVER_NIC:
has_nic = 1;
break;
- case NET_CLIENT_OPTIONS_KIND_USER:
- case NET_CLIENT_OPTIONS_KIND_TAP:
- case NET_CLIENT_OPTIONS_KIND_SOCKET:
- case NET_CLIENT_OPTIONS_KIND_VDE:
+ case NET_CLIENT_DRIVER_USER:
+ case NET_CLIENT_DRIVER_TAP:
+ case NET_CLIENT_DRIVER_SOCKET:
+ case NET_CLIENT_DRIVER_VDE:
+ case NET_CLIENT_DRIVER_VHOST_USER:
has_host_dev = 1;
break;
default:
}
}
}
+
+bool net_hub_flush(NetClientState *nc)
+{
+ NetHubPort *port;
+ NetHubPort *source_port = DO_UPCAST(NetHubPort, nc, nc);
+ int ret = 0;
+
+ QLIST_FOREACH(port, &source_port->hub->ports, next) {
+ if (port != source_port) {
+ ret += qemu_net_queue_flush(port->nc.incoming_queue);
+ }
+ }
+ return ret ? true : false;
+}