]> Git Repo - qemu.git/blobdiff - net.c
KVM: Rework of guest debug state writing
[qemu.git] / net.c
diff --git a/net.c b/net.c
index 599e5b05144cdeb3befbcd5c48049d5c1c5d3755..a1bf49fa9c948a75aa46811255964c562ce68c05 100644 (file)
--- a/net.c
+++ b/net.c
@@ -30,6 +30,7 @@
 #include "net/dump.h"
 #include "net/slirp.h"
 #include "net/vde.h"
+#include "net/util.h"
 #include "monitor.h"
 #include "sysemu.h"
 #include "qemu-common.h"
@@ -38,6 +39,8 @@
 static QTAILQ_HEAD(, VLANState) vlans;
 static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
 
+int default_net = 1;
+
 /***********************************************************/
 /* network device redirectors */
 
@@ -69,38 +72,6 @@ static void hex_dump(FILE *f, const uint8_t *buf, int size)
 }
 #endif
 
-static int parse_macaddr(uint8_t *macaddr, const char *p)
-{
-    int i;
-    char *last_char;
-    long int offset;
-
-    errno = 0;
-    offset = strtol(p, &last_char, 0);    
-    if (0 == errno && '\0' == *last_char &&
-            offset >= 0 && offset <= 0xFFFFFF) {
-        macaddr[3] = (offset & 0xFF0000) >> 16;
-        macaddr[4] = (offset & 0xFF00) >> 8;
-        macaddr[5] = offset & 0xFF;
-        return 0;
-    } else {
-        for(i = 0; i < 6; i++) {
-            macaddr[i] = strtol(p, (char **)&p, 16);
-            if (i == 5) {
-                if (*p != '\0')
-                    return -1;
-            } else {
-                if (*p != ':' && *p != '-')
-                    return -1;
-                p++;
-            }
-        }
-        return 0;    
-    }
-
-    return -1;
-}
-
 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
 {
     const char *p, *p1;
@@ -125,7 +96,7 @@ int parse_host_src_port(struct sockaddr_in *haddr,
                         struct sockaddr_in *saddr,
                         const char *input_str)
 {
-    char *str = strdup(input_str);
+    char *str = qemu_strdup(input_str);
     char *host_str = str;
     char *src_str;
     const char *src_str2;
@@ -248,34 +219,25 @@ static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
                                        int iovcnt,
                                        void *opaque);
 
-VLANClientState *qemu_new_vlan_client(net_client_type type,
-                                      VLANState *vlan,
-                                      VLANClientState *peer,
-                                      const char *model,
-                                      const char *name,
-                                      NetCanReceive *can_receive,
-                                      NetReceive *receive,
-                                      NetReceive *receive_raw,
-                                      NetReceiveIOV *receive_iov,
-                                      NetCleanup *cleanup,
-                                      void *opaque)
+VLANClientState *qemu_new_net_client(NetClientInfo *info,
+                                     VLANState *vlan,
+                                     VLANClientState *peer,
+                                     const char *model,
+                                     const char *name)
 {
     VLANClientState *vc;
 
-    vc = qemu_mallocz(sizeof(VLANClientState));
+    assert(info->size >= sizeof(VLANClientState));
+
+    vc = qemu_mallocz(info->size);
 
-    vc->type = type;
+    vc->info = info;
     vc->model = qemu_strdup(model);
-    if (name)
+    if (name) {
         vc->name = qemu_strdup(name);
-    else
+    } else {
         vc->name = assign_name(vc, model);
-    vc->can_receive = can_receive;
-    vc->receive = receive;
-    vc->receive_raw = receive_raw;
-    vc->receive_iov = receive_iov;
-    vc->cleanup = cleanup;
-    vc->opaque = opaque;
+    }
 
     if (vlan) {
         assert(!peer);
@@ -296,6 +258,27 @@ VLANClientState *qemu_new_vlan_client(net_client_type type,
     return vc;
 }
 
+NICState *qemu_new_nic(NetClientInfo *info,
+                       NICConf *conf,
+                       const char *model,
+                       const char *name,
+                       void *opaque)
+{
+    VLANClientState *nc;
+    NICState *nic;
+
+    assert(info->type == NET_CLIENT_TYPE_NIC);
+    assert(info->size >= sizeof(NICState));
+
+    nc = qemu_new_net_client(info, conf->vlan, conf->peer, model, name);
+
+    nic = DO_UPCAST(NICState, nc, nc);
+    nic->conf = conf;
+    nic->opaque = opaque;
+
+    return nic;
+}
+
 void qemu_del_vlan_client(VLANClientState *vc)
 {
     if (vc->vlan) {
@@ -310,8 +293,8 @@ void qemu_del_vlan_client(VLANClientState *vc)
         }
     }
 
-    if (vc->cleanup) {
-        vc->cleanup(vc);
+    if (vc->info->cleanup) {
+        vc->info->cleanup(vc);
     }
 
     qemu_free(vc->name);
@@ -319,19 +302,6 @@ void qemu_del_vlan_client(VLANClientState *vc)
     qemu_free(vc);
 }
 
-VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque)
-{
-    VLANClientState *vc;
-
-    QTAILQ_FOREACH(vc, &vlan->clients, next) {
-        if (vc->opaque == opaque) {
-            return vc;
-        }
-    }
-
-    return NULL;
-}
-
 VLANClientState *
 qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
                               const char *client_str)
@@ -358,6 +328,26 @@ qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
     return vc;
 }
 
