|
@@ -54,6 +54,7 @@
|
|
#include "net/colo-compare.h"
|
|
#include "net/colo-compare.h"
|
|
#include "net/filter.h"
|
|
#include "net/filter.h"
|
|
#include "qapi/string-output-visitor.h"
|
|
#include "qapi/string-output-visitor.h"
|
|
|
|
+#include "qapi/qobject-input-visitor.h"
|
|
|
|
|
|
/* Net bridge is currently not supported for W32. */
|
|
/* Net bridge is currently not supported for W32. */
|
|
#if !defined(_WIN32)
|
|
#if !defined(_WIN32)
|
|
@@ -63,6 +64,16 @@
|
|
static VMChangeStateEntry *net_change_state_entry;
|
|
static VMChangeStateEntry *net_change_state_entry;
|
|
static QTAILQ_HEAD(, NetClientState) net_clients;
|
|
static QTAILQ_HEAD(, NetClientState) net_clients;
|
|
|
|
|
|
|
|
+typedef struct NetdevQueueEntry {
|
|
|
|
+ Netdev *nd;
|
|
|
|
+ Location loc;
|
|
|
|
+ QSIMPLEQ_ENTRY(NetdevQueueEntry) entry;
|
|
|
|
+} NetdevQueueEntry;
|
|
|
|
+
|
|
|
|
+typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue;
|
|
|
|
+
|
|
|
|
+static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue);
|
|
|
|
+
|
|
/***********************************************************/
|
|
/***********************************************************/
|
|
/* network device redirectors */
|
|
/* network device redirectors */
|
|
|
|
|
|
@@ -1566,6 +1577,20 @@ out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void netdev_init_modern(void)
|
|
|
|
+{
|
|
|
|
+ while (!QSIMPLEQ_EMPTY(&nd_queue)) {
|
|
|
|
+ NetdevQueueEntry *nd = QSIMPLEQ_FIRST(&nd_queue);
|
|
|
|
+
|
|
|
|
+ QSIMPLEQ_REMOVE_HEAD(&nd_queue, entry);
|
|
|
|
+ loc_push_restore(&nd->loc);
|
|
|
|
+ net_client_init1(nd->nd, true, &error_fatal);
|
|
|
|
+ loc_pop(&nd->loc);
|
|
|
|
+ qapi_free_Netdev(nd->nd);
|
|
|
|
+ g_free(nd);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void net_init_clients(void)
|
|
void net_init_clients(void)
|
|
{
|
|
{
|
|
net_change_state_entry =
|
|
net_change_state_entry =
|
|
@@ -1573,6 +1598,8 @@ void net_init_clients(void)
|
|
|
|
|
|
QTAILQ_INIT(&net_clients);
|
|
QTAILQ_INIT(&net_clients);
|
|
|
|
|
|
|
|
+ netdev_init_modern();
|
|
|
|
+
|
|
qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
|
|
qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
|
|
&error_fatal);
|
|
&error_fatal);
|
|
|
|
|
|
@@ -1583,6 +1610,36 @@ void net_init_clients(void)
|
|
&error_fatal);
|
|
&error_fatal);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Does this -netdev argument use modern rather than traditional syntax?
|
|
|
|
+ * Modern syntax is to be parsed with netdev_parse_modern().
|
|
|
|
+ * Traditional syntax is to be parsed with net_client_parse().
|
|
|
|
+ */
|
|
|
|
+bool netdev_is_modern(const char *optarg)
|
|
|
|
+{
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * netdev_parse_modern() uses modern, more expressive syntax than
|
|
|
|
+ * net_client_parse(), but supports only the -netdev option.
|
|
|
|
+ * netdev_parse_modern() appends to @nd_queue, whereas net_client_parse()
|
|
|
|
+ * appends to @qemu_netdev_opts.
|
|
|
|
+ */
|
|
|
|
+void netdev_parse_modern(const char *optarg)
|
|
|
|
+{
|
|
|
|
+ Visitor *v;
|
|
|
|
+ NetdevQueueEntry *nd;
|
|
|
|
+
|
|
|
|
+ v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
|
|
|
|
+ nd = g_new(NetdevQueueEntry, 1);
|
|
|
|
+ visit_type_Netdev(v, NULL, &nd->nd, &error_fatal);
|
|
|
|
+ visit_free(v);
|
|
|
|
+ loc_save(&nd->loc);
|
|
|
|
+
|
|
|
|
+ QSIMPLEQ_INSERT_TAIL(&nd_queue, nd, entry);
|
|
|
|
+}
|
|
|
|
+
|
|
void net_client_parse(QemuOptsList *opts_list, const char *optarg)
|
|
void net_client_parse(QemuOptsList *opts_list, const char *optarg)
|
|
{
|
|
{
|
|
if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
|
|
if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
|