1
The following changes since commit e607bbee553cfe73072870cef458cfa4e78133e2:
1
The following changes since commit d0d3dd401b70168a353450e031727affee828527:
2
2
3
Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2018-01-26.for-upstream' into staging (2018-01-26 14:24:25 +0000)
3
Update version for v6.0.0-rc2 release (2021-04-06 18:34:34 +0100)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to bf4835a4d5338bb7424827715df22570a8adc67c:
9
for you to fetch changes up to 21df394d9e2ffce9fa308f496d1ae228cf6cdb57:
10
10
11
MAINTAINERS: update Dmitry Fleytman email (2018-01-29 16:05:38 +0800)
11
tap-win32: correctly recycle buffers (2021-04-08 17:33:59 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
Fixes for rc3:
16
Mao Zhongyi (2):
17
colo: modified the payload compare function
18
colo: compare the packet based on the tcp sequence number
19
16
20
Philippe Mathieu-Daudé (1):
17
- query-netdev is reverted (that's why the changeset is huge)
21
MAINTAINERS: update Dmitry Fleytman email
18
- fix a regression caused by padding for in TAP for win32
22
23
Thomas Huth (3):
24
net: Allow hubports to connect to other netdevs
25
net: Allow netdevs to be used with 'hostfwd_add' and 'hostfwd_remove'
26
qemu-doc: Get rid of "vlan=X" example in the documentation
27
28
MAINTAINERS | 8 +-
29
hmp-commands.hx | 4 +-
30
net/colo-compare.c | 411 +++++++++++++++++++++++++++++++++--------------------
31
net/colo.c | 9 ++
32
net/colo.h | 15 ++
33
net/hub.c | 27 +++-
34
net/hub.h | 3 +-
35
net/net.c | 2 +-
36
net/slirp.c | 33 +++--
37
net/trace-events | 2 +-
38
qapi/net.json | 4 +-
39
qemu-options.hx | 12 +-
40
12 files changed, 347 insertions(+), 183 deletions(-)
41
19
42
20
21
----------------------------------------------------------------
22
Jason Wang (6):
23
Revert "net: Do not fill legacy info_str for backends"
24
Revert "hmp: Use QAPI NetdevInfo in hmp_info_network"
25
Revert "net: Move NetClientState.info_str to dynamic allocations"
26
Revert "tests: Add tests for query-netdev command"
27
Revert "qapi: net: Add query-netdev command"
28
tap-win32: correctly recycle buffers
29
30
hw/net/xen_nic.c | 5 +-
31
include/net/net.h | 5 +-
32
include/qapi/hmp-output-visitor.h | 30 ------
33
net/l2tpv3.c | 8 +-
34
net/net.c | 73 ++------------
35
net/netmap.c | 7 --
36
net/slirp.c | 124 +-----------------------
37
net/socket.c | 92 +++++-------------
38
net/tap-win32.c | 16 ++--
39
net/tap.c | 107 +++------------------
40
net/vde.c | 25 +----
41
net/vhost-user.c | 20 +---
42
net/vhost-vdpa.c | 15 +--
43
qapi/hmp-output-visitor.c | 193 --------------------------------------
44
qapi/meson.build | 1 -
45
qapi/net.json | 80 ----------------
46
tests/qtest/meson.build | 3 -
47
tests/qtest/test-query-netdev.c | 120 ------------------------
48
18 files changed, 66 insertions(+), 858 deletions(-)
49
delete mode 100644 include/qapi/hmp-output-visitor.h
50
delete mode 100644 qapi/hmp-output-visitor.c
51
delete mode 100644 tests/qtest/test-query-netdev.c
52
53
54
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Several issues has been reported for query-netdev info
2
2
series. Consider it's late in the rc, this reverts commit
3
gently asked by his automatic reply :)
3
f2e8319d456724c3d8514d943dc4607e2f08e88a.
4
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
6
---
8
MAINTAINERS | 8 ++++----
7
net/l2tpv3.c | 2 ++
9
1 file changed, 4 insertions(+), 4 deletions(-)
8
net/slirp.c | 3 +++
10
9
net/socket.c | 28 ++++++++++++++++++++++++++++
11
diff --git a/MAINTAINERS b/MAINTAINERS
10
net/tap-win32.c | 2 ++
12
index XXXXXXX..XXXXXXX 100644
11
net/tap.c | 9 +++++++++
13
--- a/MAINTAINERS
12
net/vde.c | 2 ++
14
+++ b/MAINTAINERS
13
net/vhost-user.c | 1 +
15
@@ -XXX,XX +XXX,XX @@ F: hw/scsi/mfi.h
14
net/vhost-vdpa.c | 1 +
16
F: tests/megasas-test.c
15
8 files changed, 48 insertions(+)
17
16
18
Network packet abstractions
17
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
19
-M: Dmitry Fleytman <dmitry@daynix.com>
18
index XXXXXXX..XXXXXXX 100644
20
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
19
--- a/net/l2tpv3.c
21
S: Maintained
20
+++ b/net/l2tpv3.c
22
F: include/net/eth.h
21
@@ -XXX,XX +XXX,XX @@ int net_init_l2tpv3(const Netdev *netdev,
23
F: net/eth.c
22
24
@@ -XXX,XX +XXX,XX @@ F: hw/net/net_rx_pkt*
23
QAPI_CLONE_MEMBERS(NetdevL2TPv3Options,
25
F: hw/net/net_tx_pkt*
24
&nc->stored_config->u.l2tpv3, l2tpv3);
26
25
+
27
Vmware
26
+ s->nc.info_str = g_strdup_printf("l2tpv3: connected");
28
-M: Dmitry Fleytman <dmitry@daynix.com>
27
return 0;
29
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
28
outerr:
30
S: Maintained
29
qemu_del_net_client(nc);
31
F: hw/net/vmxnet*
30
diff --git a/net/slirp.c b/net/slirp.c
32
F: hw/scsi/vmw_pvscsi*
31
index XXXXXXX..XXXXXXX 100644
33
@@ -XXX,XX +XXX,XX @@ F: hw/mem/nvdimm.c
32
--- a/net/slirp.c
34
F: include/hw/mem/nvdimm.h
33
+++ b/net/slirp.c
35
34
@@ -XXX,XX +XXX,XX @@ static int net_slirp_init(NetClientState *peer, const char *model,
36
e1000x
35
stored->tftp_server_name = g_strdup(tftp_server_name);
37
-M: Dmitry Fleytman <dmitry@daynix.com>
36
}
38
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
37
39
S: Maintained
38
+ nc->info_str = g_strdup_printf("net=%s,restrict=%s", inet_ntoa(net),
40
F: hw/net/e1000x*
39
+ restricted ? "on" : "off");
41
40
+
42
e1000e
41
s = DO_UPCAST(SlirpState, nc, nc);
43
-M: Dmitry Fleytman <dmitry@daynix.com>
42
44
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
43
s->slirp = slirp_init(restricted, ipv4, net, mask, host,
45
S: Maintained
44
diff --git a/net/socket.c b/net/socket.c
46
F: hw/net/e1000e*
45
index XXXXXXX..XXXXXXX 100644
47
46
--- a/net/socket.c
47
+++ b/net/socket.c
48
@@ -XXX,XX +XXX,XX @@ static void net_socket_send(void *opaque)
49
s->fd = -1;
50
net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
51
s->nc.link_down = true;
52
+ g_free(s->nc.info_str);
53
+ s->nc.info_str = g_new0(char, 1);
54
55
return;
56
}
57
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
58
stored->mcast = g_strdup(mcast);
59
60
s->dgram_dst = saddr;
61
+ nc->info_str = g_strdup_printf("socket: fd=%d (cloned mcast=%s:%d)",
62
+ fd, inet_ntoa(saddr.sin_addr),
63
+ ntohs(saddr.sin_port));
64
} else {
65
if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) {
66
s->dgram_dst.sin_family = AF_UNIX;
67
}
68
+
69
+ nc->info_str = g_strdup_printf("socket: fd=%d %s",
70
+ fd, SocketAddressType_str(sa_type));
71
}
72
73
return s;
74
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
75
76
nc = qemu_new_net_client(&net_socket_info, peer, model, name);
77
78
+ nc->info_str = g_strdup_printf("socket: fd=%d", fd);
79
+
80
s = DO_UPCAST(NetSocketState, nc, nc);
81
82
s->fd = fd;
83
@@ -XXX,XX +XXX,XX @@ static void net_socket_accept(void *opaque)
84
85
stored->has_fd = true;
86
stored->fd = g_strdup_printf("%d", fd);
87
+
88
+ g_free(s->nc.info_str);
89
+ s->nc.info_str = g_strdup_printf("socket: connection from %s:%d",
90
+ inet_ntoa(saddr.sin_addr),
91
+ ntohs(saddr.sin_port));
92
}
93
94
static int net_socket_listen_init(NetClientState *peer,
95
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
96
stored->has_connect = true;
97
stored->connect = g_strdup(host_str);
98
99
+ g_free(s->nc.info_str);
100
+ s->nc.info_str = g_strdup_printf("socket: connect to %s:%d",
101
+ inet_ntoa(saddr.sin_addr),
102
+ ntohs(saddr.sin_port));
103
return 0;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
107
stored->localaddr = g_strdup(localaddr_str);
108
}
109
110
+ g_free(s->nc.info_str);
111
+ s->nc.info_str = g_strdup_printf("socket: mcast=%s:%d",
112
+ inet_ntoa(saddr.sin_addr),
113
+ ntohs(saddr.sin_port));
114
return 0;
115
+
116
}
117
118
static int net_socket_udp_init(NetClientState *peer,
119
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
120
stored->has_udp = true;
121
stored->udp = g_strdup(rhost);
122
123
+ g_free(s->nc.info_str);
124
+ s->nc.info_str = g_strdup_printf("socket: udp=%s:%d",
125
+ inet_ntoa(raddr.sin_addr),
126
+ ntohs(raddr.sin_port));
127
return 0;
128
}
129
130
diff --git a/net/tap-win32.c b/net/tap-win32.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/net/tap-win32.c
133
+++ b/net/tap-win32.c
134
@@ -XXX,XX +XXX,XX @@ static int tap_win32_init(NetClientState *peer, const char *model,
135
stored->has_ifname = true;
136
stored->ifname = g_strdup(ifname);
137
138
+ s->nc.info_str = g_strdup_printf("tap: ifname=%s", ifname);
139
+
140
s->handle = handle;
141
142
qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
143
diff --git a/net/tap.c b/net/tap.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/net/tap.c
146
+++ b/net/tap.c
147
@@ -XXX,XX +XXX,XX @@ int net_init_bridge(const Netdev *netdev, const char *name,
148
stored->helper = g_strdup(helper);
149
}
150
151
+ s->nc.info_str = g_strdup_printf("helper=%s,br=%s", helper, br);
152
+
153
return 0;
154
}
155
156
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
157
stored->fds = g_strdup_printf("%s:%d", stored->fds, fd);
158
g_free(tmp_s);
159
}
160
+
161
+ s->nc.info_str = g_strdup_printf("fd=%d", fd);
162
} else if (tap->has_helper) {
163
if (!stored->has_helper) {
164
stored->has_helper = true;
165
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
166
stored->br = tap->has_br ? g_strdup(tap->br) :
167
g_strdup(DEFAULT_BRIDGE_INTERFACE);
168
}
169
+
170
+ s->nc.info_str = g_strdup_printf("helper=%s", tap->helper);
171
} else {
172
if (ifname && !stored->has_ifname) {
173
stored->has_ifname = true;
174
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
175
stored->downscript = g_strdup(downscript);
176
}
177
178
+ s->nc.info_str = g_strdup_printf("ifname=%s,script=%s,downscript=%s",
179
+ ifname, script, downscript);
180
+
181
if (strcmp(downscript, "no") != 0) {
182
snprintf(s->down_script, sizeof(s->down_script), "%s", downscript);
183
snprintf(s->down_script_arg, sizeof(s->down_script_arg),
184
diff --git a/net/vde.c b/net/vde.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/net/vde.c
187
+++ b/net/vde.c
188
@@ -XXX,XX +XXX,XX @@ static int net_vde_init(NetClientState *peer, const char *model,
189
190
nc = qemu_new_net_client(&net_vde_info, peer, model, name);
191
192
+ nc->info_str = g_strdup_printf("sock=%s,fd=%d", sock, vde_datafd(vde));
193
+
194
s = DO_UPCAST(VDEState, nc, nc);
195
196
s->vde = vde;
197
diff --git a/net/vhost-user.c b/net/vhost-user.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/net/vhost-user.c
200
+++ b/net/vhost-user.c
201
@@ -XXX,XX +XXX,XX @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
202
user = g_new0(struct VhostUserState, 1);
203
for (i = 0; i < queues; i++) {
204
nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
205
+ nc->info_str = g_strdup_printf("vhost-user%d to %s", i, chr->label);
206
nc->queue_index = i;
207
if (!nc0) {
208
nc0 = nc;
209
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
210
index XXXXXXX..XXXXXXX 100644
211
--- a/net/vhost-vdpa.c
212
+++ b/net/vhost-vdpa.c
213
@@ -XXX,XX +XXX,XX @@ static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
214
stored->has_queues = true;
215
stored->queues = 1; /* TODO: change when support multiqueue */
216
217
+ nc->info_str = g_strdup_printf(TYPE_VHOST_VDPA);
218
nc->queue_index = 0;
219
s = DO_UPCAST(VhostVDPAState, nc, nc);
220
vdpa_device_fd = qemu_open_old(vhostdev, O_RDWR);
48
--
221
--
49
2.7.4
222
2.7.4
50
223
51
224
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
Several issues has been reported for query-netdev info
2
series. Consider it's late in the rc, this reverts commit
3
a0724776c5a98a08fc946bb5a4ad16410ca64c0e.
2
4
3
The vlan concept is marked as deprecated, so we should not use
4
this for examples in the documentation anymore.
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
6
---
9
qemu-options.hx | 4 ++--
7
include/qapi/hmp-output-visitor.h | 30 ------
10
1 file changed, 2 insertions(+), 2 deletions(-)
8
net/net.c | 31 +-----
9
qapi/hmp-output-visitor.c | 193 --------------------------------------
10
qapi/meson.build | 1 -
11
4 files changed, 1 insertion(+), 254 deletions(-)
12
delete mode 100644 include/qapi/hmp-output-visitor.h
13
delete mode 100644 qapi/hmp-output-visitor.c
11
14
12
diff --git a/qemu-options.hx b/qemu-options.hx
15
diff --git a/include/qapi/hmp-output-visitor.h b/include/qapi/hmp-output-visitor.h
16
deleted file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- a/include/qapi/hmp-output-visitor.h
19
+++ /dev/null
20
@@ -XXX,XX +XXX,XX @@
21
-/*
22
- * HMP string output Visitor
23
- *
24
- * Copyright Yandex N.V., 2021
25
- *
26
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
27
- * See the COPYING file in the top-level directory.
28
- *
29
- */
30
-
31
-#ifndef HMP_OUTPUT_VISITOR_H
32
-#define HMP_OUTPUT_VISITOR_H
33
-
34
-#include "qapi/visitor.h"
35
-
36
-typedef struct HMPOutputVisitor HMPOutputVisitor;
37
-
38
-/**
39
- * Create a HMP string output visitor for @obj
40
- *
41
- * Flattens dicts/structures, only shows arrays borders.
42
- *
43
- * Errors are not expected to happen.
44
- *
45
- * The caller is responsible for freeing the visitor with
46
- * visit_free().
47
- */
48
-Visitor *hmp_output_visitor_new(char **result);
49
-
50
-#endif
51
diff --git a/net/net.c b/net/net.c
13
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
14
--- a/qemu-options.hx
53
--- a/net/net.c
15
+++ b/qemu-options.hx
54
+++ b/net/net.c
16
@@ -XXX,XX +XXX,XX @@ qemu-system-i386 linux.img -net nic -net tap
55
@@ -XXX,XX +XXX,XX @@
17
#launch a QEMU instance with two NICs, each one connected
56
#include "sysemu/sysemu.h"
18
#to a TAP device
57
#include "net/filter.h"
19
qemu-system-i386 linux.img \
58
#include "qapi/string-output-visitor.h"
20
- -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
59
-#include "qapi/hmp-output-visitor.h"
21
- -net nic,vlan=1 -net tap,vlan=1,ifname=tap1
60
22
+ -netdev tap,id=nd0,ifname=tap0 -device e1000,netdev=nd0 \
61
/* Net bridge is currently not supported for W32. */
23
+ -netdev tap,id=nd1,ifname=tap1 -device rtl8139,netdev=nd1
62
#if !defined(_WIN32)
24
@end example
63
@@ -XXX,XX +XXX,XX @@ static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
25
64
monitor_printf(mon, "\n");
26
@example
65
}
66
67
-static char *generate_info_str(NetClientState *nc)
68
-{
69
- NetdevInfo *ni = nc->stored_config;
70
- char *ret_out = NULL;
71
- Visitor *v;
72
-
73
- /* Use legacy field info_str for NIC and hubports */
74
- if ((nc->info->type == NET_CLIENT_DRIVER_NIC) ||
75
- (nc->info->type == NET_CLIENT_DRIVER_HUBPORT)) {
76
- return g_strdup(nc->info_str ? nc->info_str : "");
77
- }
78
-
79
- if (!ni) {
80
- return g_malloc0(1);
81
- }
82
-
83
- v = hmp_output_visitor_new(&ret_out);
84
- if (visit_type_NetdevInfo(v, "", &ni, NULL)) {
85
- visit_complete(v, &ret_out);
86
- }
87
- visit_free(v);
88
-
89
- return ret_out;
90
-}
91
-
92
void print_net_client(Monitor *mon, NetClientState *nc)
93
{
94
NetFilterState *nf;
95
- char *info_str = generate_info_str(nc);
96
97
monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
98
nc->queue_index,
99
NetClientDriver_str(nc->info->type),
100
- info_str);
101
- g_free(info_str);
102
-
103
+ nc->info_str ? nc->info_str : "");
104
if (!QTAILQ_EMPTY(&nc->filters)) {
105
monitor_printf(mon, "filters:\n");
106
}
107
diff --git a/qapi/hmp-output-visitor.c b/qapi/hmp-output-visitor.c
108
deleted file mode 100644
109
index XXXXXXX..XXXXXXX
110
--- a/qapi/hmp-output-visitor.c
111
+++ /dev/null
112
@@ -XXX,XX +XXX,XX @@
113
-/*
114
- * HMP string output Visitor
115
- *
116
- * Copyright Yandex N.V., 2021
117
- *
118
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
119
- * See the COPYING file in the top-level directory.
120
- *
121
- */
122
-
123
-#include "qemu/osdep.h"
124
-#include "qemu/cutils.h"
125
-#include "qapi/hmp-output-visitor.h"
126
-#include "qapi/visitor-impl.h"
127
-
128
-struct HMPOutputVisitor {
129
- Visitor visitor;
130
- char **result;
131
- GString *buffer;
132
- bool is_continue;
133
-};
134
-
135
-static HMPOutputVisitor *to_hov(Visitor *v)
136
-{
137
- return container_of(v, HMPOutputVisitor, visitor);
138
-}
139
-
140
-static void hmp_output_append_formatted(Visitor *v, const char *fmt, ...)
141
-{
142
- HMPOutputVisitor *ov = to_hov(v);
143
- va_list args;
144
-
145
- if (ov->is_continue) {
146
- g_string_append(ov->buffer, ",");
147
- } else {
148
- ov->is_continue = true;
149
- }
150
-
151
- va_start(args, fmt);
152
- g_string_append_vprintf(ov->buffer, fmt, args);
153
- va_end(args);
154
-}
155
-
156
-static void hmp_output_skip_comma(Visitor *v)
157
-{
158
- HMPOutputVisitor *ov = to_hov(v);
159
-
160
- ov->is_continue = false;
161
-}
162
-
163
-static bool hmp_output_start_struct(Visitor *v, const char *name,
164
- void **obj, size_t unused, Error **errp)
165
-{
166
- return true;
167
-}
168
-
169
-static void hmp_output_end_struct(Visitor *v, void **obj) {}
170
-
171
-static bool hmp_output_start_list(Visitor *v, const char *name,
172
- GenericList **listp, size_t size,
173
- Error **errp)
174
-{
175
- hmp_output_append_formatted(v, "%s=[", name);
176
- /* First element in array without comma before it */
177
- hmp_output_skip_comma(v);
178
-
179
- return true;
180
-}
181
-
182
-static GenericList *hmp_output_next_list(Visitor *v, GenericList *tail,
183
- size_t size)
184
-{
185
- return tail->next;
186
-}
187
-
188
-static void hmp_output_end_list(Visitor *v, void **obj)
189
-{
190
- /* Don't need comma after last array element */
191
- hmp_output_skip_comma(v);
192
- hmp_output_append_formatted(v, "]");
193
-}
194
-
195
-static bool hmp_output_type_int64(Visitor *v, const char *name,
196
- int64_t *obj, Error **errp)
197
-{
198
- hmp_output_append_formatted(v, "%s=%" PRId64, name, *obj);
199
-
200
- return true;
201
-}
202
-
203
-static bool hmp_output_type_uint64(Visitor *v, const char *name,
204
- uint64_t *obj, Error **errp)
205
-{
206
- hmp_output_append_formatted(v, "%s=%" PRIu64, name, *obj);
207
-
208
- return true;
209
-}
210
-
211
-static bool hmp_output_type_bool(Visitor *v, const char *name, bool *obj,
212
- Error **errp)
213
-{
214
- hmp_output_append_formatted(v, "%s=%s", name, *obj ? "true" : "false");
215
-
216
- return true;
217
-}
218
-
219
-static bool hmp_output_type_str(Visitor *v, const char *name, char **obj,
220
- Error **errp)
221
-{
222
- /* Skip already printed or unused fields */
223
- if (!*obj || g_str_equal(name, "id") || g_str_equal(name, "type")) {
224
- return true;
225
- }
226
-
227
- /* Do not print stub name for StringList elements */
228
- if (g_str_equal(name, "str")) {
229
- hmp_output_append_formatted(v, "%s", *obj);
230
- } else {
231
- hmp_output_append_formatted(v, "%s=%s", name, *obj);
232
- }
233
-
234
- return true;
235
-}
236
-
237
-static bool hmp_output_type_number(Visitor *v, const char *name,
238
- double *obj, Error **errp)
239
-{
240
- hmp_output_append_formatted(v, "%s=%.17g", name, *obj);
241
-
242
- return true;
243
-}
244
-
245
-/* TODO: remove this function? */
246
-static bool hmp_output_type_any(Visitor *v, const char *name,
247
- QObject **obj, Error **errp)
248
-{
249
- return true;
250
-}
251
-
252
-static bool hmp_output_type_null(Visitor *v, const char *name,
253
- QNull **obj, Error **errp)
254
-{
255
- hmp_output_append_formatted(v, "%s=NULL", name);
256
-
257
- return true;
258
-}
259
-
260
-static void hmp_output_complete(Visitor *v, void *opaque)
261
-{
262
- HMPOutputVisitor *ov = to_hov(v);
263
-
264
- *ov->result = g_string_free(ov->buffer, false);
265
- ov->buffer = NULL;
266
-}
267
-
268
-static void hmp_output_free(Visitor *v)
269
-{
270
- HMPOutputVisitor *ov = to_hov(v);
271
-
272
- if (ov->buffer) {
273
- g_string_free(ov->buffer, true);
274
- }
275
- g_free(v);
276
-}
277
-
278
-Visitor *hmp_output_visitor_new(char **result)
279
-{
280
- HMPOutputVisitor *v;
281
-
282
- v = g_malloc0(sizeof(*v));
283
-
284
- v->visitor.type = VISITOR_OUTPUT;
285
- v->visitor.start_struct = hmp_output_start_struct;
286
- v->visitor.end_struct = hmp_output_end_struct;
287
- v->visitor.start_list = hmp_output_start_list;
288
- v->visitor.next_list = hmp_output_next_list;
289
- v->visitor.end_list = hmp_output_end_list;
290
- v->visitor.type_int64 = hmp_output_type_int64;
291
- v->visitor.type_uint64 = hmp_output_type_uint64;
292
- v->visitor.type_bool = hmp_output_type_bool;
293
- v->visitor.type_str = hmp_output_type_str;
294
- v->visitor.type_number = hmp_output_type_number;
295
- v->visitor.type_any = hmp_output_type_any;
296
- v->visitor.type_null = hmp_output_type_null;
297
- v->visitor.complete = hmp_output_complete;
298
- v->visitor.free = hmp_output_free;
299
-
300
- v->result = result;
301
- v->buffer = g_string_new("");
302
- v->is_continue = false;
303
-
304
- return &v->visitor;
305
-}
306
diff --git a/qapi/meson.build b/qapi/meson.build
307
index XXXXXXX..XXXXXXX 100644
308
--- a/qapi/meson.build
309
+++ b/qapi/meson.build
310
@@ -XXX,XX +XXX,XX @@ util_ss.add(files(
311
'qobject-output-visitor.c',
312
'string-input-visitor.c',
313
'string-output-visitor.c',
314
- 'hmp-output-visitor.c',
315
))
316
if have_system or have_tools
317
util_ss.add(files(
27
--
318
--
28
2.7.4
319
2.7.4
29
320
30
321
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
Several issues has been reported for query-netdev info
2
series. Consider it's late in the rc, this reverts commit
3
commit 59b5437eb732d6b103a9bc279c3482c834d1eff9.
2
4
3
It does not make much sense to limit these commands to the legacy 'vlan'
4
concept only, they should work with the modern netdevs, too. So now
5
it is possible to use this command with one, two or three parameters.
6
7
With one parameter, the command installs a hostfwd rule on the default
8
"user" network:
9
hostfwd_add tcp:...
10
11
With two parameters, the command installs a hostfwd rule on a netdev
12
(that's the new way of using this command):
13
hostfwd_add netdev_id tcp:...
14
15
With three parameters, the command installs a rule on a 'vlan' (aka hub):
16
hostfwd_add hub_id name tcp:...
17
18
Same applies to the hostfwd_remove command now.
19
20
Signed-off-by: Thomas Huth <thuth@redhat.com>
21
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
22
---
6
---
23
hmp-commands.hx | 4 ++--
7
hw/net/xen_nic.c | 5 +++--
24
net/slirp.c | 33 +++++++++++++++++++++++----------
8
include/net/net.h | 2 +-
25
2 files changed, 25 insertions(+), 12 deletions(-)
9
net/l2tpv3.c | 3 ++-
10
net/net.c | 14 ++++++--------
11
net/slirp.c | 5 +++--
12
net/socket.c | 43 +++++++++++++++++++------------------------
13
net/tap-win32.c | 3 ++-
14
net/tap.c | 13 ++++++++-----
15
net/vde.c | 3 ++-
16
net/vhost-user.c | 3 ++-
17
net/vhost-vdpa.c | 2 +-
18
11 files changed, 49 insertions(+), 47 deletions(-)
26
19
27
diff --git a/hmp-commands.hx b/hmp-commands.hx
20
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
28
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
29
--- a/hmp-commands.hx
22
--- a/hw/net/xen_nic.c
30
+++ b/hmp-commands.hx
23
+++ b/hw/net/xen_nic.c
31
@@ -XXX,XX +XXX,XX @@ ETEXI
24
@@ -XXX,XX +XXX,XX @@ static int net_init(struct XenLegacyDevice *xendev)
32
{
25
netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf,
33
.name = "hostfwd_add",
26
"xen", NULL, netdev);
34
.args_type = "arg1:s,arg2:s?,arg3:s?",
27
35
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
28
- qemu_get_queue(netdev->nic)->info_str = g_strdup_printf(
36
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
29
- "nic: xenbus vif macaddr=%s", netdev->mac);
37
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
30
+ snprintf(qemu_get_queue(netdev->nic)->info_str,
38
.cmd = hmp_hostfwd_add,
31
+ sizeof(qemu_get_queue(netdev->nic)->info_str),
39
},
32
+ "nic: xenbus vif macaddr=%s", netdev->mac);
40
@@ -XXX,XX +XXX,XX @@ ETEXI
33
41
{
34
/* fill info */
42
.name = "hostfwd_remove",
35
xenstore_write_be_int(&netdev->xendev, "feature-rx-copy", 1);
43
.args_type = "arg1:s,arg2:s?,arg3:s?",
36
diff --git a/include/net/net.h b/include/net/net.h
44
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
37
index XXXXXXX..XXXXXXX 100644
45
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport",
38
--- a/include/net/net.h
46
.help = "remove host-to-guest TCP or UDP redirection",
39
+++ b/include/net/net.h
47
.cmd = hmp_hostfwd_remove,
40
@@ -XXX,XX +XXX,XX @@ struct NetClientState {
48
},
41
NetQueue *incoming_queue;
42
char *model;
43
char *name;
44
- char *info_str;
45
+ char info_str[256];
46
NetdevInfo *stored_config;
47
unsigned receive_disabled : 1;
48
NetClientDestructor *destructor;
49
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/net/l2tpv3.c
52
+++ b/net/l2tpv3.c
53
@@ -XXX,XX +XXX,XX @@ int net_init_l2tpv3(const Netdev *netdev,
54
QAPI_CLONE_MEMBERS(NetdevL2TPv3Options,
55
&nc->stored_config->u.l2tpv3, l2tpv3);
56
57
- s->nc.info_str = g_strdup_printf("l2tpv3: connected");
58
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
59
+ "l2tpv3: connected");
60
return 0;
61
outerr:
62
qemu_del_net_client(nc);
63
diff --git a/net/net.c b/net/net.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/net/net.c
66
+++ b/net/net.c
67
@@ -XXX,XX +XXX,XX @@ char *qemu_mac_strdup_printf(const uint8_t *macaddr)
68
69
void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
70
{
71
- g_free(nc->info_str);
72
- nc->info_str = g_strdup_printf(
73
- "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
74
- nc->model,
75
- macaddr[0], macaddr[1], macaddr[2],
76
- macaddr[3], macaddr[4], macaddr[5]);
77
+ snprintf(nc->info_str, sizeof(nc->info_str),
78
+ "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
79
+ nc->model,
80
+ macaddr[0], macaddr[1], macaddr[2],
81
+ macaddr[3], macaddr[4], macaddr[5]);
82
}
83
84
static int mac_table[256] = {0};
85
@@ -XXX,XX +XXX,XX @@ static void qemu_free_net_client(NetClientState *nc)
86
}
87
g_free(nc->name);
88
g_free(nc->model);
89
- g_free(nc->info_str);
90
qapi_free_NetdevInfo(nc->stored_config);
91
if (nc->destructor) {
92
nc->destructor(nc);
93
@@ -XXX,XX +XXX,XX @@ void print_net_client(Monitor *mon, NetClientState *nc)
94
monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
95
nc->queue_index,
96
NetClientDriver_str(nc->info->type),
97
- nc->info_str ? nc->info_str : "");
98
+ nc->info_str);
99
if (!QTAILQ_EMPTY(&nc->filters)) {
100
monitor_printf(mon, "filters:\n");
101
}
49
diff --git a/net/slirp.c b/net/slirp.c
102
diff --git a/net/slirp.c b/net/slirp.c
50
index XXXXXXX..XXXXXXX 100644
103
index XXXXXXX..XXXXXXX 100644
51
--- a/net/slirp.c
104
--- a/net/slirp.c
52
+++ b/net/slirp.c
105
+++ b/net/slirp.c
53
@@ -XXX,XX +XXX,XX @@ error:
106
@@ -XXX,XX +XXX,XX @@ static int net_slirp_init(NetClientState *peer, const char *model,
54
return -1;
107
stored->tftp_server_name = g_strdup(tftp_server_name);
55
}
108
}
56
109
57
-static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
110
- nc->info_str = g_strdup_printf("net=%s,restrict=%s", inet_ntoa(net),
58
- const char *stack)
111
- restricted ? "on" : "off");
59
+static SlirpState *slirp_lookup(Monitor *mon, const char *hub_id,
112
+ snprintf(nc->info_str, sizeof(nc->info_str),
60
+ const char *name)
113
+ "net=%s,restrict=%s", inet_ntoa(net),
61
{
114
+ restricted ? "on" : "off");
62
-
115
63
- if (vlan) {
116
s = DO_UPCAST(SlirpState, nc, nc);
64
+ if (name) {
117
65
NetClientState *nc;
118
diff --git a/net/socket.c b/net/socket.c
66
- nc = net_hub_find_client_by_name(strtol(vlan, NULL, 0), stack);
119
index XXXXXXX..XXXXXXX 100644
67
- if (!nc) {
120
--- a/net/socket.c
68
- monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
121
+++ b/net/socket.c
69
- return NULL;
122
@@ -XXX,XX +XXX,XX @@ static void net_socket_send(void *opaque)
70
+ if (hub_id) {
123
s->fd = -1;
71
+ nc = net_hub_find_client_by_name(strtol(hub_id, NULL, 0), name);
124
net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
72
+ if (!nc) {
125
s->nc.link_down = true;
73
+ monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
126
- g_free(s->nc.info_str);
74
+ return NULL;
127
- s->nc.info_str = g_new0(char, 1);
75
+ }
128
+ memset(s->nc.info_str, 0, sizeof(s->nc.info_str));
76
+ } else {
129
77
+ nc = qemu_find_netdev(name);
130
return;
78
+ if (!nc) {
131
}
79
+ monitor_printf(mon, "unrecognized netdev id '%s'\n", name);
132
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
80
+ return NULL;
133
stored->mcast = g_strdup(mcast);
81
+ }
134
135
s->dgram_dst = saddr;
136
- nc->info_str = g_strdup_printf("socket: fd=%d (cloned mcast=%s:%d)",
137
- fd, inet_ntoa(saddr.sin_addr),
138
- ntohs(saddr.sin_port));
139
+ snprintf(nc->info_str, sizeof(nc->info_str),
140
+ "socket: fd=%d (cloned mcast=%s:%d)",
141
+ fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
142
} else {
143
if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) {
144
s->dgram_dst.sin_family = AF_UNIX;
82
}
145
}
83
if (strcmp(nc->model, "user")) {
146
84
monitor_printf(mon, "invalid device specified\n");
147
- nc->info_str = g_strdup_printf("socket: fd=%d %s",
85
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
148
- fd, SocketAddressType_str(sa_type));
86
const char *arg2 = qdict_get_try_str(qdict, "arg2");
149
+ snprintf(nc->info_str, sizeof(nc->info_str),
87
const char *arg3 = qdict_get_try_str(qdict, "arg3");
150
+ "socket: fd=%d %s", fd, SocketAddressType_str(sa_type));
88
151
}
89
- if (arg2) {
152
90
+ if (arg3) {
153
return s;
91
s = slirp_lookup(mon, arg1, arg2);
154
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
92
src_str = arg3;
155
93
+ } else if (arg2) {
156
nc = qemu_new_net_client(&net_socket_info, peer, model, name);
94
+ s = slirp_lookup(mon, NULL, arg1);
157
95
+ src_str = arg2;
158
- nc->info_str = g_strdup_printf("socket: fd=%d", fd);
159
+ snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd);
160
161
s = DO_UPCAST(NetSocketState, nc, nc);
162
163
@@ -XXX,XX +XXX,XX @@ static void net_socket_accept(void *opaque)
164
stored->has_fd = true;
165
stored->fd = g_strdup_printf("%d", fd);
166
167
- g_free(s->nc.info_str);
168
- s->nc.info_str = g_strdup_printf("socket: connection from %s:%d",
169
- inet_ntoa(saddr.sin_addr),
170
- ntohs(saddr.sin_port));
171
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
172
+ "socket: connection from %s:%d",
173
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
174
}
175
176
static int net_socket_listen_init(NetClientState *peer,
177
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
178
stored->has_connect = true;
179
stored->connect = g_strdup(host_str);
180
181
- g_free(s->nc.info_str);
182
- s->nc.info_str = g_strdup_printf("socket: connect to %s:%d",
183
- inet_ntoa(saddr.sin_addr),
184
- ntohs(saddr.sin_port));
185
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
186
+ "socket: connect to %s:%d",
187
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
188
return 0;
189
}
190
191
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
192
stored->localaddr = g_strdup(localaddr_str);
193
}
194
195
- g_free(s->nc.info_str);
196
- s->nc.info_str = g_strdup_printf("socket: mcast=%s:%d",
197
- inet_ntoa(saddr.sin_addr),
198
- ntohs(saddr.sin_port));
199
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
200
+ "socket: mcast=%s:%d",
201
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
202
return 0;
203
204
}
205
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
206
stored->has_udp = true;
207
stored->udp = g_strdup(rhost);
208
209
- g_free(s->nc.info_str);
210
- s->nc.info_str = g_strdup_printf("socket: udp=%s:%d",
211
- inet_ntoa(raddr.sin_addr),
212
- ntohs(raddr.sin_port));
213
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
214
+ "socket: udp=%s:%d",
215
+ inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
216
return 0;
217
}
218
219
diff --git a/net/tap-win32.c b/net/tap-win32.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/net/tap-win32.c
222
+++ b/net/tap-win32.c
223
@@ -XXX,XX +XXX,XX @@ static int tap_win32_init(NetClientState *peer, const char *model,
224
stored->has_ifname = true;
225
stored->ifname = g_strdup(ifname);
226
227
- s->nc.info_str = g_strdup_printf("tap: ifname=%s", ifname);
228
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
229
+ "tap: ifname=%s", ifname);
230
231
s->handle = handle;
232
233
diff --git a/net/tap.c b/net/tap.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/net/tap.c
236
+++ b/net/tap.c
237
@@ -XXX,XX +XXX,XX @@ int net_init_bridge(const Netdev *netdev, const char *name,
238
stored->helper = g_strdup(helper);
239
}
240
241
- s->nc.info_str = g_strdup_printf("helper=%s,br=%s", helper, br);
242
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper,
243
+ br);
244
245
return 0;
246
}
247
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
248
g_free(tmp_s);
249
}
250
251
- s->nc.info_str = g_strdup_printf("fd=%d", fd);
252
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd);
253
} else if (tap->has_helper) {
254
if (!stored->has_helper) {
255
stored->has_helper = true;
256
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
257
g_strdup(DEFAULT_BRIDGE_INTERFACE);
258
}
259
260
- s->nc.info_str = g_strdup_printf("helper=%s", tap->helper);
261
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s",
262
+ tap->helper);
96
} else {
263
} else {
97
s = slirp_lookup(mon, NULL, NULL);
264
if (ifname && !stored->has_ifname) {
98
src_str = arg1;
265
stored->has_ifname = true;
99
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
266
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
100
const char *arg2 = qdict_get_try_str(qdict, "arg2");
267
stored->downscript = g_strdup(downscript);
101
const char *arg3 = qdict_get_try_str(qdict, "arg3");
268
}
102
269
103
- if (arg2) {
270
- s->nc.info_str = g_strdup_printf("ifname=%s,script=%s,downscript=%s",
104
+ if (arg3) {
271
- ifname, script, downscript);
105
s = slirp_lookup(mon, arg1, arg2);
272
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
106
redir_str = arg3;
273
+ "ifname=%s,script=%s,downscript=%s", ifname, script,
107
+ } else if (arg2) {
274
+ downscript);
108
+ s = slirp_lookup(mon, NULL, arg1);
275
109
+ redir_str = arg2;
276
if (strcmp(downscript, "no") != 0) {
110
} else {
277
snprintf(s->down_script, sizeof(s->down_script), "%s", downscript);
111
s = slirp_lookup(mon, NULL, NULL);
278
diff --git a/net/vde.c b/net/vde.c
112
redir_str = arg1;
279
index XXXXXXX..XXXXXXX 100644
280
--- a/net/vde.c
281
+++ b/net/vde.c
282
@@ -XXX,XX +XXX,XX @@ static int net_vde_init(NetClientState *peer, const char *model,
283
284
nc = qemu_new_net_client(&net_vde_info, peer, model, name);
285
286
- nc->info_str = g_strdup_printf("sock=%s,fd=%d", sock, vde_datafd(vde));
287
+ snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d",
288
+ sock, vde_datafd(vde));
289
290
s = DO_UPCAST(VDEState, nc, nc);
291
292
diff --git a/net/vhost-user.c b/net/vhost-user.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/net/vhost-user.c
295
+++ b/net/vhost-user.c
296
@@ -XXX,XX +XXX,XX @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
297
user = g_new0(struct VhostUserState, 1);
298
for (i = 0; i < queues; i++) {
299
nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
300
- nc->info_str = g_strdup_printf("vhost-user%d to %s", i, chr->label);
301
+ snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
302
+ i, chr->label);
303
nc->queue_index = i;
304
if (!nc0) {
305
nc0 = nc;
306
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
307
index XXXXXXX..XXXXXXX 100644
308
--- a/net/vhost-vdpa.c
309
+++ b/net/vhost-vdpa.c
310
@@ -XXX,XX +XXX,XX @@ static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
311
stored->has_queues = true;
312
stored->queues = 1; /* TODO: change when support multiqueue */
313
314
- nc->info_str = g_strdup_printf(TYPE_VHOST_VDPA);
315
+ snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
316
nc->queue_index = 0;
317
s = DO_UPCAST(VhostVDPAState, nc, nc);
318
vdpa_device_fd = qemu_open_old(vhostdev, O_RDWR);
113
--
319
--
114
2.7.4
320
2.7.4
115
321
116
322
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
Several issues has been reported for query-netdev series. Consider
2
it's late in the rc, this reverts commit
3
3c3b656885473ef0d699290ba966177f17839aa5.
2
4
3
Modified the function colo_packet_compare_common to prepare for the
4
tcp packet comparison in the next patch.
5
6
Cc: Zhang Chen <zhangckid@gmail.com>
7
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
8
Cc: Jason Wang <jasowang@redhat.com>
9
10
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
11
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
12
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
13
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
6
---
16
net/colo-compare.c | 88 +++++++++++++++++++++++++++---------------------------
7
tests/qtest/meson.build | 3 -
17
1 file changed, 44 insertions(+), 44 deletions(-)
8
tests/qtest/test-query-netdev.c | 120 ----------------------------------------
9
2 files changed, 123 deletions(-)
10
delete mode 100644 tests/qtest/test-query-netdev.c
18
11
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
12
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
14
--- a/tests/qtest/meson.build
22
+++ b/net/colo-compare.c
15
+++ b/tests/qtest/meson.build
23
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
16
@@ -XXX,XX +XXX,XX @@ qtests_generic = \
24
* return: 0 means packet same
17
if config_host.has_key('CONFIG_MODULES')
25
* > 0 || < 0 means packet different
18
qtests_generic += [ 'modules-test' ]
26
*/
19
endif
27
-static int colo_packet_compare_common(Packet *ppkt,
20
-if slirp.found()
28
- Packet *spkt,
21
- qtests_generic += [ 'test-query-netdev' ]
29
- int poffset,
22
-endif
30
- int soffset)
23
31
+static int colo_compare_packet_payload(Packet *ppkt,
24
qtests_pci = \
32
+ Packet *spkt,
25
(config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) + \
33
+ uint16_t poffset,
26
diff --git a/tests/qtest/test-query-netdev.c b/tests/qtest/test-query-netdev.c
34
+ uint16_t soffset,
27
deleted file mode 100644
35
+ uint16_t len)
28
index XXXXXXX..XXXXXXX
36
+
29
--- a/tests/qtest/test-query-netdev.c
37
{
30
+++ /dev/null
38
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
31
@@ -XXX,XX +XXX,XX @@
39
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
32
-/*
40
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt,
33
- * QTest testcase for the query-netdev
41
sec_ip_src, sec_ip_dst);
34
- *
42
}
35
- * Copyright Yandex N.V., 2019
43
36
- *
44
- poffset = ppkt->vnet_hdr_len + poffset;
37
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
45
- soffset = ppkt->vnet_hdr_len + soffset;
38
- * See the COPYING file in the top-level directory.
39
- *
40
- */
46
-
41
-
47
- if (ppkt->size - poffset == spkt->size - soffset) {
42
-#include "qemu/osdep.h"
48
- return memcmp(ppkt->data + poffset,
43
-
49
- spkt->data + soffset,
44
-#include "libqos/libqtest.h"
50
- spkt->size - soffset);
45
-#include "qapi/qmp/qdict.h"
46
-#include "qapi/qmp/qlist.h"
47
-
48
-/*
49
- * Events can get in the way of responses we are actually waiting for.
50
- */
51
-GCC_FMT_ATTR(2, 3)
52
-static QObject *wait_command(QTestState *who, const char *command, ...)
53
-{
54
- va_list ap;
55
- QDict *response;
56
- QObject *result;
57
-
58
- va_start(ap, command);
59
- qtest_qmp_vsend(who, command, ap);
60
- va_end(ap);
61
-
62
- response = qtest_qmp_receive(who);
63
-
64
- result = qdict_get(response, "return");
65
- g_assert(result);
66
- qobject_ref(result);
67
- qobject_unref(response);
68
-
69
- return result;
70
-}
71
-
72
-static void qmp_query_netdev_no_error(QTestState *qts, size_t netdevs_count)
73
-{
74
- QObject *resp;
75
- QList *netdevs;
76
-
77
- resp = wait_command(qts, "{'execute': 'query-netdev'}");
78
-
79
- netdevs = qobject_to(QList, resp);
80
- g_assert(netdevs);
81
- g_assert(qlist_size(netdevs) == netdevs_count);
82
-
83
- qobject_unref(resp);
84
-}
85
-
86
-static void test_query_netdev(void)
87
-{
88
- const char *arch = qtest_get_arch();
89
- QObject *resp;
90
- QTestState *state;
91
-
92
- /* Choosing machine for platforms without default one */
93
- if (g_str_equal(arch, "arm") ||
94
- g_str_equal(arch, "aarch64")) {
95
- state = qtest_init(
96
- "-nodefaults "
97
- "-M virt "
98
- "-netdev user,id=slirp0");
99
- } else if (g_str_equal(arch, "tricore")) {
100
- state = qtest_init(
101
- "-nodefaults "
102
- "-M tricore_testboard "
103
- "-netdev user,id=slirp0");
104
- } else if (g_str_equal(arch, "avr")) {
105
- state = qtest_init(
106
- "-nodefaults "
107
- "-M mega2560 "
108
- "-netdev user,id=slirp0");
109
- } else if (g_str_equal(arch, "rx")) {
110
- state = qtest_init(
111
- "-nodefaults "
112
- "-M gdbsim-r5f562n8 "
113
- "-netdev user,id=slirp0");
51
- } else {
114
- } else {
52
- trace_colo_compare_main("Net packet size are not the same");
115
- state = qtest_init(
53
- return -1;
116
- "-nodefaults "
117
- "-netdev user,id=slirp0");
54
- }
118
- }
55
+ return memcmp(ppkt->data + poffset, spkt->data + soffset, len);
119
- g_assert(state);
56
}
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
60
* the secondary guest's timestamp. COLO just focus on payload,
61
* so we just need skip this field.
62
*/
63
- if (ptcp->th_off > 5) {
64
- ptrdiff_t ptcp_offset, stcp_offset;
65
66
- ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
67
- + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
68
- stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
69
- + (stcp->th_off * 4) - spkt->vnet_hdr_len;
70
+ ptrdiff_t ptcp_offset, stcp_offset;
71
72
- /*
73
- * When network is busy, some tcp options(like sack) will unpredictable
74
- * occur in primary side or secondary side. it will make packet size
75
- * not same, but the two packet's payload is identical. colo just
76
- * care about packet payload, so we skip the option field.
77
- */
78
- res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset);
79
- } else if (ptcp->th_sum == stcp->th_sum) {
80
- res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN);
81
+ ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
82
+ + (ptcp->th_off << 2) - ppkt->vnet_hdr_len;
83
+ stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
84
+ + (stcp->th_off << 2) - spkt->vnet_hdr_len;
85
+ if (ppkt->size - ptcp_offset == spkt->size - stcp_offset) {
86
+ res = colo_compare_packet_payload(ppkt, spkt,
87
+ ptcp_offset, stcp_offset,
88
+ ppkt->size - ptcp_offset);
89
} else {
90
+ trace_colo_compare_main("TCP: payload size of packets are different");
91
res = -1;
92
}
93
94
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
95
*/
96
static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
97
{
98
- int ret;
99
- int network_header_length = ppkt->ip->ip_hl * 4;
100
+ uint16_t network_header_length = ppkt->ip->ip_hl << 2;
101
+ uint16_t offset = network_header_length + ETH_HLEN + ppkt->vnet_hdr_len;
102
103
trace_colo_compare_main("compare udp");
104
105
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
106
* other field like TOS,TTL,IP Checksum. we only need to compare
107
* the ip payload here.
108
*/
109
- ret = colo_packet_compare_common(ppkt, spkt,
110
- network_header_length + ETH_HLEN,
111
- network_header_length + ETH_HLEN);
112
-
120
-
113
- if (ret) {
121
- qmp_query_netdev_no_error(state, 1);
114
+ if (ppkt->size != spkt->size) {
122
-
115
+ trace_colo_compare_main("UDP: payload size of packets are different");
123
- resp = wait_command(state,
116
+ return -1;
124
- "{'execute': 'netdev_add', 'arguments': {"
117
+ }
125
- " 'id': 'slirp1',"
118
+ if (colo_compare_packet_payload(ppkt, spkt, offset, offset,
126
- " 'type': 'user'}}");
119
+ ppkt->size - offset)) {
127
- qobject_unref(resp);
120
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
128
-
121
trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
129
- qmp_query_netdev_no_error(state, 2);
122
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
130
-
123
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
131
- resp = wait_command(state,
124
qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
132
- "{'execute': 'netdev_del', 'arguments': {"
125
spkt->size);
133
- " 'id': 'slirp1'}}");
126
}
134
- qobject_unref(resp);
127
+ return -1;
135
-
128
+ } else {
136
- qmp_query_netdev_no_error(state, 1);
129
+ return 0;
137
-
130
}
138
- qtest_quit(state);
139
-}
140
-
141
-int main(int argc, char **argv)
142
-{
143
- int ret = 0;
144
- g_test_init(&argc, &argv, NULL);
145
-
146
- qtest_add_func("/net/qapi/query_netdev", test_query_netdev);
147
-
148
- ret = g_test_run();
131
-
149
-
132
- return ret;
150
- return ret;
133
}
151
-}
134
135
/*
136
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
137
*/
138
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
139
{
140
- int network_header_length = ppkt->ip->ip_hl * 4;
141
+ uint16_t network_header_length = ppkt->ip->ip_hl << 2;
142
+ uint16_t offset = network_header_length + ETH_HLEN + ppkt->vnet_hdr_len;
143
144
trace_colo_compare_main("compare icmp");
145
146
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
147
* other field like TOS,TTL,IP Checksum. we only need to compare
148
* the ip payload here.
149
*/
150
- if (colo_packet_compare_common(ppkt, spkt,
151
- network_header_length + ETH_HLEN,
152
- network_header_length + ETH_HLEN)) {
153
+ if (ppkt->size != spkt->size) {
154
+ trace_colo_compare_main("ICMP: payload size of packets are different");
155
+ return -1;
156
+ }
157
+ if (colo_compare_packet_payload(ppkt, spkt, offset, offset,
158
+ ppkt->size - offset)) {
159
trace_colo_compare_icmp_miscompare("primary pkt size",
160
ppkt->size);
161
trace_colo_compare_icmp_miscompare("Secondary pkt size",
162
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
163
*/
164
static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
165
{
166
+ uint16_t offset = ppkt->vnet_hdr_len;
167
+
168
trace_colo_compare_main("compare other");
169
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
170
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
171
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
172
sec_ip_src, sec_ip_dst);
173
}
174
175
- return colo_packet_compare_common(ppkt, spkt, 0, 0);
176
+ if (ppkt->size != spkt->size) {
177
+ trace_colo_compare_main("Other: payload size of packets are different");
178
+ return -1;
179
+ }
180
+ return colo_compare_packet_payload(ppkt, spkt, offset, offset,
181
+ ppkt->size - offset);
182
}
183
184
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
185
--
152
--
186
2.7.4
153
2.7.4
187
154
188
155
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
Several issues has been reported for query-netdev series. Consider
2
it's late in the rc, this reverts commit
3
d32ad10a14d46dfe9304e3ed5858a11dcd5c71a0.
2
4
3
QEMU can emulate hubs to connect NICs and netdevs. This is currently
4
primarily used for the mis-named 'vlan' feature of the networking
5
subsystem. Now the 'vlan' feature has been marked as deprecated, since
6
its name is rather confusing and the users often rather mis-configure
7
their network when trying to use it. But while the 'vlan' parameter
8
should be removed at one point in time, the basic idea of emulating
9
a hub in QEMU is still good: It's useful for bundling up the output of
10
multiple NICs into one single l2tp netdev for example.
11
12
Now to be able to use the hubport feature without 'vlan's, there is one
13
missing piece: The possibility to connect a hubport to a netdev, too.
14
This patch adds this possibility by introducing a new "netdev=..."
15
parameter to the hubports.
16
17
To bundle up the output of multiple NICs into one socket netdev, you can
18
now run QEMU with these parameters for example:
19
20
qemu-system-ppc64 ... -netdev socket,id=s1,connect=:11122 \
21
-netdev hubport,hubid=1,id=h1,netdev=s1 \
22
-netdev hubport,hubid=1,id=h2 -device e1000,netdev=h2 \
23
-netdev hubport,hubid=1,id=h3 -device virtio-net-pci,netdev=h3
24
25
For using the socket netdev, you have got to start another QEMU as the
26
receiving side first, for example with network dumping enabled:
27
28
qemu-system-x86_64 -M isapc -netdev socket,id=s0,listen=:11122 \
29
-device ne2k_isa,netdev=s0 \
30
-object filter-dump,id=f1,netdev=s0,file=/tmp/dump.dat
31
32
After the ppc64 guest tried to boot from both NICs, you can see in the
33
dump file (using Wireshark, for example), that the output of both NICs
34
(the e1000 and the virtio-net-pci) has been successfully transfered
35
via the socket netdev in this case.
36
37
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
38
Signed-off-by: Thomas Huth <thuth@redhat.com>
39
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
40
---
6
---
41
net/hub.c | 27 +++++++++++++++++++++------
7
include/net/net.h | 3 --
42
net/hub.h | 3 ++-
8
net/l2tpv3.c | 7 ----
43
net/net.c | 2 +-
9
net/net.c | 30 +-------------
44
qapi/net.json | 4 +++-
10
net/netmap.c | 7 ----
45
qemu-options.hx | 8 +++++---
11
net/slirp.c | 122 ------------------------------------------------------
46
5 files changed, 32 insertions(+), 12 deletions(-)
12
net/socket.c | 71 -------------------------------
13
net/tap-win32.c | 9 ----
14
net/tap.c | 103 +++------------------------------------------
15
net/vde.c | 22 ----------
16
net/vhost-user.c | 18 ++------
17
net/vhost-vdpa.c | 14 -------
18
qapi/net.json | 80 -----------------------------------
19
12 files changed, 9 insertions(+), 477 deletions(-)
47
20
48
diff --git a/net/hub.c b/net/hub.c
21
diff --git a/include/net/net.h b/include/net/net.h
49
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
50
--- a/net/hub.c
23
--- a/include/net/net.h
51
+++ b/net/hub.c
24
+++ b/include/net/net.h
52
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
53
*/
26
#include "qapi/qapi-types-net.h"
54
27
#include "net/queue.h"
55
#include "qemu/osdep.h"
28
#include "hw/qdev-properties-system.h"
56
+#include "qapi/error.h"
29
-#include "qapi/clone-visitor.h"
30
-#include "qapi/qapi-visit-net.h"
31
32
#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
33
#define MAC_ARG(x) ((uint8_t *)(x))[0], ((uint8_t *)(x))[1], \
34
@@ -XXX,XX +XXX,XX @@ struct NetClientState {
35
char *model;
36
char *name;
37
char info_str[256];
38
- NetdevInfo *stored_config;
39
unsigned receive_disabled : 1;
40
NetClientDestructor *destructor;
41
unsigned int queue_index;
42
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/net/l2tpv3.c
45
+++ b/net/l2tpv3.c
46
@@ -XXX,XX +XXX,XX @@ int net_init_l2tpv3(const Netdev *netdev,
47
48
l2tpv3_read_poll(s, true);
49
50
- /* Store startup parameters */
51
- nc->stored_config = g_new0(NetdevInfo, 1);
52
- nc->stored_config->type = NET_BACKEND_L2TPV3;
53
-
54
- QAPI_CLONE_MEMBERS(NetdevL2TPv3Options,
55
- &nc->stored_config->u.l2tpv3, l2tpv3);
56
-
57
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
58
"l2tpv3: connected");
59
return 0;
60
diff --git a/net/net.c b/net/net.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/net/net.c
63
+++ b/net/net.c
64
@@ -XXX,XX +XXX,XX @@
57
#include "monitor/monitor.h"
65
#include "monitor/monitor.h"
58
#include "net/net.h"
66
#include "qemu/help_option.h"
59
#include "clients.h"
67
#include "qapi/qapi-commands-net.h"
60
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_hub_port_info = {
68
+#include "qapi/qapi-visit-net.h"
61
.cleanup = net_hub_port_cleanup,
69
#include "qapi/qmp/qdict.h"
62
};
70
#include "qapi/qmp/qerror.h"
63
71
#include "qemu/error-report.h"
64
-static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
72
@@ -XXX,XX +XXX,XX @@ static void qemu_free_net_client(NetClientState *nc)
65
+static NetHubPort *net_hub_port_new(NetHub *hub, const char *name,
73
}
66
+ NetClientState *hubpeer)
74
g_free(nc->name);
75
g_free(nc->model);
76
- qapi_free_NetdevInfo(nc->stored_config);
77
if (nc->destructor) {
78
nc->destructor(nc);
79
}
80
@@ -XXX,XX +XXX,XX @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
81
return filter_list;
82
}
83
84
-NetdevInfoList *qmp_query_netdev(Error **errp)
85
-{
86
- NetdevInfoList *list = NULL;
87
- NetClientState *nc;
88
-
89
- QTAILQ_FOREACH(nc, &net_clients, next) {
90
- /*
91
- * Only look at netdevs (backend network devices), not for each queue
92
- * or NIC / hubport
93
- */
94
- if (nc->stored_config) {
95
- NetdevInfo *element = QAPI_CLONE(NetdevInfo, nc->stored_config);
96
-
97
- g_free(element->id); /* Need to dealloc empty id after clone */
98
- element->id = g_strdup(nc->name);
99
-
100
- element->has_peer_id = nc->peer != NULL;
101
- if (element->has_peer_id) {
102
- element->peer_id = g_strdup(nc->peer->name);
103
- }
104
-
105
- QAPI_LIST_PREPEND(list, element);
106
- }
107
- }
108
-
109
- return list;
110
-}
111
-
112
void hmp_info_network(Monitor *mon, const QDict *qdict)
113
{
114
NetClientState *nc, *peer;
115
diff --git a/net/netmap.c b/net/netmap.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/net/netmap.c
118
+++ b/net/netmap.c
119
@@ -XXX,XX +XXX,XX @@ int net_init_netmap(const Netdev *netdev,
120
pstrcpy(s->ifname, sizeof(s->ifname), netmap_opts->ifname);
121
netmap_read_poll(s, true); /* Initially only poll for reads. */
122
123
- /* Store startup parameters */
124
- nc->stored_config = g_new0(NetdevInfo, 1);
125
- nc->stored_config->type = NET_BACKEND_NETMAP;
126
-
127
- QAPI_CLONE_MEMBERS(NetdevNetmapOptions,
128
- &nc->stored_config->u.netmap, netmap_opts);
129
-
130
return 0;
131
}
132
133
diff --git a/net/slirp.c b/net/slirp.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/net/slirp.c
136
+++ b/net/slirp.c
137
@@ -XXX,XX +XXX,XX @@ static int net_slirp_init(NetClientState *peer, const char *model,
138
int shift;
139
char *end;
140
struct slirp_config_str *config;
141
- NetdevUserOptions *stored;
142
- StringList **stored_hostfwd;
143
- StringList **stored_guestfwd;
144
145
if (!ipv4 && (vnetwork || vhost || vnameserver)) {
146
error_setg(errp, "IPv4 disabled but netmask/host/dns provided");
147
@@ -XXX,XX +XXX,XX @@ static int net_slirp_init(NetClientState *peer, const char *model,
148
149
nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
150
151
- /* Store startup parameters */
152
- nc->stored_config = g_new0(NetdevInfo, 1);
153
- nc->stored_config->type = NET_BACKEND_USER;
154
- stored = &nc->stored_config->u.user;
155
-
156
- if (vhostname) {
157
- stored->has_hostname = true;
158
- stored->hostname = g_strdup(vhostname);
159
- }
160
-
161
- stored->has_q_restrict = true;
162
- stored->q_restrict = restricted;
163
-
164
- stored->has_ipv4 = true;
165
- stored->ipv4 = ipv4;
166
-
167
- stored->has_ipv6 = true;
168
- stored->ipv6 = ipv6;
169
-
170
- if (ipv4) {
171
- uint8_t *net_bytes = (uint8_t *)&net;
172
- uint8_t *mask_bytes = (uint8_t *)&mask;
173
-
174
- stored->has_net = true;
175
- stored->net = g_strdup_printf("%d.%d.%d.%d/%d.%d.%d.%d",
176
- net_bytes[0], net_bytes[1],
177
- net_bytes[2], net_bytes[3],
178
- mask_bytes[0], mask_bytes[1],
179
- mask_bytes[2], mask_bytes[3]);
180
-
181
- stored->has_host = true;
182
- stored->host = g_strdup(inet_ntoa(host));
183
- }
184
-
185
- if (tftp_export) {
186
- stored->has_tftp = true;
187
- stored->tftp = g_strdup(tftp_export);
188
- }
189
-
190
- if (bootfile) {
191
- stored->has_bootfile = true;
192
- stored->bootfile = g_strdup(bootfile);
193
- }
194
-
195
- if (vdhcp_start) {
196
- stored->has_dhcpstart = true;
197
- stored->dhcpstart = g_strdup(vdhcp_start);
198
- }
199
-
200
- if (ipv4) {
201
- stored->has_dns = true;
202
- stored->dns = g_strdup(inet_ntoa(dns));
203
- }
204
-
205
- if (dnssearch) {
206
- stored->has_dnssearch = true;
207
- StringList **stored_list = &stored->dnssearch;
208
-
209
- for (int i = 0; dnssearch[i]; i++) {
210
- String *element = g_new0(String, 1);
211
-
212
- element->str = g_strdup(dnssearch[i]);
213
- QAPI_LIST_APPEND(stored_list, element);
214
- }
215
- }
216
-
217
- if (vdomainname) {
218
- stored->has_domainname = true;
219
- stored->domainname = g_strdup(vdomainname);
220
- }
221
-
222
- if (ipv6) {
223
- char addrstr[INET6_ADDRSTRLEN];
224
- const char *res;
225
-
226
- stored->has_ipv6_prefix = true;
227
- stored->ipv6_prefix = g_strdup(vprefix6);
228
-
229
- stored->has_ipv6_prefixlen = true;
230
- stored->ipv6_prefixlen = vprefix6_len;
231
-
232
- res = inet_ntop(AF_INET6, &ip6_host,
233
- addrstr, sizeof(addrstr));
234
-
235
- stored->has_ipv6_host = true;
236
- stored->ipv6_host = g_strdup(res);
237
-
238
- res = inet_ntop(AF_INET6, &ip6_dns,
239
- addrstr, sizeof(addrstr));
240
-
241
- stored->has_ipv6_dns = true;
242
- stored->ipv6_dns = g_strdup(res);
243
- }
244
-
245
- if (smb_export) {
246
- stored->has_smb = true;
247
- stored->smb = g_strdup(smb_export);
248
- }
249
-
250
- if (vsmbserver) {
251
- stored->has_smbserver = true;
252
- stored->smbserver = g_strdup(vsmbserver);
253
- }
254
-
255
- if (tftp_server_name) {
256
- stored->has_tftp_server_name = true;
257
- stored->tftp_server_name = g_strdup(tftp_server_name);
258
- }
259
-
260
snprintf(nc->info_str, sizeof(nc->info_str),
261
"net=%s,restrict=%s", inet_ntoa(net),
262
restricted ? "on" : "off");
263
@@ -XXX,XX +XXX,XX @@ static int net_slirp_init(NetClientState *peer, const char *model,
264
s->poll_notifier.notify = net_slirp_poll_notify;
265
main_loop_poll_add_notifier(&s->poll_notifier);
266
267
- stored_hostfwd = &stored->hostfwd;
268
- stored_guestfwd = &stored->guestfwd;
269
-
270
for (config = slirp_configs; config; config = config->next) {
271
- String *element = g_new0(String, 1);
272
-
273
- element->str = g_strdup(config->str);
274
if (config->flags & SLIRP_CFG_HOSTFWD) {
275
if (slirp_hostfwd(s, config->str, errp) < 0) {
276
goto error;
277
}
278
- stored->has_hostfwd = true;
279
- QAPI_LIST_APPEND(stored_hostfwd, element);
280
} else {
281
if (slirp_guestfwd(s, config->str, errp) < 0) {
282
goto error;
283
}
284
- stored->has_guestfwd = true;
285
- QAPI_LIST_APPEND(stored_guestfwd, element);
286
}
287
}
288
#ifndef _WIN32
289
diff --git a/net/socket.c b/net/socket.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/net/socket.c
292
+++ b/net/socket.c
293
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
294
NetSocketState *s;
295
SocketAddress *sa;
296
SocketAddressType sa_type;
297
- NetdevSocketOptions *stored;
298
299
sa = socket_local_address(fd, errp);
300
if (!sa) {
301
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
302
net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
303
net_socket_read_poll(s, true);
304
305
- /* Store startup parameters */
306
- nc->stored_config = g_new0(NetdevInfo, 1);
307
- nc->stored_config->type = NET_BACKEND_SOCKET;
308
- stored = &nc->stored_config->u.socket;
309
-
310
- stored->has_fd = true;
311
- stored->fd = g_strdup_printf("%d", fd);
312
-
313
/* mcast: save bound address as dst */
314
if (is_connected && mcast != NULL) {
315
- stored->has_mcast = true;
316
- stored->mcast = g_strdup(mcast);
317
-
318
s->dgram_dst = saddr;
319
snprintf(nc->info_str, sizeof(nc->info_str),
320
"socket: fd=%d (cloned mcast=%s:%d)",
321
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
67
{
322
{
68
NetClientState *nc;
323
NetClientState *nc;
69
NetHubPort *port;
324
NetSocketState *s;
70
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
325
- NetdevSocketOptions *stored;
71
name = default_name;
326
327
nc = qemu_new_net_client(&net_socket_info, peer, model, name);
328
329
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
330
} else {
331
qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
72
}
332
}
73
333
-
74
- nc = qemu_new_net_client(&net_hub_port_info, NULL, "hub", name);
334
- /* Store startup parameters */
75
+ nc = qemu_new_net_client(&net_hub_port_info, hubpeer, "hub", name);
335
- nc->stored_config = g_new0(NetdevInfo, 1);
76
port = DO_UPCAST(NetHubPort, nc, nc);
336
- nc->stored_config->type = NET_BACKEND_SOCKET;
77
port->id = id;
337
- stored = &nc->stored_config->u.socket;
78
port->hub = hub;
338
-
79
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
339
- stored->has_fd = true;
80
340
- stored->fd = g_strdup_printf("%d", fd);
81
/**
341
-
82
* Create a port on a given hub
342
return s;
83
+ * @hub_id: Number of the hub
84
* @name: Net client name or NULL for default name.
85
+ * @hubpeer: Peer to use (if "netdev=id" has been specified)
86
*
87
* If there is no existing hub with the given id then a new hub is created.
88
*/
89
-NetClientState *net_hub_add_port(int hub_id, const char *name)
90
+NetClientState *net_hub_add_port(int hub_id, const char *name,
91
+ NetClientState *hubpeer)
92
{
93
NetHub *hub;
94
NetHubPort *port;
95
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_add_port(int hub_id, const char *name)
96
hub = net_hub_new(hub_id);
97
}
98
99
- port = net_hub_port_new(hub, name);
100
+ port = net_hub_port_new(hub, name, hubpeer);
101
return &port->nc;
102
}
343
}
103
344
104
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_port_find(int hub_id)
345
@@ -XXX,XX +XXX,XX @@ static void net_socket_accept(void *opaque)
105
}
346
struct sockaddr_in saddr;
106
}
347
socklen_t len;
107
348
int fd;
108
- nc = net_hub_add_port(hub_id, NULL);
349
- NetdevSocketOptions *stored;
109
+ nc = net_hub_add_port(hub_id, NULL, NULL);
350
110
return nc;
351
for(;;) {
111
}
352
len = sizeof(saddr);
112
353
@@ -XXX,XX +XXX,XX @@ static void net_socket_accept(void *opaque)
113
@@ -XXX,XX +XXX,XX @@ int net_init_hubport(const Netdev *netdev, const char *name,
354
s->fd = fd;
114
NetClientState *peer, Error **errp)
355
s->nc.link_down = false;
115
{
356
net_socket_connect(s);
116
const NetdevHubPortOptions *hubport;
357
-
117
+ NetClientState *hubpeer = NULL;
358
- /* Store additional startup parameters (extend net_socket_listen_init) */
118
359
- stored = &s->nc.stored_config->u.socket;
119
assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
360
-
120
assert(!peer);
361
- stored->has_fd = true;
121
hubport = &netdev->u.hubport;
362
- stored->fd = g_strdup_printf("%d", fd);
122
363
-
123
- net_hub_add_port(hubport->hubid, name);
364
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
124
+ if (hubport->has_netdev) {
365
"socket: connection from %s:%d",
125
+ hubpeer = qemu_find_netdev(hubport->netdev);
366
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
126
+ if (!hubpeer) {
367
@@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer,
127
+ error_setg(errp, "netdev '%s' not found", hubport->netdev);
368
NetSocketState *s;
128
+ return -1;
369
struct sockaddr_in saddr;
129
+ }
370
int fd, ret;
130
+ }
371
- NetdevSocketOptions *stored;
131
+
372
132
+ net_hub_add_port(hubport->hubid, name, hubpeer);
373
if (parse_host_port(&saddr, host_str, errp) < 0) {
133
+
374
return -1;
375
@@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer,
376
net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
377
378
qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
379
-
380
- /* Store startup parameters */
381
- nc->stored_config = g_new0(NetdevInfo, 1);
382
- nc->stored_config->type = NET_BACKEND_SOCKET;
383
- stored = &nc->stored_config->u.socket;
384
-
385
- stored->has_listen = true;
386
- stored->listen = g_strdup(host_str);
387
-
134
return 0;
388
return 0;
135
}
389
}
136
390
137
diff --git a/net/hub.h b/net/hub.h
391
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
138
index XXXXXXX..XXXXXXX 100644
392
NetSocketState *s;
139
--- a/net/hub.h
393
int fd, connected, ret;
140
+++ b/net/hub.h
394
struct sockaddr_in saddr;
141
@@ -XXX,XX +XXX,XX @@
395
- NetdevSocketOptions *stored;
142
396
143
#include "qemu-common.h"
397
if (parse_host_port(&saddr, host_str, errp) < 0) {
144
398
return -1;
145
-NetClientState *net_hub_add_port(int hub_id, const char *name);
399
@@ -XXX,XX +XXX,XX @@ static int net_socket_connect_init(NetClientState *peer,
146
+NetClientState *net_hub_add_port(int hub_id, const char *name,
400
return -1;
147
+ NetClientState *hubpeer);
401
}
148
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
402
149
void net_hub_info(Monitor *mon);
403
- /* Store additional startup parameters (extend net_socket_fd_init) */
150
void net_hub_check_clients(void);
404
- stored = &s->nc.stored_config->u.socket;
151
diff --git a/net/net.c b/net/net.c
405
-
152
index XXXXXXX..XXXXXXX 100644
406
- stored->has_connect = true;
153
--- a/net/net.c
407
- stored->connect = g_strdup(host_str);
154
+++ b/net/net.c
408
-
155
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
409
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
156
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
410
"socket: connect to %s:%d",
157
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
411
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
158
!opts->u.nic.has_netdev) {
412
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
159
- peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
413
int fd;
160
+ peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL, NULL);
414
struct sockaddr_in saddr;
415
struct in_addr localaddr, *param_localaddr;
416
- NetdevSocketOptions *stored;
417
418
if (parse_host_port(&saddr, host_str, errp) < 0) {
419
return -1;
420
@@ -XXX,XX +XXX,XX @@ static int net_socket_mcast_init(NetClientState *peer,
421
422
s->dgram_dst = saddr;
423
424
- /* Store additional startup parameters (extend net_socket_fd_init) */
425
- stored = &s->nc.stored_config->u.socket;
426
-
427
- if (!stored->has_mcast) {
428
- stored->has_mcast = true;
429
- stored->mcast = g_strdup(host_str);
430
- }
431
-
432
- if (localaddr_str) {
433
- stored->has_localaddr = true;
434
- stored->localaddr = g_strdup(localaddr_str);
435
- }
436
-
437
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
438
"socket: mcast=%s:%d",
439
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
440
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
441
NetSocketState *s;
442
int fd, ret;
443
struct sockaddr_in laddr, raddr;
444
- NetdevSocketOptions *stored;
445
446
if (parse_host_port(&laddr, lhost, errp) < 0) {
447
return -1;
448
@@ -XXX,XX +XXX,XX @@ static int net_socket_udp_init(NetClientState *peer,
449
450
s->dgram_dst = raddr;
451
452
- /* Store additional startup parameters (extend net_socket_fd_init) */
453
- stored = &s->nc.stored_config->u.socket;
454
-
455
- stored->has_localaddr = true;
456
- stored->localaddr = g_strdup(lhost);
457
-
458
- stored->has_udp = true;
459
- stored->udp = g_strdup(rhost);
460
-
461
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
462
"socket: udp=%s:%d",
463
inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
464
diff --git a/net/tap-win32.c b/net/tap-win32.c
465
index XXXXXXX..XXXXXXX 100644
466
--- a/net/tap-win32.c
467
+++ b/net/tap-win32.c
468
@@ -XXX,XX +XXX,XX @@ static int tap_win32_init(NetClientState *peer, const char *model,
469
NetClientState *nc;
470
TAPState *s;
471
tap_win32_overlapped_t *handle;
472
- NetdevTapOptions *stored;
473
474
if (tap_win32_open(&handle, ifname) < 0) {
475
printf("tap: Could not open '%s'\n", ifname);
476
@@ -XXX,XX +XXX,XX @@ static int tap_win32_init(NetClientState *peer, const char *model,
477
478
s = DO_UPCAST(TAPState, nc, nc);
479
480
- /* Store startup parameters */
481
- nc->stored_config = g_new0(NetdevInfo, 1);
482
- nc->stored_config->type = NET_BACKEND_TAP;
483
- stored = &nc->stored_config->u.tap;
484
-
485
- stored->has_ifname = true;
486
- stored->ifname = g_strdup(ifname);
487
-
488
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
489
"tap: ifname=%s", ifname);
490
491
diff --git a/net/tap.c b/net/tap.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/net/tap.c
494
+++ b/net/tap.c
495
@@ -XXX,XX +XXX,XX @@ int net_init_bridge(const Netdev *netdev, const char *name,
496
const char *helper, *br;
497
TAPState *s;
498
int fd, vnet_hdr;
499
- NetdevBridgeOptions *stored;
500
501
assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE);
502
bridge = &netdev->u.bridge;
503
@@ -XXX,XX +XXX,XX @@ int net_init_bridge(const Netdev *netdev, const char *name,
504
}
505
s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);
506
507
- /* Store startup parameters */
508
- s->nc.stored_config = g_new0(NetdevInfo, 1);
509
- s->nc.stored_config->type = NET_BACKEND_BRIDGE;
510
- stored = &s->nc.stored_config->u.bridge;
511
-
512
- if (br) {
513
- stored->has_br = true;
514
- stored->br = g_strdup(br);
515
- }
516
-
517
- if (helper) {
518
- stored->has_helper = true;
519
- stored->helper = g_strdup(helper);
520
- }
521
-
522
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper,
523
br);
524
525
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
526
const char *model, const char *name,
527
const char *ifname, const char *script,
528
const char *downscript, const char *vhostfdname,
529
- int vnet_hdr, int fd, NetdevInfo **common_stored,
530
- Error **errp)
531
+ int vnet_hdr, int fd, Error **errp)
532
{
533
Error *err = NULL;
534
TAPState *s = net_tap_fd_init(peer, model, name, fd, vnet_hdr);
535
int vhostfd;
536
- NetdevTapOptions *stored;
537
538
tap_set_sndbuf(s->fd, tap, &err);
539
if (err) {
540
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
541
return;
542
}
543
544
- /* Store startup parameters */
545
- if (!*common_stored) {
546
- *common_stored = g_new0(NetdevInfo, 1);
547
- (*common_stored)->type = NET_BACKEND_TAP;
548
- s->nc.stored_config = *common_stored;
549
- }
550
- stored = &(*common_stored)->u.tap;
551
-
552
- if (tap->has_sndbuf && !stored->has_sndbuf) {
553
- stored->has_sndbuf = true;
554
- stored->sndbuf = tap->sndbuf;
555
- }
556
-
557
- if (vnet_hdr && !stored->has_vnet_hdr) {
558
- stored->has_vnet_hdr = true;
559
- stored->vnet_hdr = true;
560
- }
561
-
562
if (tap->has_fd || tap->has_fds) {
563
- if (!stored->has_fds) {
564
- stored->has_fds = true;
565
- stored->fds = g_strdup_printf("%d", fd);
566
- } else {
567
- char *tmp_s = stored->fds;
568
- stored->fds = g_strdup_printf("%s:%d", stored->fds, fd);
569
- g_free(tmp_s);
570
- }
571
-
572
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd);
573
} else if (tap->has_helper) {
574
- if (!stored->has_helper) {
575
- stored->has_helper = true;
576
- stored->helper = g_strdup(tap->helper);
577
- }
578
-
579
- if (!stored->has_br) {
580
- stored->has_br = true;
581
- stored->br = tap->has_br ? g_strdup(tap->br) :
582
- g_strdup(DEFAULT_BRIDGE_INTERFACE);
583
- }
584
-
585
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s",
586
tap->helper);
587
} else {
588
- if (ifname && !stored->has_ifname) {
589
- stored->has_ifname = true;
590
- stored->ifname = g_strdup(ifname);
591
- }
592
-
593
- if (script && !stored->has_script) {
594
- stored->has_script = true;
595
- stored->script = g_strdup(script);
596
- }
597
-
598
- if (downscript && !stored->has_downscript) {
599
- stored->has_downscript = true;
600
- stored->downscript = g_strdup(downscript);
601
- }
602
-
603
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
604
"ifname=%s,script=%s,downscript=%s", ifname, script,
605
downscript);
606
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
607
vhostfdname || (tap->has_vhostforce && tap->vhostforce)) {
608
VhostNetOptions options;
609
610
- stored->has_vhost = true;
611
- stored->vhost = true;
612
-
613
- if (tap->has_vhostforce && tap->vhostforce) {
614
- stored->has_vhostforce = true;
615
- stored->vhostforce = true;
616
- }
617
-
618
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
619
options.net_backend = &s->nc;
620
if (tap->has_poll_us) {
621
- stored->has_poll_us = true;
622
- stored->poll_us = tap->poll_us;
623
-
624
options.busyloop_timeout = tap->poll_us;
625
} else {
626
options.busyloop_timeout = 0;
627
@@ -XXX,XX +XXX,XX @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
161
}
628
}
162
629
options.opaque = (void *)(uintptr_t)vhostfd;
163
if (net->has_vlan && !vlan_warned) {
630
631
- if (!stored->has_vhostfds) {
632
- stored->has_vhostfds = true;
633
- stored->vhostfds = g_strdup_printf("%d", vhostfd);
634
- } else {
635
- char *tmp_s = stored->vhostfds;
636
- stored->vhostfds = g_strdup_printf("%s:%d", stored->fds, vhostfd);
637
- g_free(tmp_s);
638
- }
639
-
640
s->vhost_net = vhost_net_init(&options);
641
if (!s->vhost_net) {
642
if (tap->has_vhostforce && tap->vhostforce) {
643
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
644
const char *vhostfdname;
645
char ifname[128];
646
int ret = 0;
647
- NetdevInfo *common_stored = NULL; /* will store configuration */
648
649
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
650
tap = &netdev->u.tap;
651
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
652
653
net_init_tap_one(tap, peer, "tap", name, NULL,
654
script, downscript,
655
- vhostfdname, vnet_hdr, fd, &common_stored, &err);
656
+ vhostfdname, vnet_hdr, fd, &err);
657
if (err) {
658
error_propagate(errp, err);
659
close(fd);
660
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
661
net_init_tap_one(tap, peer, "tap", name, ifname,
662
script, downscript,
663
tap->has_vhostfds ? vhost_fds[i] : NULL,
664
- vnet_hdr, fd, &common_stored, &err);
665
+ vnet_hdr, fd, &err);
666
if (err) {
667
error_propagate(errp, err);
668
ret = -1;
669
@@ -XXX,XX +XXX,XX @@ free_fail:
670
671
net_init_tap_one(tap, peer, "bridge", name, ifname,
672
script, downscript, vhostfdname,
673
- vnet_hdr, fd, &common_stored, &err);
674
+ vnet_hdr, fd, &err);
675
if (err) {
676
error_propagate(errp, err);
677
close(fd);
678
@@ -XXX,XX +XXX,XX @@ free_fail:
679
net_init_tap_one(tap, peer, "tap", name, ifname,
680
i >= 1 ? "no" : script,
681
i >= 1 ? "no" : downscript,
682
- vhostfdname, vnet_hdr, fd,
683
- &common_stored, &err);
684
+ vhostfdname, vnet_hdr, fd, &err);
685
if (err) {
686
error_propagate(errp, err);
687
close(fd);
688
diff --git a/net/vde.c b/net/vde.c
689
index XXXXXXX..XXXXXXX 100644
690
--- a/net/vde.c
691
+++ b/net/vde.c
692
@@ -XXX,XX +XXX,XX @@ static int net_vde_init(NetClientState *peer, const char *model,
693
VDECONN *vde;
694
char *init_group = (char *)group;
695
char *init_sock = (char *)sock;
696
- NetdevVdeOptions *stored;
697
698
struct vde_open_args args = {
699
.port = port,
700
@@ -XXX,XX +XXX,XX @@ static int net_vde_init(NetClientState *peer, const char *model,
701
702
qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);
703
704
- /* Store startup parameters */
705
- nc->stored_config = g_new0(NetdevInfo, 1);
706
- nc->stored_config->type = NET_BACKEND_VDE;
707
- stored = &nc->stored_config->u.vde;
708
-
709
- if (sock) {
710
- stored->has_sock = true;
711
- stored->sock = g_strdup(sock);
712
- }
713
-
714
- stored->has_port = true;
715
- stored->port = port;
716
-
717
- if (group) {
718
- stored->has_group = true;
719
- stored->group = g_strdup(group);
720
- }
721
-
722
- stored->has_mode = true;
723
- stored->mode = mode;
724
-
725
return 0;
726
}
727
728
diff --git a/net/vhost-user.c b/net/vhost-user.c
729
index XXXXXXX..XXXXXXX 100644
730
--- a/net/vhost-user.c
731
+++ b/net/vhost-user.c
732
@@ -XXX,XX +XXX,XX @@ static void net_vhost_user_event(void *opaque, QEMUChrEvent event)
733
}
734
735
static int net_vhost_user_init(NetClientState *peer, const char *device,
736
- const char *name, const char *chardev,
737
- Chardev *chr, int queues)
738
+ const char *name, Chardev *chr,
739
+ int queues)
740
{
741
Error *err = NULL;
742
NetClientState *nc, *nc0 = NULL;
743
NetVhostUserState *s = NULL;
744
VhostUserState *user;
745
int i;
746
- NetdevVhostUserOptions *stored;
747
748
assert(name);
749
assert(queues > 0);
750
@@ -XXX,XX +XXX,XX @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
751
752
assert(s->vhost_net);
753
754
- /* Store startup parameters */
755
- nc0->stored_config = g_new0(NetdevInfo, 1);
756
- nc0->stored_config->type = NET_BACKEND_VHOST_USER;
757
- stored = &nc0->stored_config->u.vhost_user;
758
-
759
- stored->chardev = g_strdup(chardev);
760
-
761
- stored->has_queues = true;
762
- stored->queues = queues;
763
-
764
return 0;
765
766
err:
767
@@ -XXX,XX +XXX,XX @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
768
return -1;
769
}
770
771
- return net_vhost_user_init(peer, "vhost_user", name,
772
- vhost_user_opts->chardev, chr, queues);
773
+ return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
774
}
775
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
776
index XXXXXXX..XXXXXXX 100644
777
--- a/net/vhost-vdpa.c
778
+++ b/net/vhost-vdpa.c
779
@@ -XXX,XX +XXX,XX @@ static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
780
VhostVDPAState *s;
781
int vdpa_device_fd = -1;
782
int ret = 0;
783
- NetdevVhostVDPAOptions *stored;
784
-
785
assert(name);
786
nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
787
-
788
- /* Store startup parameters */
789
- nc->stored_config = g_new0(NetdevInfo, 1);
790
- nc->stored_config->type = NET_BACKEND_VHOST_VDPA;
791
- stored = &nc->stored_config->u.vhost_vdpa;
792
-
793
- stored->has_vhostdev = true;
794
- stored->vhostdev = g_strdup(vhostdev);
795
-
796
- stored->has_queues = true;
797
- stored->queues = 1; /* TODO: change when support multiqueue */
798
-
799
snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
800
nc->queue_index = 0;
801
s = DO_UPCAST(VhostVDPAState, nc, nc);
164
diff --git a/qapi/net.json b/qapi/net.json
802
diff --git a/qapi/net.json b/qapi/net.json
165
index XXXXXXX..XXXXXXX 100644
803
index XXXXXXX..XXXXXXX 100644
166
--- a/qapi/net.json
804
--- a/qapi/net.json
167
+++ b/qapi/net.json
805
+++ b/qapi/net.json
168
@@ -XXX,XX +XXX,XX @@
806
@@ -XXX,XX +XXX,XX @@
169
# Connect two or more net clients through a software hub.
170
#
171
# @hubid: hub identifier number
172
+# @netdev: used to connect hub to a netdev instead of a device (since 2.12)
173
#
174
# Since: 1.2
175
##
807
##
176
{ 'struct': 'NetdevHubPortOptions',
808
{ 'event': 'FAILOVER_NEGOTIATED',
177
'data': {
809
'data': {'device-id': 'str'} }
178
- 'hubid': 'int32' } }
810
-
179
+ 'hubid': 'int32',
811
-##
180
+ '*netdev': 'str' } }
812
-# @NetBackend:
181
813
-#
182
##
814
-# Available netdev backend drivers.
183
# @NetdevNetmapOptions:
815
-#
184
diff --git a/qemu-options.hx b/qemu-options.hx
816
-# Since: 6.0
185
index XXXXXXX..XXXXXXX 100644
817
-##
186
--- a/qemu-options.hx
818
-{ 'enum': 'NetBackend',
187
+++ b/qemu-options.hx
819
- 'data': [ 'bridge', 'l2tpv3', 'netmap', 'socket', 'tap', 'user', 'vde',
188
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
820
- 'vhost-user', 'vhost-vdpa' ] }
189
#endif
821
-
190
"-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n"
822
-##
191
" configure a vhost-user network, backed by a chardev 'dev'\n"
823
-# @NetdevInfo:
192
- "-netdev hubport,id=str,hubid=n\n"
824
-#
193
+ "-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
825
-# Configuration of a network backend device (netdev).
194
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
826
-#
195
DEF("net", HAS_ARG, QEMU_OPTION_net,
827
-# @id: Device identifier.
196
"-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
828
-#
197
@@ -XXX,XX +XXX,XX @@ vde_switch -F -sock /tmp/myswitch
829
-# @type: Specify the driver used for interpreting remaining arguments.
198
qemu-system-i386 linux.img -net nic -net vde,sock=/tmp/myswitch
830
-#
199
@end example
831
-# @peer-id: The connected frontend network device name (absent if no frontend
200
832
-# is connected).
201
-@item -netdev hubport,id=@var{id},hubid=@var{hubid}
833
-#
202
+@item -netdev hubport,id=@var{id},hubid=@var{hubid}[,netdev=@var{nd}]
834
-# Since: 6.0
203
835
-##
204
Create a hub port on QEMU "vlan" @var{hubid}.
836
-{ 'union': 'NetdevInfo',
205
837
- 'base': { 'id': 'str',
206
The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
838
- 'type': 'NetBackend',
207
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
839
- '*peer-id': 'str' },
208
-required hub automatically.
840
- 'discriminator': 'type',
209
+required hub automatically. Alternatively, you can also connect the hubport
841
- 'data': {
210
+to another netdev with ID @var{nd} by using the @option{netdev=@var{nd}}
842
- 'bridge': 'NetdevBridgeOptions',
211
+option.
843
- 'l2tpv3': 'NetdevL2TPv3Options',
212
844
- 'netmap': 'NetdevNetmapOptions',
213
@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
845
- 'socket': 'NetdevSocketOptions',
214
846
- 'tap': 'NetdevTapOptions',
847
- 'user': 'NetdevUserOptions',
848
- 'vde': 'NetdevVdeOptions',
849
- 'vhost-user': 'NetdevVhostUserOptions',
850
- 'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
851
-
852
-##
853
-# @query-netdev:
854
-#
855
-# Get a list of @NetdevInfo for all virtual network backend devices (netdevs).
856
-#
857
-# Returns: a list of @NetdevInfo describing each netdev.
858
-#
859
-# Since: 6.0
860
-#
861
-# Example:
862
-#
863
-# -> { "execute": "query-netdev" }
864
-# <- { "return": [
865
-# {
866
-# "ipv6": true,
867
-# "ipv4": true,
868
-# "host": "10.0.2.2",
869
-# "ipv6-dns": "fec0::3",
870
-# "ipv6-prefix": "fec0::",
871
-# "net": "10.0.2.0/255.255.255.0",
872
-# "ipv6-host": "fec0::2",
873
-# "type": "user",
874
-# "peer-id": "net0",
875
-# "dns": "10.0.2.3",
876
-# "hostfwd": [
877
-# {
878
-# "str": "tcp::20004-:22"
879
-# }
880
-# ],
881
-# "ipv6-prefixlen": 64,
882
-# "id": "netdev0",
883
-# "restrict": false
884
-# }
885
-# ]
886
-# }
887
-#
888
-##
889
-{ 'command': 'query-netdev', 'returns': ['NetdevInfo'] }
215
--
890
--
216
2.7.4
891
2.7.4
217
892
218
893
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
Commit 969e50b61a28 ("net: Pad short frames to minimum size before
2
sending from SLiRP/TAP") tries to pad frames but try to recyle the
3
local array that is used for padding to tap thread. This patch fixes
4
this by recyling the original buffer.
2
5
3
Packet size some time different or when network is busy.
6
Fixes: 969e50b61a28 ("net: Pad short frames to minimum size before sending from SLiRP/TAP")
4
Based on same payload size, but TCP protocol can not
7
Tested-by: Howard Spoelstra <hsp.cat7@gmail.com>
5
guarantee send the same one packet in the same way,
8
Tested-by: Bin Meng <bmeng.cn@gmail.com>
6
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
7
like that:
8
We send this payload:
9
------------------------------
10
| header |1|2|3|4|5|6|7|8|9|0|
11
------------------------------
12
13
primary:
14
ppkt1:
15
----------------
16
| header |1|2|3|
17
----------------
18
ppkt2:
19
------------------------
20
| header |4|5|6|7|8|9|0|
21
------------------------
22
23
secondary:
24
spkt1:
25
------------------------------
26
| header |1|2|3|4|5|6|7|8|9|0|
27
------------------------------
28
29
In the original method, ppkt1 and ppkt2 are different in size and
30
spkt1, so they can't compare and trigger the checkpoint.
31
32
I have tested FTP get 200M and 1G file many times, I found that
33
the performance was less than 1% of the native.
34
35
Now I reconstructed the comparison of TCP packets based on the
36
TCP sequence number. first of all, ppkt1 and spkt1 have the same
37
starting sequence number, so they can compare, even though their
38
length is different. And then ppkt1 with a smaller payload length
39
is used as the comparison length, if the payload is same, send
40
out the ppkt1 and record the offset(the length of ppkt1 payload)
41
in spkt1. The next comparison, ppkt2 and spkt1 can be compared
42
from the recorded position of spkt1.
43
44
like that:
45
----------------
46
| header |1|2|3| ppkt1
47
---------|-----|
48
| |
49
---------v-----v--------------
50
| header |1|2|3|4|5|6|7|8|9|0| spkt1
51
---------------|\------------|
52
| \offset |
53
---------v-------------v
54
| header |4|5|6|7|8|9|0| ppkt2
55
------------------------
56
57
In this way, the performance can reach native 20% in my multiple
58
tests.
59
60
Cc: Zhang Chen <zhangckid@gmail.com>
61
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
62
Cc: Jason Wang <jasowang@redhat.com>
63
64
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
65
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
66
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
67
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
68
Tested-by: Zhang Chen <zhangckid@gmail.com>
69
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
70
---
11
---
71
net/colo-compare.c | 343 +++++++++++++++++++++++++++++++++++------------------
12
net/tap-win32.c | 6 ++++--
72
net/colo.c | 9 ++
13
1 file changed, 4 insertions(+), 2 deletions(-)
73
net/colo.h | 15 +++
74
net/trace-events | 2 +-
75
4 files changed, 250 insertions(+), 119 deletions(-)
76
14
77
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
diff --git a/net/tap-win32.c b/net/tap-win32.c
78
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
79
--- a/net/colo-compare.c
17
--- a/net/tap-win32.c
80
+++ b/net/colo-compare.c
18
+++ b/net/tap-win32.c
81
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
82
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
20
static void tap_win32_send(void *opaque)
83
#define MAX_QUEUE_SIZE 1024
21
{
84
22
TAPState *s = opaque;
85
+#define COLO_COMPARE_FREE_PRIMARY 0x01
23
- uint8_t *buf;
86
+#define COLO_COMPARE_FREE_SECONDARY 0x02
24
+ uint8_t *buf, *orig_buf;
25
int max_size = 4096;
26
int size;
27
uint8_t min_pkt[ETH_ZLEN];
28
@@ -XXX,XX +XXX,XX @@ static void tap_win32_send(void *opaque)
29
30
size = tap_win32_read(s->handle, &buf, max_size);
31
if (size > 0) {
32
+ orig_buf = buf;
87
+
33
+
88
/* TODO: Should be configurable */
34
if (!s->nc.peer->do_not_pad) {
89
#define REGULAR_PACKET_CHECK_MS 3000
35
if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
90
36
buf = min_pkt;
91
@@ -XXX,XX +XXX,XX @@ static gint seq_sorter(Packet *a, Packet *b, gpointer data)
37
@@ -XXX,XX +XXX,XX @@ static void tap_win32_send(void *opaque)
92
return ntohl(atcp->th_seq) - ntohl(btcp->th_seq);
93
}
94
95
+static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
96
+{
97
+ Packet *pkt = data;
98
+ struct tcphdr *tcphd;
99
+
100
+ tcphd = (struct tcphdr *)pkt->transport_header;
101
+
102
+ pkt->tcp_seq = ntohl(tcphd->th_seq);
103
+ pkt->tcp_ack = ntohl(tcphd->th_ack);
104
+ *max_ack = *max_ack > pkt->tcp_ack ? *max_ack : pkt->tcp_ack;
105
+ pkt->header_size = pkt->transport_header - (uint8_t *)pkt->data
106
+ + (tcphd->th_off << 2) - pkt->vnet_hdr_len;
107
+ pkt->payload_size = pkt->size - pkt->header_size;
108
+ pkt->seq_end = pkt->tcp_seq + pkt->payload_size;
109
+ pkt->flags = tcphd->th_flags;
110
+}
111
+
112
/*
113
* Return 1 on success, if return 0 means the
114
* packet will be dropped
115
*/
116
-static int colo_insert_packet(GQueue *queue, Packet *pkt)
117
+static int colo_insert_packet(GQueue *queue, Packet *pkt, uint32_t *max_ack)
118
{
119
if (g_queue_get_length(queue) <= MAX_QUEUE_SIZE) {
120
if (pkt->ip->ip_p == IPPROTO_TCP) {
121
+ fill_pkt_tcp_info(pkt, max_ack);
122
g_queue_insert_sorted(queue,
123
pkt,
124
(GCompareDataFunc)seq_sorter,
125
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
126
}
127
128
if (mode == PRIMARY_IN) {
129
- if (!colo_insert_packet(&conn->primary_list, pkt)) {
130
+ if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
131
error_report("colo compare primary queue size too big,"
132
"drop packet");
133
}
38
}
134
} else {
39
135
- if (!colo_insert_packet(&conn->secondary_list, pkt)) {
40
qemu_send_packet(&s->nc, buf, size);
136
+ if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
41
- tap_win32_free_buffer(s->handle, buf);
137
error_report("colo compare secondary queue size too big,"
42
+ tap_win32_free_buffer(s->handle, orig_buf);
138
"drop packet");
139
}
140
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
141
return 0;
142
}
143
144
+static inline bool after(uint32_t seq1, uint32_t seq2)
145
+{
146
+ return (int32_t)(seq1 - seq2) > 0;
147
+}
148
+
149
+static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
150
+{
151
+ int ret;
152
+ ret = compare_chr_send(s,
153
+ pkt->data,
154
+ pkt->size,
155
+ pkt->vnet_hdr_len);
156
+ if (ret < 0) {
157
+ error_report("colo send primary packet failed");
158
+ }
159
+ trace_colo_compare_main("packet same and release packet");
160
+ packet_destroy(pkt, NULL);
161
+}
162
+
163
/*
164
* The IP packets sent by primary and secondary
165
* will be compared in here
166
@@ -XXX,XX +XXX,XX @@ static int colo_compare_packet_payload(Packet *ppkt,
167
}
168
169
/*
170
- * Called from the compare thread on the primary
171
- * for compare tcp packet
172
- * compare_tcp copied from Dr. David Alan Gilbert's branch
173
- */
174
-static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
175
+ * return true means that the payload is consist and
176
+ * need to make the next comparison, false means do
177
+ * the checkpoint
178
+*/
179
+static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
180
+ int8_t *mark, uint32_t max_ack)
181
{
182
- struct tcphdr *ptcp, *stcp;
183
- int res;
184
+ *mark = 0;
185
+
186
+ if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
187
+ if (colo_compare_packet_payload(ppkt, spkt,
188
+ ppkt->header_size, spkt->header_size,
189
+ ppkt->payload_size)) {
190
+ *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
191
+ return true;
192
+ }
193
+ }
194
+ if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
195
+ if (colo_compare_packet_payload(ppkt, spkt,
196
+ ppkt->header_size, spkt->header_size,
197
+ ppkt->payload_size)) {
198
+ *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
199
+ return true;
200
+ }
201
+ }
202
+
203
+ /* one part of secondary packet payload still need to be compared */
204
+ if (!after(ppkt->seq_end, spkt->seq_end)) {
205
+ if (colo_compare_packet_payload(ppkt, spkt,
206
+ ppkt->header_size + ppkt->offset,
207
+ spkt->header_size + spkt->offset,
208
+ ppkt->payload_size - ppkt->offset)) {
209
+ if (!after(ppkt->tcp_ack, max_ack)) {
210
+ *mark = COLO_COMPARE_FREE_PRIMARY;
211
+ spkt->offset += ppkt->payload_size - ppkt->offset;
212
+ return true;
213
+ } else {
214
+ /* secondary guest hasn't ack the data, don't send
215
+ * out this packet
216
+ */
217
+ return false;
218
+ }
219
+ }
220
+ } else {
221
+ /* primary packet is longer than secondary packet, compare
222
+ * the same part and mark the primary packet offset
223
+ */
224
+ if (colo_compare_packet_payload(ppkt, spkt,
225
+ ppkt->header_size + ppkt->offset,
226
+ spkt->header_size + spkt->offset,
227
+ spkt->payload_size - spkt->offset)) {
228
+ *mark = COLO_COMPARE_FREE_SECONDARY;
229
+ ppkt->offset += spkt->payload_size - spkt->offset;
230
+ return true;
231
+ }
232
+ }
233
234
- trace_colo_compare_main("compare tcp");
235
+ return false;
236
+}
237
238
- ptcp = (struct tcphdr *)ppkt->transport_header;
239
- stcp = (struct tcphdr *)spkt->transport_header;
240
+static void colo_compare_tcp(CompareState *s, Connection *conn)
241
+{
242
+ Packet *ppkt = NULL, *spkt = NULL;
243
+ int8_t mark;
244
245
/*
246
- * The 'identification' field in the IP header is *very* random
247
- * it almost never matches. Fudge this by ignoring differences in
248
- * unfragmented packets; they'll normally sort themselves out if different
249
- * anyway, and it should recover at the TCP level.
250
- * An alternative would be to get both the primary and secondary to rewrite
251
- * somehow; but that would need some sync traffic to sync the state
252
- */
253
- if (ntohs(ppkt->ip->ip_off) & IP_DF) {
254
- spkt->ip->ip_id = ppkt->ip->ip_id;
255
- /* and the sum will be different if the IDs were different */
256
- spkt->ip->ip_sum = ppkt->ip->ip_sum;
257
+ * If ppkt and spkt have the same payload, but ppkt's ACK
258
+ * is greater than spkt's ACK, in this case we can not
259
+ * send the ppkt because it will cause the secondary guest
260
+ * to miss sending some data in the next. Therefore, we
261
+ * record the maximum ACK in the current queue at both
262
+ * primary side and secondary side. Only when the ack is
263
+ * less than the smaller of the two maximum ack, then we
264
+ * can ensure that the packet's payload is acknowledged by
265
+ * primary and secondary.
266
+ */
267
+ uint32_t min_ack = conn->pack > conn->sack ? conn->sack : conn->pack;
268
+
269
+pri:
270
+ if (g_queue_is_empty(&conn->primary_list)) {
271
+ return;
272
}
273
+ ppkt = g_queue_pop_head(&conn->primary_list);
274
+sec:
275
+ if (g_queue_is_empty(&conn->secondary_list)) {
276
+ g_queue_push_head(&conn->primary_list, ppkt);
277
+ return;
278
+ }
279
+ spkt = g_queue_pop_head(&conn->secondary_list);
280
281
- /*
282
- * Check tcp header length for tcp option field.
283
- * th_off > 5 means this tcp packet have options field.
284
- * The tcp options maybe always different.
285
- * for example:
286
- * From RFC 7323.
287
- * TCP Timestamps option (TSopt):
288
- * Kind: 8
289
- *
290
- * Length: 10 bytes
291
- *
292
- * +-------+-------+---------------------+---------------------+
293
- * |Kind=8 | 10 | TS Value (TSval) |TS Echo Reply (TSecr)|
294
- * +-------+-------+---------------------+---------------------+
295
- * 1 1 4 4
296
- *
297
- * In this case the primary guest's timestamp always different with
298
- * the secondary guest's timestamp. COLO just focus on payload,
299
- * so we just need skip this field.
300
- */
301
+ if (ppkt->tcp_seq == ppkt->seq_end) {
302
+ colo_release_primary_pkt(s, ppkt);
303
+ ppkt = NULL;
304
+ }
305
306
- ptrdiff_t ptcp_offset, stcp_offset;
307
+ if (ppkt && conn->compare_seq && !after(ppkt->seq_end, conn->compare_seq)) {
308
+ trace_colo_compare_main("pri: this packet has compared");
309
+ colo_release_primary_pkt(s, ppkt);
310
+ ppkt = NULL;
311
+ }
312
313
- ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
314
- + (ptcp->th_off << 2) - ppkt->vnet_hdr_len;
315
- stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
316
- + (stcp->th_off << 2) - spkt->vnet_hdr_len;
317
- if (ppkt->size - ptcp_offset == spkt->size - stcp_offset) {
318
- res = colo_compare_packet_payload(ppkt, spkt,
319
- ptcp_offset, stcp_offset,
320
- ppkt->size - ptcp_offset);
321
+ if (spkt->tcp_seq == spkt->seq_end) {
322
+ packet_destroy(spkt, NULL);
323
+ if (!ppkt) {
324
+ goto pri;
325
+ } else {
326
+ goto sec;
327
+ }
328
} else {
329
- trace_colo_compare_main("TCP: payload size of packets are different");
330
- res = -1;
331
+ if (conn->compare_seq && !after(spkt->seq_end, conn->compare_seq)) {
332
+ trace_colo_compare_main("sec: this packet has compared");
333
+ packet_destroy(spkt, NULL);
334
+ if (!ppkt) {
335
+ goto pri;
336
+ } else {
337
+ goto sec;
338
+ }
339
+ }
340
+ if (!ppkt) {
341
+ g_queue_push_head(&conn->secondary_list, spkt);
342
+ goto pri;
343
+ }
344
}
345
346
- if (res != 0 &&
347
- trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
348
- char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
349
-
350
- strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src));
351
- strcpy(pri_ip_dst, inet_ntoa(ppkt->ip->ip_dst));
352
- strcpy(sec_ip_src, inet_ntoa(spkt->ip->ip_src));
353
- strcpy(sec_ip_dst, inet_ntoa(spkt->ip->ip_dst));
354
-
355
- trace_colo_compare_ip_info(ppkt->size, pri_ip_src,
356
- pri_ip_dst, spkt->size,
357
- sec_ip_src, sec_ip_dst);
358
-
359
- trace_colo_compare_tcp_info("pri tcp packet",
360
- ntohl(ptcp->th_seq),
361
- ntohl(ptcp->th_ack),
362
- res, ptcp->th_flags,
363
- ppkt->size);
364
-
365
- trace_colo_compare_tcp_info("sec tcp packet",
366
- ntohl(stcp->th_seq),
367
- ntohl(stcp->th_ack),
368
- res, stcp->th_flags,
369
- spkt->size);
370
+ if (colo_mark_tcp_pkt(ppkt, spkt, &mark, min_ack)) {
371
+ trace_colo_compare_tcp_info("pri",
372
+ ppkt->tcp_seq, ppkt->tcp_ack,
373
+ ppkt->header_size, ppkt->payload_size,
374
+ ppkt->offset, ppkt->flags);
375
+
376
+ trace_colo_compare_tcp_info("sec",
377
+ spkt->tcp_seq, spkt->tcp_ack,
378
+ spkt->header_size, spkt->payload_size,
379
+ spkt->offset, spkt->flags);
380
+
381
+ if (mark == COLO_COMPARE_FREE_PRIMARY) {
382
+ conn->compare_seq = ppkt->seq_end;
383
+ colo_release_primary_pkt(s, ppkt);
384
+ g_queue_push_head(&conn->secondary_list, spkt);
385
+ goto pri;
386
+ }
387
+ if (mark == COLO_COMPARE_FREE_SECONDARY) {
388
+ conn->compare_seq = spkt->seq_end;
389
+ packet_destroy(spkt, NULL);
390
+ goto sec;
391
+ }
392
+ if (mark == (COLO_COMPARE_FREE_PRIMARY | COLO_COMPARE_FREE_SECONDARY)) {
393
+ conn->compare_seq = ppkt->seq_end;
394
+ colo_release_primary_pkt(s, ppkt);
395
+ packet_destroy(spkt, NULL);
396
+ goto pri;
397
+ }
398
+ } else {
399
+ g_queue_push_head(&conn->primary_list, ppkt);
400
+ g_queue_push_head(&conn->secondary_list, spkt);
401
402
qemu_hexdump((char *)ppkt->data, stderr,
403
"colo-compare ppkt", ppkt->size);
404
qemu_hexdump((char *)spkt->data, stderr,
405
"colo-compare spkt", spkt->size);
406
- }
407
408
- return res;
409
+ /*
410
+ * colo_compare_inconsistent_notify();
411
+ * TODO: notice to checkpoint();
412
+ */
413
+ }
414
}
415
416
+
417
/*
418
* Called from the compare thread on the primary
419
* for compare udp packet
420
@@ -XXX,XX +XXX,XX @@ static void colo_old_packet_check(void *opaque)
421
(GCompareFunc)colo_old_packet_check_one_conn);
422
}
423
424
-/*
425
- * Called from the compare thread on the primary
426
- * for compare packet with secondary list of the
427
- * specified connection when a new packet was
428
- * queued to it.
429
- */
430
-static void colo_compare_connection(void *opaque, void *user_data)
431
+static void colo_compare_packet(CompareState *s, Connection *conn,
432
+ int (*HandlePacket)(Packet *spkt,
433
+ Packet *ppkt))
434
{
435
- CompareState *s = user_data;
436
- Connection *conn = opaque;
437
Packet *pkt = NULL;
438
GList *result = NULL;
439
- int ret;
440
441
while (!g_queue_is_empty(&conn->primary_list) &&
442
!g_queue_is_empty(&conn->secondary_list)) {
443
pkt = g_queue_pop_head(&conn->primary_list);
444
- switch (conn->ip_proto) {
445
- case IPPROTO_TCP:
446
- result = g_queue_find_custom(&conn->secondary_list,
447
- pkt, (GCompareFunc)colo_packet_compare_tcp);
448
- break;
449
- case IPPROTO_UDP:
450
- result = g_queue_find_custom(&conn->secondary_list,
451
- pkt, (GCompareFunc)colo_packet_compare_udp);
452
- break;
453
- case IPPROTO_ICMP:
454
- result = g_queue_find_custom(&conn->secondary_list,
455
- pkt, (GCompareFunc)colo_packet_compare_icmp);
456
- break;
457
- default:
458
- result = g_queue_find_custom(&conn->secondary_list,
459
- pkt, (GCompareFunc)colo_packet_compare_other);
460
- break;
461
- }
462
+ result = g_queue_find_custom(&conn->secondary_list,
463
+ pkt, (GCompareFunc)HandlePacket);
464
465
if (result) {
466
- ret = compare_chr_send(s,
467
- pkt->data,
468
- pkt->size,
469
- pkt->vnet_hdr_len);
470
- if (ret < 0) {
471
- error_report("colo_send_primary_packet failed");
472
- }
473
- trace_colo_compare_main("packet same and release packet");
474
+ colo_release_primary_pkt(s, pkt);
475
g_queue_remove(&conn->secondary_list, result->data);
476
- packet_destroy(pkt, NULL);
477
} else {
478
/*
479
* If one packet arrive late, the secondary_list or
480
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
481
}
43
}
482
}
44
}
483
45
484
+/*
485
+ * Called from the compare thread on the primary
486
+ * for compare packet with secondary list of the
487
+ * specified connection when a new packet was
488
+ * queued to it.
489
+ */
490
+static void colo_compare_connection(void *opaque, void *user_data)
491
+{
492
+ CompareState *s = user_data;
493
+ Connection *conn = opaque;
494
+
495
+ switch (conn->ip_proto) {
496
+ case IPPROTO_TCP:
497
+ colo_compare_tcp(s, conn);
498
+ break;
499
+ case IPPROTO_UDP:
500
+ colo_compare_packet(s, conn, colo_packet_compare_udp);
501
+ break;
502
+ case IPPROTO_ICMP:
503
+ colo_compare_packet(s, conn, colo_packet_compare_icmp);
504
+ break;
505
+ default:
506
+ colo_compare_packet(s, conn, colo_packet_compare_other);
507
+ break;
508
+ }
509
+}
510
+
511
static int compare_chr_send(CompareState *s,
512
const uint8_t *buf,
513
uint32_t size,
514
diff --git a/net/colo.c b/net/colo.c
515
index XXXXXXX..XXXXXXX 100644
516
--- a/net/colo.c
517
+++ b/net/colo.c
518
@@ -XXX,XX +XXX,XX @@ Connection *connection_new(ConnectionKey *key)
519
conn->processing = false;
520
conn->offset = 0;
521
conn->syn_flag = 0;
522
+ conn->pack = 0;
523
+ conn->sack = 0;
524
g_queue_init(&conn->primary_list);
525
g_queue_init(&conn->secondary_list);
526
527
@@ -XXX,XX +XXX,XX @@ Packet *packet_new(const void *data, int size, int vnet_hdr_len)
528
pkt->size = size;
529
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
530
pkt->vnet_hdr_len = vnet_hdr_len;
531
+ pkt->tcp_seq = 0;
532
+ pkt->tcp_ack = 0;
533
+ pkt->seq_end = 0;
534
+ pkt->header_size = 0;
535
+ pkt->payload_size = 0;
536
+ pkt->offset = 0;
537
+ pkt->flags = 0;
538
539
return pkt;
540
}
541
diff --git a/net/colo.h b/net/colo.h
542
index XXXXXXX..XXXXXXX 100644
543
--- a/net/colo.h
544
+++ b/net/colo.h
545
@@ -XXX,XX +XXX,XX @@ typedef struct Packet {
546
int64_t creation_ms;
547
/* Get vnet_hdr_len from filter */
548
uint32_t vnet_hdr_len;
549
+ uint32_t tcp_seq; /* sequence number */
550
+ uint32_t tcp_ack; /* acknowledgement number */
551
+ /* the sequence number of the last byte of the packet */
552
+ uint32_t seq_end;
553
+ uint8_t header_size; /* the header length */
554
+ uint16_t payload_size; /* the payload length */
555
+ /* record the payload offset(the length that has been compared) */
556
+ uint16_t offset;
557
+ uint8_t flags; /* Flags(aka Control bits) */
558
} Packet;
559
560
typedef struct ConnectionKey {
561
@@ -XXX,XX +XXX,XX @@ typedef struct Connection {
562
/* flag to enqueue unprocessed_connections */
563
bool processing;
564
uint8_t ip_proto;
565
+ /* record the sequence number that has been compared */
566
+ uint32_t compare_seq;
567
+ /* the maximum of acknowledgement number in primary_list queue */
568
+ uint32_t pack;
569
+ /* the maximum of acknowledgement number in secondary_list queue */
570
+ uint32_t sack;
571
/* offset = secondary_seq - primary_seq */
572
tcp_seq offset;
573
/*
574
diff --git a/net/trace-events b/net/trace-events
575
index XXXXXXX..XXXXXXX 100644
576
--- a/net/trace-events
577
+++ b/net/trace-events
578
@@ -XXX,XX +XXX,XX @@ colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
579
colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
580
colo_old_packet_check_found(int64_t old_time) "%" PRId64
581
colo_compare_miscompare(void) ""
582
-colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int res, uint32_t flag, int size) "side: %s seq/ack= %u/%u res= %d flags= 0x%x pkt_size: %d\n"
583
+colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int hdlen, int pdlen, int offset, int flags) "%s: seq/ack= %u/%u hdlen= %d pdlen= %d offset= %d flags=%d\n"
584
585
# net/filter-rewriter.c
586
colo_filter_rewriter_debug(void) ""
587
--
46
--
588
2.7.4
47
2.7.4
589
48
590
49
diff view generated by jsdifflib