+void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
+{
+    VLANClientState *nc;
+    VLANState *vlan;
+
+    QTAILQ_FOREACH(nc, &non_vlan_clients, next) {
+        if (nc->info->type == NET_CLIENT_TYPE_NIC) {
+            func(DO_UPCAST(NICState, nc, nc), opaque);
+        }
+    }
+
+    QTAILQ_FOREACH(vlan, &vlans, next) {
+        QTAILQ_FOREACH(nc, &vlan->clients, next) {
+            if (nc->info->type == NET_CLIENT_TYPE_NIC) {
+                func(DO_UPCAST(NICState, nc, nc), opaque);
+            }
+        }
+    }
+}
+
 int qemu_can_send_packet(VLANClientState *sender)
 {
     VLANState *vlan = sender->vlan;
@@ -366,8 +356,8 @@ int qemu_can_send_packet(VLANClientState *sender)
     if (sender->peer) {
         if (sender->peer->receive_disabled) {
             return 0;
-        } else if (sender->peer->can_receive &&
-                   !sender->peer->can_receive(sender->peer)) {
+        } else if (sender->peer->info->can_receive &&
+                   !sender->peer->info->can_receive(sender->peer)) {
             return 0;
         } else {
             return 1;
@@ -384,7 +374,7 @@ int qemu_can_send_packet(VLANClientState *sender)
         }
 
         /* no can_receive() handler, they can always receive */
-        if (!vc->can_receive || vc->can_receive(vc)) {
+        if (!vc->info->can_receive || vc->info->can_receive(vc)) {
             return 1;
         }
     }
@@ -408,10 +398,10 @@ static ssize_t qemu_deliver_packet(VLANClientState *sender,
         return 0;
     }
 
-    if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) {
-        ret = vc->receive_raw(vc, data, size);
+    if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->info->receive_raw) {
+        ret = vc->info->receive_raw(vc, data, size);
     } else {
-        ret = vc->receive(vc, data, size);
+        ret = vc->info->receive(vc, data, size);
     }
 
     if (ret == 0) {
@@ -448,10 +438,10 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
             continue;
         }
 
-        if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) {
-            len = vc->receive_raw(vc, buf, size);
+        if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->info->receive_raw) {
+            len = vc->info->receive_raw(vc, buf, size);
         } else {
-            len = vc->receive(vc, buf, size);
+            len = vc->info->receive(vc, buf, size);
         }
 
         if (len == 0) {
@@ -556,7 +546,7 @@ static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov,
         offset += len;
     }
 
-    return vc->receive(vc, buffer, offset);
+    return vc->info->receive(vc, buffer, offset);
 }
 
 static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt)
@@ -581,8 +571,8 @@ static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
         return calc_iov_length(iov, iovcnt);
     }
 
