]> git.proxmox.com Git - qemu.git/blobdiff - net/hub.c
misc: move include files to include/qemu/
[qemu.git] / net / hub.c
index be6e014aad47a86db9b46b8c289c88fbfd674af2..5adfce444beb4385af4ef2fede11eefee9a47500 100644 (file)
--- a/net/hub.c
+++ b/net/hub.c
  *
  */
 
-#include "monitor.h"
-#include "net.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.
@@ -25,7 +27,7 @@
 typedef struct NetHub NetHub;
 
 typedef struct NetHubPort {
-    VLANClientState nc;
+    NetClientState nc;
     QLIST_ENTRY(NetHubPort) next;
     NetHub *hub;
     int id;
@@ -59,16 +61,16 @@ static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *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)
@@ -85,7 +87,26 @@ static NetHub *net_hub_new(int id)
     return hub;
 }
 
-static ssize_t net_hub_port_receive(VLANClientState *nc,
+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)
 {
     NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
@@ -93,7 +114,7 @@ static ssize_t net_hub_port_receive(VLANClientState *nc,
     return net_hub_receive(port->hub, port, buf, len);
 }
 
-static ssize_t net_hub_port_receive_iov(VLANClientState *nc,
+static ssize_t net_hub_port_receive_iov(NetClientState *nc,
                                         const struct iovec *iov, int iovcnt)
 {
     NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
@@ -101,7 +122,7 @@ static ssize_t net_hub_port_receive_iov(VLANClientState *nc,
     return net_hub_receive_iov(port->hub, port, iov, iovcnt);
 }
 
-static void net_hub_port_cleanup(VLANClientState *nc)
+static void net_hub_port_cleanup(NetClientState *nc)
 {
     NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
 
@@ -111,6 +132,7 @@ static void net_hub_port_cleanup(VLANClientState *nc)
 static NetClientInfo net_hub_port_info = {
     .type = NET_CLIENT_OPTIONS_KIND_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,
@@ -118,7 +140,7 @@ static NetClientInfo net_hub_port_info = {
 
 static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
 {
-    VLANClientState *nc;
+    NetClientState *nc;
     NetHubPort *port;
     int id = hub->num_ports++;
     char default_name[128];
@@ -129,7 +151,7 @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
         name = default_name;
     }
 
-    nc = qemu_new_net_client(&net_hub_port_info, NULL, NULL, "hub", name);
+    nc = qemu_new_net_client(&net_hub_port_info, NULL, "hub", name);
     port = DO_UPCAST(NetHubPort, nc, nc);
     port->id = id;
     port->hub = hub;
@@ -145,7 +167,7 @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
  *
  * If there is no existing hub with the given id then a new hub is created.
  */
-VLANClientState *net_hub_add_port(int hub_id, const char *name)
+NetClientState *net_hub_add_port(int hub_id, const char *name)
 {
     NetHub *hub;
     NetHubPort *port;
@@ -164,6 +186,54 @@ VLANClientState *net_hub_add_port(int hub_id, const char *name)
     return &port->nc;
 }
 
+/**
+ * Find a specific client on a hub
+ */
+NetClientState *net_hub_find_client_by_name(int hub_id, const char *name)
+{
+    NetHub *hub;
+    NetHubPort *port;
+    NetClientState *peer;
+
+    QLIST_FOREACH(hub, &hubs, next) {
+        if (hub->id == hub_id) {
+            QLIST_FOREACH(port, &hub->ports, next) {
+                peer = port->nc.peer;
+
+                if (peer && strcmp(peer->name, name) == 0) {
+                    return peer;
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+/**
+ * Find a available port on a hub; otherwise create one new port
+ */
+NetClientState *net_hub_port_find(int hub_id)
+{
+    NetHub *hub;
+    NetHubPort *port;
+    NetClientState *nc;
+
+    QLIST_FOREACH(hub, &hubs, next) {
+        if (hub->id == hub_id) {
+            QLIST_FOREACH(port, &hub->ports, next) {
+                nc = port->nc.peer;
+                if (!nc) {
+                    return &(port->nc);
+                }
+            }
+            break;
+        }
+    }
+
+    nc = net_hub_add_port(hub_id, NULL);
+    return nc;
+}
+
 /**
  * Print hub configuration
  */
@@ -175,8 +245,10 @@ void net_hub_info(Monitor *mon)
     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>");
+            if (port->nc.peer) {
+                monitor_printf(mon, " \\ ");
+                print_net_client(mon, port->nc.peer);
+            }
         }
     }
 }
@@ -186,7 +258,7 @@ void net_hub_info(Monitor *mon)
  *
  * @id              Pointer for hub id output, may be NULL
  */
-int net_hub_id_for_client(VLANClientState *nc, int *id)
+int net_hub_id_for_client(NetClientState *nc, int *id)
 {
     NetHubPort *port;
 
@@ -206,18 +278,63 @@ int net_hub_id_for_client(VLANClientState *nc, int *id)
 }
 
 int net_init_hubport(const NetClientOptions *opts, const char *name,
-                     VLANState *vlan)
+                     NetClientState *peer)
 {
     const NetdevHubPortOptions *hubport;
 
     assert(opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);
     hubport = opts->hubport;
 
-    /* The hub is a "vlan" so this option makes no sense. */
-    if (vlan) {
+    /* Treat hub port like a backend, NIC must be the one to peer */
+    if (peer) {
         return -EINVAL;
     }
 
     net_hub_add_port(hubport->hubid, name);
     return 0;
 }
+
+/**
+ * Warn if hub configurations are likely wrong
+ */
+void net_hub_check_clients(void)
+{
+    NetHub *hub;
+    NetHubPort *port;
+    NetClientState *peer;
+
+    QLIST_FOREACH(hub, &hubs, next) {
+        int has_nic = 0, has_host_dev = 0;
+
+        QLIST_FOREACH(port, &hub->ports, next) {
+            peer = port->nc.peer;
+            if (!peer) {
+                fprintf(stderr, "Warning: hub port %s has no peer\n",
+                        port->nc.name);
+                continue;
+            }
+
+            switch (peer->info->type) {
+            case NET_CLIENT_OPTIONS_KIND_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:
+                has_host_dev = 1;
+                break;
+            default:
+                break;
+            }
+        }
+        if (has_host_dev && !has_nic) {
+            fprintf(stderr, "Warning: vlan %d with no nics\n", hub->id);
+        }
+        if (has_nic && !has_host_dev) {
+            fprintf(stderr,
+                    "Warning: vlan %d is not connected to host network\n",
+                    hub->id);
+        }
+    }
+}