1
The following changes since commit e607bbee553cfe73072870cef458cfa4e78133e2:
1
The following changes since commit e81eb5e6d108008445821e4f891fb9563016c71b:
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
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-01-23 22:34:21 +0000)
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 f574633529926697ced51b6865e5c50bbb78bf1b:
10
10
11
MAINTAINERS: update Dmitry Fleytman email (2018-01-29 16:05:38 +0800)
11
net: checksum: Introduce fine control over checksum type (2021-01-25 17:04:56 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Mao Zhongyi (2):
16
Bin Meng (1):
17
colo: modified the payload compare function
17
net: checksum: Introduce fine control over checksum type
18
colo: compare the packet based on the tcp sequence number
19
18
20
Philippe Mathieu-Daudé (1):
19
Guishan Qin (1):
21
MAINTAINERS: update Dmitry Fleytman email
20
net: checksum: Add IP header checksum calculation
22
21
23
Thomas Huth (3):
22
Markus Armbruster (1):
24
net: Allow hubports to connect to other netdevs
23
net: Fix handling of id in netdev_add and netdev_del
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
24
28
MAINTAINERS | 8 +-
25
Markus Carlstedt (1):
29
hmp-commands.hx | 4 +-
26
net: checksum: Skip fragmented IP packets
30
net/colo-compare.c | 411 +++++++++++++++++++++++++++++++++--------------------
27
31
net/colo.c | 9 ++
28
hw/net/allwinner-sun8i-emac.c | 2 +-
32
net/colo.h | 15 ++
29
hw/net/cadence_gem.c | 2 +-
33
net/hub.c | 27 +++-
30
hw/net/fsl_etsec/rings.c | 18 +++++++++---------
34
net/hub.h | 3 +-
31
hw/net/ftgmac100.c | 13 ++++++++++++-
35
net/net.c | 2 +-
32
hw/net/imx_fec.c | 20 ++++++++------------
36
net/slirp.c | 33 +++--
33
hw/net/virtio-net.c | 2 +-
37
net/trace-events | 2 +-
34
hw/net/xen_nic.c | 2 +-
38
qapi/net.json | 4 +-
35
include/net/checksum.h | 7 ++++++-
39
qemu-options.hx | 12 +-
36
net/checksum.c | 24 +++++++++++++++++++++---
40
12 files changed, 347 insertions(+), 183 deletions(-)
37
net/filter-rewriter.c | 4 ++--
38
net/net.c | 20 ++++++++++++++++++--
39
11 files changed, 80 insertions(+), 34 deletions(-)
41
40
42
41
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Markus Armbruster <armbru@redhat.com>
2
2
3
Modified the function colo_packet_compare_common to prepare for the
3
CLI -netdev accumulates in option group "netdev".
4
tcp packet comparison in the next patch.
5
4
6
Cc: Zhang Chen <zhangckid@gmail.com>
5
Before commit 08712fcb85 "net: Track netdevs in NetClientState rather
7
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
6
than QemuOpt", netdev_add added to the option group, and netdev_del
8
Cc: Jason Wang <jasowang@redhat.com>
7
removed from it, both HMP and QMP. Thus, every netdev had a
8
corresponding QemuOpts in this option group.
9
9
10
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
10
Commit 08712fcb85 dropped this for QMP netdev_add and both netdev_del.
11
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
11
Now a netdev has a corresponding QemuOpts only when it was created
12
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
12
with CLI or HMP. Two issues:
13
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
13
14
* QMP and HMP netdev_del can leave QemuOpts behind, breaking HMP
15
netdev_add. Reproducer:
16
17
$ qemu-system-x86_64 -S -display none -nodefaults -monitor stdio
18
QEMU 5.1.92 monitor - type 'help' for more information
19
(qemu) netdev_add user,id=net0
20
(qemu) info network
21
net0: index=0,type=user,net=10.0.2.0,restrict=off
22
(qemu) netdev_del net0
23
(qemu) info network
24
(qemu) netdev_add user,id=net0
25
upstream-qemu: Duplicate ID 'net0' for netdev
26
Try "help netdev_add" for more information
27
28
Fix by restoring the QemuOpts deletion in qmp_netdev_del(), but with
29
a guard, because the QemuOpts need not exist.
30
31
* QMP netdev_add loses its "no duplicate ID" check. Reproducer:
32
33
$ qemu-system-x86_64 -S -display none -qmp stdio
34
{"QMP": {"version": {"qemu": {"micro": 92, "minor": 1, "major": 5}, "package": "v5.2.0-rc2-1-g02c1f0142c"}, "capabilities": ["oob"]}}
35
{"execute": "qmp_capabilities"}
36
{"return": {}}
37
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
38
{"return": {}}
39
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
40
{"return": {}}
41
42
Fix by adding a duplicate ID check to net_client_init1() to replace
43
the lost one. The check is redundant for callers where QemuOpts
44
still checks, i.e. for CLI and HMP.
45
46
Reported-by: Andrew Melnichenko <andrew@daynix.com>
47
Fixes: 08712fcb851034228b61f75bd922863a984a4f60
48
Cc: qemu-stable@nongnu.org
49
Signed-off-by: Markus Armbruster <armbru@redhat.com>
50
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
51
Signed-off-by: Jason Wang <jasowang@redhat.com>
15
---
52
---
16
net/colo-compare.c | 88 +++++++++++++++++++++++++++---------------------------
53
net/net.c | 20 ++++++++++++++++++--
17
1 file changed, 44 insertions(+), 44 deletions(-)
54
1 file changed, 18 insertions(+), 2 deletions(-)
18
55
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
56
diff --git a/net/net.c b/net/net.c
20
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
58
--- a/net/net.c
22
+++ b/net/colo-compare.c
59
+++ b/net/net.c
23
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
60
@@ -XXX,XX +XXX,XX @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
24
* return: 0 means packet same
61
static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
25
* > 0 || < 0 means packet different
26
*/
27
-static int colo_packet_compare_common(Packet *ppkt,
28
- Packet *spkt,
29
- int poffset,
30
- int soffset)
31
+static int colo_compare_packet_payload(Packet *ppkt,
32
+ Packet *spkt,
33
+ uint16_t poffset,
34
+ uint16_t soffset,
35
+ uint16_t len)
36
+
37
{
62
{
38
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
63
NetClientState *peer = NULL;
39
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
64
+ NetClientState *nc;
40
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt,
65
41
sec_ip_src, sec_ip_dst);
66
if (is_netdev) {
67
if (netdev->type == NET_CLIENT_DRIVER_NIC ||
68
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
69
}
42
}
70
}
43
71
44
- poffset = ppkt->vnet_hdr_len + poffset;
72
+ nc = qemu_find_netdev(netdev->id);
45
- soffset = ppkt->vnet_hdr_len + soffset;
73
+ if (nc) {
46
-
74
+ error_setg(errp, "Duplicate ID '%s'", netdev->id);
47
- if (ppkt->size - poffset == spkt->size - soffset) {
48
- return memcmp(ppkt->data + poffset,
49
- spkt->data + soffset,
50
- spkt->size - soffset);
51
- } else {
52
- trace_colo_compare_main("Net packet size are not the same");
53
- return -1;
54
- }
55
+ return memcmp(ppkt->data + poffset, spkt->data + soffset, len);
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
-
113
- if (ret) {
114
+ if (ppkt->size != spkt->size) {
115
+ trace_colo_compare_main("UDP: payload size of packets are different");
116
+ return -1;
75
+ return -1;
117
+ }
76
+ }
118
+ if (colo_compare_packet_payload(ppkt, spkt, offset, offset,
77
+
119
+ ppkt->size - offset)) {
78
if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
120
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
79
/* FIXME drop when all init functions store an Error */
121
trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
80
if (errp && !*errp) {
122
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
81
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
123
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
124
qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
125
spkt->size);
126
}
127
+ return -1;
128
+ } else {
129
+ return 0;
130
}
82
}
83
84
if (is_netdev) {
85
- NetClientState *nc;
131
-
86
-
132
- return ret;
87
nc = qemu_find_netdev(netdev->id);
88
assert(nc);
89
nc->is_netdev = true;
90
@@ -XXX,XX +XXX,XX @@ void qmp_netdev_add(Netdev *netdev, Error **errp)
91
void qmp_netdev_del(const char *id, Error **errp)
92
{
93
NetClientState *nc;
94
+ QemuOpts *opts;
95
96
nc = qemu_find_netdev(id);
97
if (!nc) {
98
@@ -XXX,XX +XXX,XX @@ void qmp_netdev_del(const char *id, Error **errp)
99
}
100
101
qemu_del_net_client(nc);
102
+
103
+ /*
104
+ * Wart: we need to delete the QemuOpts associated with netdevs
105
+ * created via CLI or HMP, to avoid bogus "Duplicate ID" errors in
106
+ * HMP netdev_add.
107
+ */
108
+ opts = qemu_opts_find(qemu_find_opts("netdev"), id);
109
+ if (opts) {
110
+ qemu_opts_del(opts);
111
+ }
133
}
112
}
134
113
135
/*
114
static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
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
--
115
--
186
2.7.4
116
2.7.4
187
117
188
118
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Markus Carlstedt <markus.carlstedt@windriver.com>
2
2
3
QEMU can emulate hubs to connect NICs and netdevs. This is currently
3
To calculate the TCP/UDP checksum we need the whole datagram. Unless
4
primarily used for the mis-named 'vlan' feature of the networking
4
the hardware has some logic to collect all fragments before sending
5
subsystem. Now the 'vlan' feature has been marked as deprecated, since
5
the whole datagram first, it can only be done by the network stack,
6
its name is rather confusing and the users often rather mis-configure
6
which is normally the case for the NICs we have seen so far.
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
7
12
Now to be able to use the hubport feature without 'vlan's, there is one
8
Skip these fragmented IP packets to avoid checksum corruption.
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
9
17
To bundle up the output of multiple NICs into one socket netdev, you can
10
Signed-off-by: Markus Carlstedt <markus.carlstedt@windriver.com>
18
now run QEMU with these parameters for example:
11
Signed-off-by: Bin Meng <bin.meng@windriver.com>
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>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
40
---
13
---
41
net/hub.c | 27 +++++++++++++++++++++------
14
net/checksum.c | 4 ++++
42
net/hub.h | 3 ++-
15
1 file changed, 4 insertions(+)
43
net/net.c | 2 +-
44
qapi/net.json | 4 +++-
45
qemu-options.hx | 8 +++++---
46
5 files changed, 32 insertions(+), 12 deletions(-)
47
16
48
diff --git a/net/hub.c b/net/hub.c
17
diff --git a/net/checksum.c b/net/checksum.c
49
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
50
--- a/net/hub.c
19
--- a/net/checksum.c
51
+++ b/net/hub.c
20
+++ b/net/checksum.c
52
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
53
*/
22
return; /* not IPv4 */
54
55
#include "qemu/osdep.h"
56
+#include "qapi/error.h"
57
#include "monitor/monitor.h"
58
#include "net/net.h"
59
#include "clients.h"
60
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_hub_port_info = {
61
.cleanup = net_hub_port_cleanup,
62
};
63
64
-static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
65
+static NetHubPort *net_hub_port_new(NetHub *hub, const char *name,
66
+ NetClientState *hubpeer)
67
{
68
NetClientState *nc;
69
NetHubPort *port;
70
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
71
name = default_name;
72
}
23
}
73
24
74
- nc = qemu_new_net_client(&net_hub_port_info, NULL, "hub", name);
25
+ if (IP4_IS_FRAGMENT(ip)) {
75
+ nc = qemu_new_net_client(&net_hub_port_info, hubpeer, "hub", name);
26
+ return; /* a fragmented IP packet */
76
port = DO_UPCAST(NetHubPort, nc, nc);
77
port->id = id;
78
port->hub = hub;
79
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
80
81
/**
82
* Create a port on a given hub
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
}
103
104
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_port_find(int hub_id)
105
}
106
}
107
108
- nc = net_hub_add_port(hub_id, NULL);
109
+ nc = net_hub_add_port(hub_id, NULL, NULL);
110
return nc;
111
}
112
113
@@ -XXX,XX +XXX,XX @@ int net_init_hubport(const Netdev *netdev, const char *name,
114
NetClientState *peer, Error **errp)
115
{
116
const NetdevHubPortOptions *hubport;
117
+ NetClientState *hubpeer = NULL;
118
119
assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
120
assert(!peer);
121
hubport = &netdev->u.hubport;
122
123
- net_hub_add_port(hubport->hubid, name);
124
+ if (hubport->has_netdev) {
125
+ hubpeer = qemu_find_netdev(hubport->netdev);
126
+ if (!hubpeer) {
127
+ error_setg(errp, "netdev '%s' not found", hubport->netdev);
128
+ return -1;
129
+ }
130
+ }
27
+ }
131
+
28
+
132
+ net_hub_add_port(hubport->hubid, name, hubpeer);
29
ip_len = lduw_be_p(&ip->ip_len);
133
+
30
134
return 0;
31
/* Last, check that we have enough data for the all IP frame */
135
}
136
137
diff --git a/net/hub.h b/net/hub.h
138
index XXXXXXX..XXXXXXX 100644
139
--- a/net/hub.h
140
+++ b/net/hub.h
141
@@ -XXX,XX +XXX,XX @@
142
143
#include "qemu-common.h"
144
145
-NetClientState *net_hub_add_port(int hub_id, const char *name);
146
+NetClientState *net_hub_add_port(int hub_id, const char *name,
147
+ NetClientState *hubpeer);
148
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
149
void net_hub_info(Monitor *mon);
150
void net_hub_check_clients(void);
151
diff --git a/net/net.c b/net/net.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/net/net.c
154
+++ b/net/net.c
155
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
156
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
157
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
158
!opts->u.nic.has_netdev) {
159
- peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
160
+ peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL, NULL);
161
}
162
163
if (net->has_vlan && !vlan_warned) {
164
diff --git a/qapi/net.json b/qapi/net.json
165
index XXXXXXX..XXXXXXX 100644
166
--- a/qapi/net.json
167
+++ b/qapi/net.json
168
@@ -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
##
176
{ 'struct': 'NetdevHubPortOptions',
177
'data': {
178
- 'hubid': 'int32' } }
179
+ 'hubid': 'int32',
180
+ '*netdev': 'str' } }
181
182
##
183
# @NetdevNetmapOptions:
184
diff --git a/qemu-options.hx b/qemu-options.hx
185
index XXXXXXX..XXXXXXX 100644
186
--- a/qemu-options.hx
187
+++ b/qemu-options.hx
188
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
189
#endif
190
"-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n"
191
" configure a vhost-user network, backed by a chardev 'dev'\n"
192
- "-netdev hubport,id=str,hubid=n\n"
193
+ "-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
194
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
195
DEF("net", HAS_ARG, QEMU_OPTION_net,
196
"-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
197
@@ -XXX,XX +XXX,XX @@ vde_switch -F -sock /tmp/myswitch
198
qemu-system-i386 linux.img -net nic -net vde,sock=/tmp/myswitch
199
@end example
200
201
-@item -netdev hubport,id=@var{id},hubid=@var{hubid}
202
+@item -netdev hubport,id=@var{id},hubid=@var{hubid}[,netdev=@var{nd}]
203
204
Create a hub port on QEMU "vlan" @var{hubid}.
205
206
The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
207
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
208
-required hub automatically.
209
+required hub automatically. Alternatively, you can also connect the hubport
210
+to another netdev with ID @var{nd} by using the @option{netdev=@var{nd}}
211
+option.
212
213
@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
214
215
--
32
--
216
2.7.4
33
2.7.4
217
34
218
35
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Guishan Qin <guishan.qin@windriver.com>
2
2
3
gently asked by his automatic reply :)
3
At present net_checksum_calculate() only calculates TCP/UDP checksum
4
in an IP packet, but assumes the IP header checksum to be provided
5
by the software, e.g.: Linux kernel always calculates the IP header
6
checksum. However this might not always be the case, e.g.: for an IP
7
checksum offload enabled stack like VxWorks, the IP header checksum
8
can be zero.
4
9
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
This adds the checksum calculation of the IP header.
11
12
Signed-off-by: Guishan Qin <guishan.qin@windriver.com>
13
Signed-off-by: Yabing Liu <yabing.liu@windriver.com>
14
Signed-off-by: Bin Meng <bin.meng@windriver.com>
15
Reviewed-by: Cédric Le Goater <clg@kaod.org>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
17
---
8
MAINTAINERS | 8 ++++----
18
net/checksum.c | 8 ++++++--
9
1 file changed, 4 insertions(+), 4 deletions(-)
19
1 file changed, 6 insertions(+), 2 deletions(-)
10
20
11
diff --git a/MAINTAINERS b/MAINTAINERS
21
diff --git a/net/checksum.c b/net/checksum.c
12
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
13
--- a/MAINTAINERS
23
--- a/net/checksum.c
14
+++ b/MAINTAINERS
24
+++ b/net/checksum.c
15
@@ -XXX,XX +XXX,XX @@ F: hw/scsi/mfi.h
25
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
16
F: tests/megasas-test.c
26
{
17
27
int mac_hdr_len, ip_len;
18
Network packet abstractions
28
struct ip_header *ip;
19
-M: Dmitry Fleytman <dmitry@daynix.com>
29
+ uint16_t csum;
20
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
30
21
S: Maintained
31
/*
22
F: include/net/eth.h
32
* Note: We cannot assume "data" is aligned, so the all code uses
23
F: net/eth.c
33
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
24
@@ -XXX,XX +XXX,XX @@ F: hw/net/net_rx_pkt*
34
return; /* not IPv4 */
25
F: hw/net/net_tx_pkt*
35
}
26
36
27
Vmware
37
+ /* Calculate IP checksum */
28
-M: Dmitry Fleytman <dmitry@daynix.com>
38
+ stw_he_p(&ip->ip_sum, 0);
29
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
39
+ csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip));
30
S: Maintained
40
+ stw_be_p(&ip->ip_sum, csum);
31
F: hw/net/vmxnet*
41
+
32
F: hw/scsi/vmw_pvscsi*
42
if (IP4_IS_FRAGMENT(ip)) {
33
@@ -XXX,XX +XXX,XX @@ F: hw/mem/nvdimm.c
43
return; /* a fragmented IP packet */
34
F: include/hw/mem/nvdimm.h
44
}
35
45
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
36
e1000x
46
switch (ip->ip_p) {
37
-M: Dmitry Fleytman <dmitry@daynix.com>
47
case IP_PROTO_TCP:
38
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
48
{
39
S: Maintained
49
- uint16_t csum;
40
F: hw/net/e1000x*
50
tcp_header *tcp = (tcp_header *)(ip + 1);
41
51
42
e1000e
52
if (ip_len < sizeof(tcp_header)) {
43
-M: Dmitry Fleytman <dmitry@daynix.com>
53
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
44
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
54
}
45
S: Maintained
55
case IP_PROTO_UDP:
46
F: hw/net/e1000e*
56
{
47
57
- uint16_t csum;
58
udp_header *udp = (udp_header *)(ip + 1);
59
60
if (ip_len < sizeof(udp_header)) {
48
--
61
--
49
2.7.4
62
2.7.4
50
63
51
64
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
Packet size some time different or when network is busy.
3
At present net_checksum_calculate() blindly calculates all types of
4
Based on same payload size, but TCP protocol can not
4
checksums (IP, TCP, UDP). Some NICs may have a per type setting in
5
guarantee send the same one packet in the same way,
5
their BDs to control what checksum should be offloaded. To support
6
6
such hardware behavior, introduce a 'csum_flag' parameter to the
7
like that:
7
net_checksum_calculate() API to allow fine control over what type
8
We send this payload:
8
checksum is calculated.
9
------------------------------
9
10
| header |1|2|3|4|5|6|7|8|9|0|
10
Existing users of this API are updated accordingly.
11
------------------------------
11
12
12
Signed-off-by: Bin Meng <bin.meng@windriver.com>
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>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
70
---
14
---
71
net/colo-compare.c | 343 +++++++++++++++++++++++++++++++++++------------------
15
hw/net/allwinner-sun8i-emac.c | 2 +-
72
net/colo.c | 9 ++
16
hw/net/cadence_gem.c | 2 +-
73
net/colo.h | 15 +++
17
hw/net/fsl_etsec/rings.c | 18 +++++++++---------
74
net/trace-events | 2 +-
18
hw/net/ftgmac100.c | 13 ++++++++++++-
75
4 files changed, 250 insertions(+), 119 deletions(-)
19
hw/net/imx_fec.c | 20 ++++++++------------
76
20
hw/net/virtio-net.c | 2 +-
77
diff --git a/net/colo-compare.c b/net/colo-compare.c
21
hw/net/xen_nic.c | 2 +-
78
index XXXXXXX..XXXXXXX 100644
22
include/net/checksum.h | 7 ++++++-
79
--- a/net/colo-compare.c
23
net/checksum.c | 18 ++++++++++++++----
80
+++ b/net/colo-compare.c
24
net/filter-rewriter.c | 4 ++--
81
@@ -XXX,XX +XXX,XX @@
25
10 files changed, 55 insertions(+), 33 deletions(-)
82
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
26
83
#define MAX_QUEUE_SIZE 1024
27
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
84
28
index XXXXXXX..XXXXXXX 100644
85
+#define COLO_COMPARE_FREE_PRIMARY 0x01
29
--- a/hw/net/allwinner-sun8i-emac.c
86
+#define COLO_COMPARE_FREE_SECONDARY 0x02
30
+++ b/hw/net/allwinner-sun8i-emac.c
87
+
31
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
88
/* TODO: Should be configurable */
32
/* After the last descriptor, send the packet */
89
#define REGULAR_PACKET_CHECK_MS 3000
33
if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) {
90
34
if (desc.status2 & TX_DESC_STATUS2_CHECKSUM_MASK) {
91
@@ -XXX,XX +XXX,XX @@ static gint seq_sorter(Packet *a, Packet *b, gpointer data)
35
- net_checksum_calculate(packet_buf, packet_bytes);
92
return ntohl(atcp->th_seq) - ntohl(btcp->th_seq);
36
+ net_checksum_calculate(packet_buf, packet_bytes, CSUM_ALL);
93
}
37
}
94
38
95
+static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
39
qemu_send_packet(nc, packet_buf, packet_bytes);
96
+{
40
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
97
+ Packet *pkt = data;
41
index XXXXXXX..XXXXXXX 100644
98
+ struct tcphdr *tcphd;
42
--- a/hw/net/cadence_gem.c
99
+
43
+++ b/hw/net/cadence_gem.c
100
+ tcphd = (struct tcphdr *)pkt->transport_header;
44
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
101
+
45
102
+ pkt->tcp_seq = ntohl(tcphd->th_seq);
46
/* Is checksum offload enabled? */
103
+ pkt->tcp_ack = ntohl(tcphd->th_ack);
47
if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
104
+ *max_ack = *max_ack > pkt->tcp_ack ? *max_ack : pkt->tcp_ack;
48
- net_checksum_calculate(s->tx_packet, total_bytes);
105
+ pkt->header_size = pkt->transport_header - (uint8_t *)pkt->data
49
+ net_checksum_calculate(s->tx_packet, total_bytes, CSUM_ALL);
106
+ + (tcphd->th_off << 2) - pkt->vnet_hdr_len;
50
}
107
+ pkt->payload_size = pkt->size - pkt->header_size;
51
108
+ pkt->seq_end = pkt->tcp_seq + pkt->payload_size;
52
/* Update MAC statistics */
109
+ pkt->flags = tcphd->th_flags;
53
diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
110
+}
54
index XXXXXXX..XXXXXXX 100644
111
+
55
--- a/hw/net/fsl_etsec/rings.c
112
/*
56
+++ b/hw/net/fsl_etsec/rings.c
113
* Return 1 on success, if return 0 means the
57
@@ -XXX,XX +XXX,XX @@ static void process_tx_fcb(eTSEC *etsec)
114
* packet will be dropped
58
uint8_t *l3_header = etsec->tx_buffer + 8 + l3_header_offset;
115
*/
59
/* L4 header */
116
-static int colo_insert_packet(GQueue *queue, Packet *pkt)
60
uint8_t *l4_header = l3_header + l4_header_offset;
117
+static int colo_insert_packet(GQueue *queue, Packet *pkt, uint32_t *max_ack)
61
+ int csum = 0;
118
{
62
119
if (g_queue_get_length(queue) <= MAX_QUEUE_SIZE) {
63
/* if packet is IP4 and IP checksum is requested */
120
if (pkt->ip->ip_p == IPPROTO_TCP) {
64
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
121
+ fill_pkt_tcp_info(pkt, max_ack);
65
- /* do IP4 checksum (TODO This function does TCP/UDP checksum
122
g_queue_insert_sorted(queue,
66
- * but not sure if it also does IP4 checksum.) */
123
pkt,
67
- net_checksum_calculate(etsec->tx_buffer + 8,
124
(GCompareDataFunc)seq_sorter,
68
- etsec->tx_buffer_len - 8);
125
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
69
+ csum |= CSUM_IP;
126
}
70
}
127
71
/* TODO Check the correct usage of the PHCS field of the FCB in case the NPH
128
if (mode == PRIMARY_IN) {
72
* flag is on */
129
- if (!colo_insert_packet(&conn->primary_list, pkt)) {
73
@@ -XXX,XX +XXX,XX @@ static void process_tx_fcb(eTSEC *etsec)
130
+ if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
74
/* if checksum is requested */
131
error_report("colo compare primary queue size too big,"
75
if (flags & FCB_TX_CTU) {
132
"drop packet");
76
/* do UDP checksum */
77
-
78
- net_checksum_calculate(etsec->tx_buffer + 8,
79
- etsec->tx_buffer_len - 8);
80
+ csum |= CSUM_UDP;
81
} else {
82
/* set checksum field to 0 */
83
l4_header[6] = 0;
84
@@ -XXX,XX +XXX,XX @@ static void process_tx_fcb(eTSEC *etsec)
85
}
86
} else if (flags & FCB_TX_CTU) { /* if TCP and checksum is requested */
87
/* do TCP checksum */
88
- net_checksum_calculate(etsec->tx_buffer + 8,
89
- etsec->tx_buffer_len - 8);
90
+ csum |= CSUM_TCP;
133
}
91
}
134
} else {
92
}
135
- if (!colo_insert_packet(&conn->secondary_list, pkt)) {
93
+
136
+ if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
94
+ if (csum) {
137
error_report("colo compare secondary queue size too big,"
95
+ net_checksum_calculate(etsec->tx_buffer + 8,
138
"drop packet");
96
+ etsec->tx_buffer_len - 8, csum);
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
+ }
97
+ }
414
}
98
}
415
99
416
+
100
static void process_tx_bd(eTSEC *etsec,
417
/*
101
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
418
* Called from the compare thread on the primary
102
index XXXXXXX..XXXXXXX 100644
419
* for compare udp packet
103
--- a/hw/net/ftgmac100.c
420
@@ -XXX,XX +XXX,XX @@ static void colo_old_packet_check(void *opaque)
104
+++ b/hw/net/ftgmac100.c
421
(GCompareFunc)colo_old_packet_check_one_conn);
105
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
106
ptr += len;
107
frame_size += len;
108
if (bd.des0 & FTGMAC100_TXDES0_LTS) {
109
+ int csum = 0;
110
111
/* Check for VLAN */
112
if (flags & FTGMAC100_TXDES1_INS_VLANTAG &&
113
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
114
}
115
116
if (flags & FTGMAC100_TXDES1_IP_CHKSUM) {
117
- net_checksum_calculate(s->frame, frame_size);
118
+ csum |= CSUM_IP;
119
}
120
+ if (flags & FTGMAC100_TXDES1_TCP_CHKSUM) {
121
+ csum |= CSUM_TCP;
122
+ }
123
+ if (flags & FTGMAC100_TXDES1_UDP_CHKSUM) {
124
+ csum |= CSUM_UDP;
125
+ }
126
+ if (csum) {
127
+ net_checksum_calculate(s->frame, frame_size, csum);
128
+ }
129
+
130
/* Last buffer in frame. */
131
qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
132
ptr = s->frame;
133
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/net/imx_fec.c
136
+++ b/hw/net/imx_fec.c
137
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
138
ptr += len;
139
frame_size += len;
140
if (bd.flags & ENET_BD_L) {
141
+ int csum = 0;
142
+
143
if (bd.option & ENET_BD_PINS) {
144
- struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
145
- if (IP_HEADER_VERSION(ip_hd) == 4) {
146
- net_checksum_calculate(s->frame, frame_size);
147
- }
148
+ csum |= (CSUM_TCP | CSUM_UDP);
149
}
150
if (bd.option & ENET_BD_IINS) {
151
- struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
152
- /* We compute checksum only for IPv4 frames */
153
- if (IP_HEADER_VERSION(ip_hd) == 4) {
154
- uint16_t csum;
155
- ip_hd->ip_sum = 0;
156
- csum = net_raw_checksum((uint8_t *)ip_hd, sizeof(*ip_hd));
157
- ip_hd->ip_sum = cpu_to_be16(csum);
158
- }
159
+ csum |= CSUM_IP;
160
+ }
161
+ if (csum) {
162
+ net_checksum_calculate(s->frame, frame_size, csum);
163
}
164
+
165
/* Last buffer in frame. */
166
167
qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
168
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
169
index XXXXXXX..XXXXXXX 100644
170
--- a/hw/net/virtio-net.c
171
+++ b/hw/net/virtio-net.c
172
@@ -XXX,XX +XXX,XX @@ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
173
(buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
174
(buf[23] == 17) && /* ip.protocol == UDP */
175
(buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
176
- net_checksum_calculate(buf, size);
177
+ net_checksum_calculate(buf, size, CSUM_UDP);
178
hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
179
}
422
}
180
}
423
181
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
424
-/*
182
index XXXXXXX..XXXXXXX 100644
425
- * Called from the compare thread on the primary
183
--- a/hw/net/xen_nic.c
426
- * for compare packet with secondary list of the
184
+++ b/hw/net/xen_nic.c
427
- * specified connection when a new packet was
185
@@ -XXX,XX +XXX,XX @@ static void net_tx_packets(struct XenNetDev *netdev)
428
- * queued to it.
186
tmpbuf = g_malloc(XC_PAGE_SIZE);
429
- */
187
}
430
-static void colo_compare_connection(void *opaque, void *user_data)
188
memcpy(tmpbuf, page + txreq.offset, txreq.size);
431
+static void colo_compare_packet(CompareState *s, Connection *conn,
189
- net_checksum_calculate(tmpbuf, txreq.size);
432
+ int (*HandlePacket)(Packet *spkt,
190
+ net_checksum_calculate(tmpbuf, txreq.size, CSUM_ALL);
433
+ Packet *ppkt))
191
qemu_send_packet(qemu_get_queue(netdev->nic), tmpbuf,
192
txreq.size);
193
} else {
194
diff --git a/include/net/checksum.h b/include/net/checksum.h
195
index XXXXXXX..XXXXXXX 100644
196
--- a/include/net/checksum.h
197
+++ b/include/net/checksum.h
198
@@ -XXX,XX +XXX,XX @@
199
#include "qemu/bswap.h"
200
struct iovec;
201
202
+#define CSUM_IP 0x01
203
+#define CSUM_TCP 0x02
204
+#define CSUM_UDP 0x04
205
+#define CSUM_ALL (CSUM_IP | CSUM_TCP | CSUM_UDP)
206
+
207
uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq);
208
uint16_t net_checksum_finish(uint32_t sum);
209
uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
210
uint8_t *addrs, uint8_t *buf);
211
-void net_checksum_calculate(uint8_t *data, int length);
212
+void net_checksum_calculate(uint8_t *data, int length, int csum_flag);
213
214
static inline uint32_t
215
net_checksum_add(int len, uint8_t *buf)
216
diff --git a/net/checksum.c b/net/checksum.c
217
index XXXXXXX..XXXXXXX 100644
218
--- a/net/checksum.c
219
+++ b/net/checksum.c
220
@@ -XXX,XX +XXX,XX @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
221
return net_checksum_finish(sum);
222
}
223
224
-void net_checksum_calculate(uint8_t *data, int length)
225
+void net_checksum_calculate(uint8_t *data, int length, int csum_flag)
434
{
226
{
435
- CompareState *s = user_data;
227
int mac_hdr_len, ip_len;
436
- Connection *conn = opaque;
228
struct ip_header *ip;
437
Packet *pkt = NULL;
229
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
438
GList *result = NULL;
230
}
439
- int ret;
231
440
232
/* Calculate IP checksum */
441
while (!g_queue_is_empty(&conn->primary_list) &&
233
- stw_he_p(&ip->ip_sum, 0);
442
!g_queue_is_empty(&conn->secondary_list)) {
234
- csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip));
443
pkt = g_queue_pop_head(&conn->primary_list);
235
- stw_be_p(&ip->ip_sum, csum);
444
- switch (conn->ip_proto) {
236
+ if (csum_flag & CSUM_IP) {
445
- case IPPROTO_TCP:
237
+ stw_he_p(&ip->ip_sum, 0);
446
- result = g_queue_find_custom(&conn->secondary_list,
238
+ csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip));
447
- pkt, (GCompareFunc)colo_packet_compare_tcp);
239
+ stw_be_p(&ip->ip_sum, csum);
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
}
482
}
483
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
+ }
240
+ }
509
+}
241
510
+
242
if (IP4_IS_FRAGMENT(ip)) {
511
static int compare_chr_send(CompareState *s,
243
return; /* a fragmented IP packet */
512
const uint8_t *buf,
244
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
513
uint32_t size,
245
switch (ip->ip_p) {
514
diff --git a/net/colo.c b/net/colo.c
246
case IP_PROTO_TCP:
515
index XXXXXXX..XXXXXXX 100644
247
{
516
--- a/net/colo.c
248
+ if (!(csum_flag & CSUM_TCP)) {
517
+++ b/net/colo.c
249
+ return;
518
@@ -XXX,XX +XXX,XX @@ Connection *connection_new(ConnectionKey *key)
250
+ }
519
conn->processing = false;
251
+
520
conn->offset = 0;
252
tcp_header *tcp = (tcp_header *)(ip + 1);
521
conn->syn_flag = 0;
253
522
+ conn->pack = 0;
254
if (ip_len < sizeof(tcp_header)) {
523
+ conn->sack = 0;
255
@@ -XXX,XX +XXX,XX @@ void net_checksum_calculate(uint8_t *data, int length)
524
g_queue_init(&conn->primary_list);
256
}
525
g_queue_init(&conn->secondary_list);
257
case IP_PROTO_UDP:
526
258
{
527
@@ -XXX,XX +XXX,XX @@ Packet *packet_new(const void *data, int size, int vnet_hdr_len)
259
+ if (!(csum_flag & CSUM_UDP)) {
528
pkt->size = size;
260
+ return;
529
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
261
+ }
530
pkt->vnet_hdr_len = vnet_hdr_len;
262
+
531
+ pkt->tcp_seq = 0;
263
udp_header *udp = (udp_header *)(ip + 1);
532
+ pkt->tcp_ack = 0;
264
533
+ pkt->seq_end = 0;
265
if (ip_len < sizeof(udp_header)) {
534
+ pkt->header_size = 0;
266
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
535
+ pkt->payload_size = 0;
267
index XXXXXXX..XXXXXXX 100644
536
+ pkt->offset = 0;
268
--- a/net/filter-rewriter.c
537
+ pkt->flags = 0;
269
+++ b/net/filter-rewriter.c
538
270
@@ -XXX,XX +XXX,XX @@ static int handle_primary_tcp_pkt(RewriterState *rf,
539
return pkt;
271
tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
540
}
272
541
diff --git a/net/colo.h b/net/colo.h
273
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
542
index XXXXXXX..XXXXXXX 100644
274
- pkt->size - pkt->vnet_hdr_len);
543
--- a/net/colo.h
275
+ pkt->size - pkt->vnet_hdr_len, CSUM_TCP);
544
+++ b/net/colo.h
276
}
545
@@ -XXX,XX +XXX,XX @@ typedef struct Packet {
277
546
int64_t creation_ms;
278
/*
547
/* Get vnet_hdr_len from filter */
279
@@ -XXX,XX +XXX,XX @@ static int handle_secondary_tcp_pkt(RewriterState *rf,
548
uint32_t vnet_hdr_len;
280
tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
549
+ uint32_t tcp_seq; /* sequence number */
281
550
+ uint32_t tcp_ack; /* acknowledgement number */
282
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
551
+ /* the sequence number of the last byte of the packet */
283
- pkt->size - pkt->vnet_hdr_len);
552
+ uint32_t seq_end;
284
+ pkt->size - pkt->vnet_hdr_len, CSUM_TCP);
553
+ uint8_t header_size; /* the header length */
285
}
554
+ uint16_t payload_size; /* the payload length */
286
}
555
+ /* record the payload offset(the length that has been compared) */
287
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
--
288
--
588
2.7.4
289
2.7.4
589
290
590
291
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
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>
22
---
23
hmp-commands.hx | 4 ++--
24
net/slirp.c | 33 +++++++++++++++++++++++----------
25
2 files changed, 25 insertions(+), 12 deletions(-)
26
27
diff --git a/hmp-commands.hx b/hmp-commands.hx
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hmp-commands.hx
30
+++ b/hmp-commands.hx
31
@@ -XXX,XX +XXX,XX @@ ETEXI
32
{
33
.name = "hostfwd_add",
34
.args_type = "arg1:s,arg2:s?,arg3:s?",
35
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
36
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
37
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
38
.cmd = hmp_hostfwd_add,
39
},
40
@@ -XXX,XX +XXX,XX @@ ETEXI
41
{
42
.name = "hostfwd_remove",
43
.args_type = "arg1:s,arg2:s?,arg3:s?",
44
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
45
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport",
46
.help = "remove host-to-guest TCP or UDP redirection",
47
.cmd = hmp_hostfwd_remove,
48
},
49
diff --git a/net/slirp.c b/net/slirp.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/net/slirp.c
52
+++ b/net/slirp.c
53
@@ -XXX,XX +XXX,XX @@ error:
54
return -1;
55
}
56
57
-static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
58
- const char *stack)
59
+static SlirpState *slirp_lookup(Monitor *mon, const char *hub_id,
60
+ const char *name)
61
{
62
-
63
- if (vlan) {
64
+ if (name) {
65
NetClientState *nc;
66
- nc = net_hub_find_client_by_name(strtol(vlan, NULL, 0), stack);
67
- if (!nc) {
68
- monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
69
- return NULL;
70
+ if (hub_id) {
71
+ nc = net_hub_find_client_by_name(strtol(hub_id, NULL, 0), name);
72
+ if (!nc) {
73
+ monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
74
+ return NULL;
75
+ }
76
+ } else {
77
+ nc = qemu_find_netdev(name);
78
+ if (!nc) {
79
+ monitor_printf(mon, "unrecognized netdev id '%s'\n", name);
80
+ return NULL;
81
+ }
82
}
83
if (strcmp(nc->model, "user")) {
84
monitor_printf(mon, "invalid device specified\n");
85
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
86
const char *arg2 = qdict_get_try_str(qdict, "arg2");
87
const char *arg3 = qdict_get_try_str(qdict, "arg3");
88
89
- if (arg2) {
90
+ if (arg3) {
91
s = slirp_lookup(mon, arg1, arg2);
92
src_str = arg3;
93
+ } else if (arg2) {
94
+ s = slirp_lookup(mon, NULL, arg1);
95
+ src_str = arg2;
96
} else {
97
s = slirp_lookup(mon, NULL, NULL);
98
src_str = arg1;
99
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
100
const char *arg2 = qdict_get_try_str(qdict, "arg2");
101
const char *arg3 = qdict_get_try_str(qdict, "arg3");
102
103
- if (arg2) {
104
+ if (arg3) {
105
s = slirp_lookup(mon, arg1, arg2);
106
redir_str = arg3;
107
+ } else if (arg2) {
108
+ s = slirp_lookup(mon, NULL, arg1);
109
+ redir_str = arg2;
110
} else {
111
s = slirp_lookup(mon, NULL, NULL);
112
redir_str = arg1;
113
--
114
2.7.4
115
116
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
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>
8
---
9
qemu-options.hx | 4 ++--
10
1 file changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/qemu-options.hx b/qemu-options.hx
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qemu-options.hx
15
+++ b/qemu-options.hx
16
@@ -XXX,XX +XXX,XX @@ qemu-system-i386 linux.img -net nic -net tap
17
#launch a QEMU instance with two NICs, each one connected
18
#to a TAP device
19
qemu-system-i386 linux.img \
20
- -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
21
- -net nic,vlan=1 -net tap,vlan=1,ifname=tap1
22
+ -netdev tap,id=nd0,ifname=tap0 -device e1000,netdev=nd0 \
23
+ -netdev tap,id=nd1,ifname=tap1 -device rtl8139,netdev=nd1
24
@end example
25
26
@example
27
--
28
2.7.4
29
30
diff view generated by jsdifflib