-    if (vc->receive_iov) {
-        return vc->receive_iov(vc, iov, iovcnt);
+    if (vc->info->receive_iov) {
+        return vc->info->receive_iov(vc, iov, iovcnt);
     } else {
         return vc_sendv_compat(vc, iov, iovcnt);
     }
@@ -612,8 +602,8 @@ static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender,
 
         assert(!(flags & QEMU_NET_PACKET_FLAG_RAW));
 
-        if (vc->receive_iov) {
-            len = vc->receive_iov(vc, iov, iovcnt);
+        if (vc->info->receive_iov) {
+            len = vc->info->receive_iov(vc, iov, iovcnt);
         } else {
             len = vc_sendv_compat(vc, iov, iovcnt);
         }
@@ -809,7 +799,7 @@ static int net_init_nic(QemuOpts *opts,
     nd->macaddr[5] = 0x56 + idx;
 
     if (qemu_opt_get(opts, "macaddr") &&
-        parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) {
+        net_parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) {
         qemu_error("invalid syntax for ethernet address\n");
         return -1;
     }
@@ -822,9 +812,6 @@ static int net_init_nic(QemuOpts *opts,
     }
 
     nd->used = 1;
-    if (vlan) {
-        nd->vlan->nb_guest_devs++;
-    }
     nb_nics++;
 
     return idx;
@@ -853,7 +840,7 @@ typedef int (*net_client_init_func)(QemuOpts *opts,
 /* magic number, but compiler will warn if too small */
 #define NET_MAX_DESC 20
 
-static struct {
+static const struct {
     const char *type;
     net_client_init_func init;
     QemuOptDesc desc[NET_MAX_DESC];
@@ -1067,12 +1054,18 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
     int i;
 
     type = qemu_opt_get(opts, "type");
-    if (!type) {
-        qemu_error("No type specified for -net\n");
-        return -1;
-    }
 
-    if (is_netdev) {
+    if (!is_netdev) {
+        if (!type) {
+            qemu_error("No type specified for -net\n");
+            return -1;
+        }
+    } else {
+        if (!type) {
+            qemu_error("No type specified for -netdev\n");
+            return -1;
+        }
+
         if (strcmp(type, "tap") != 0 &&
 #ifdef CONFIG_SLIRP
             strcmp(type, "user") != 0 &&
@@ -1132,20 +1125,6 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
     return -1;
 }
 
-void net_client_uninit(NICInfo *nd)
-{
-    if (nd->vlan) {
-        nd->vlan->nb_guest_devs--;
-    }
-    nb_nics--;
-
-    qemu_free(nd->model);
-    qemu_free(nd->name);
-    qemu_free(nd->devaddr);
-
-    nd->used = 0;
-}
-
 static int net_host_check_device(const char *device)
 {
     int i;
@@ -1231,16 +1210,23 @@ void net_set_boot_mask(int net_boot_mask)
 void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
+    VLANClientState *vc;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        VLANClientState *vc;
-
         monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
 
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
             monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
         }
     }
+    monitor_printf(mon, "Devices not on any VLAN:\n");
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        monitor_printf(mon, "  %s: %s", vc->name, vc->info_str);
+        if (vc->peer) {
+            monitor_printf(mon, " peer=%s", vc->peer->name);
+        }
+        monitor_printf(mon, "\n");
+    }
 }
 
 void do_set_link(Monitor *mon, const QDict *qdict)
@@ -1257,6 +1243,7 @@ void do_set_link(Monitor *mon, const QDict *qdict)
             }
         }
     }
+    vc = qemu_find_netdev(name);
 done:
 
     if (!vc) {
@@ -1272,8 +1259,9 @@ done:
         monitor_printf(mon, "invalid link status '%s'; only 'up' or 'down' "
                        "valid\n", up_or_down);
 
-    if (vc->link_status_changed)
-        vc->link_status_changed(vc);
+    if (vc->info->link_status_changed) {
+        vc->info->link_status_changed(vc);
+    }
 }
 
 void net_cleanup(void)
@@ -1292,20 +1280,41 @@ void net_cleanup(void)
     }
 }
 
-static void net_check_clients(void)
+void net_check_clients(void)
 {
     VLANState *vlan;
+    VLANClientState *vc;
+    int has_nic = 0, has_host_dev = 0;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
-            continue;
-        if (vlan->nb_guest_devs == 0)
+        QTAILQ_FOREACH(vc, &vlan->clients, next) {
+            switch (vc->info->type) {
+            case NET_CLIENT_TYPE_NIC:
+                has_nic = 1;
+                break;
+            case NET_CLIENT_TYPE_SLIRP:
+            case NET_CLIENT_TYPE_TAP:
+            case NET_CLIENT_TYPE_SOCKET:
+            case NET_CLIENT_TYPE_VDE:
+                has_host_dev = 1;
+                break;
+            default: ;
+            }
+        }
+        if (has_host_dev && !has_nic)
             fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id);
-        if (vlan->nb_host_devs == 0)
+        if (has_nic && !has_host_dev)
             fprintf(stderr,
                     "Warning: vlan %d is not connected to host network\n",
                     vlan->id);
     }
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (!vc->peer) {
+            fprintf(stderr, "Warning: %s %s has no peer\n",
+                    vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev",
+                    vc->name);
+        }
+    }
 }
 
 static int net_init_client(QemuOpts *opts, void *dummy)
@@ -1322,7 +1331,7 @@ static int net_init_netdev(QemuOpts *opts, void *dummy)
 
 int net_init_clients(void)
 {
-    if (QTAILQ_EMPTY(&qemu_net_opts.head)) {
+    if (default_net) {
         /* if no clients, we use a default config */
         qemu_opts_set(&qemu_net_opts, NULL, "type", "nic");
 #ifdef CONFIG_SLIRP
@@ -1340,8 +1349,6 @@ int net_init_clients(void)
         return -1;
     }
 
-    net_check_clients();
-
     return 0;
 }
 
@@ -1358,5 +1365,6 @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
         return -1;
     }
 
+    default_net = 0;
     return 0;
 }
This page took 0.035718 seconds and 4 git commands to generate.