1
The following changes since commit 6632f6ff96f0537fc34cdc00c760656fc62e23c5:
1
The following changes since commit 13356edb87506c148b163b8c7eb0695647d00c2a:
2
2
3
Merge remote-tracking branch 'remotes/famz/tags/block-and-testing-pull-request' into staging (2017-07-17 11:46:36 +0100)
3
Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2023-01-24 09:45:33 +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 189ae6bb5ce1f5a322f8691d00fe942ba43dd601:
9
for you to fetch changes up to 2bd492bca521ee8594f1d5db8dc9aac126fc4f85:
10
10
11
virtio-net: fix offload ctrl endian (2017-07-17 20:13:56 +0800)
11
vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check (2023-02-02 14:16:48 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
- fix virtio-net ctrl offload endian
15
----------------------------------------------------------------
16
- vnet header support for variou COLO netfilters and compare thread
16
Christian Svensson (1):
17
net: Increase L2TPv3 buffer to fit jumboframes
17
18
18
----------------------------------------------------------------
19
Eugenio Pérez (1):
19
Jason Wang (1):
20
vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check
20
virtio-net: fix offload ctrl endian
21
21
22
Michal Privoznik (1):
22
Fiona Ebner (1):
23
virtion-net: Prefer is_power_of_2()
23
hw/net/vmxnet3: allow VMXNET3_MAX_MTU itself as a value
24
24
25
Zhang Chen (12):
25
Joelle van Dyne (1):
26
net: Add vnet_hdr_len arguments in NetClientState
26
vmnet: stop recieving events when VM is stopped
27
net/net.c: Add vnet_hdr support in SocketReadState
28
net/filter-mirror.c: Introduce parameter for filter_send()
29
net/filter-mirror.c: Make filter mirror support vnet support.
30
net/filter-mirror.c: Add new option to enable vnet support for filter-redirector
31
net/colo.c: Make vnet_hdr_len as packet property
32
net/colo-compare.c: Introduce parameter for compare_chr_send()
33
net/colo-compare.c: Make colo-compare support vnet_hdr_len
34
net/colo.c: Add vnet packet parse feature in colo-proxy
35
net/colo-compare.c: Add vnet packet's tcp/udp/icmp compare
36
net/filter-rewriter.c: Make filter-rewriter support vnet_hdr_len
37
docs/colo-proxy.txt: Update colo-proxy usage of net driver with vnet_header
38
27
39
docs/colo-proxy.txt | 26 ++++++++++++++++
28
Laurent Vivier (2):
40
hw/net/virtio-net.c | 4 ++-
29
tests/qtest: netdev: test stream and dgram backends
41
include/net/net.h | 10 ++++--
30
net: stream: add a new option to automatically reconnect
42
net/colo-compare.c | 84 ++++++++++++++++++++++++++++++++++++++++++---------
31
43
net/colo.c | 9 +++---
32
Qiang Liu (2):
44
net/colo.h | 4 ++-
33
hw/net/lan9118: log [read|write]b when mode_16bit is enabled rather than abort
45
net/filter-mirror.c | 75 +++++++++++++++++++++++++++++++++++++++++----
34
hw/net/can/xlnx-zynqmp-can: fix assertion failures in transfer_fifo()
46
net/filter-rewriter.c | 37 ++++++++++++++++++++++-
35
47
net/net.c | 37 ++++++++++++++++++++---
36
Thomas Huth (3):
48
net/socket.c | 8 ++---
37
net: Move the code to collect available NIC models to a separate function
49
qemu-options.hx | 19 ++++++------
38
net: Restore printing of the help text with "-nic help"
50
11 files changed, 265 insertions(+), 48 deletions(-)
39
net: Replace "Supported NIC models" with "Available NIC models"
40
41
hw/net/can/xlnx-zynqmp-can.c | 9 +-
42
hw/net/lan9118.c | 17 +-
43
hw/net/vmxnet3.c | 2 +-
44
hw/pci/pci.c | 29 +--
45
include/net/net.h | 14 ++
46
net/l2tpv3.c | 2 +-
47
net/net.c | 50 +++-
48
net/stream.c | 53 ++++-
49
net/vhost-vdpa.c | 2 +-
50
net/vmnet-common.m | 48 +++-
51
net/vmnet_int.h | 2 +
52
qapi/net.json | 7 +-
53
qemu-options.hx | 6 +-
54
tests/qtest/meson.build | 2 +
55
tests/qtest/netdev-socket.c | 549 +++++++++++++++++++++++++++++++++++++++++++
56
15 files changed, 730 insertions(+), 62 deletions(-)
57
create mode 100644 tests/qtest/netdev-socket.c
51
58
52
59
60
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
We add a flag to decide whether net_fill_rstate() need read
3
The code that collects the available NIC models is not really specific
4
the vnet_hdr_len or not.
4
to PCI anymore and will be required in the next patch, too, so let's
5
move this into a new separate function in net.c instead.
5
6
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Suggested-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
9
---
10
include/net/net.h | 9 +++++++--
10
hw/pci/pci.c | 29 +----------------------------
11
net/colo-compare.c | 4 ++--
11
include/net/net.h | 14 ++++++++++++++
12
net/filter-mirror.c | 2 +-
12
net/net.c | 34 ++++++++++++++++++++++++++++++++++
13
net/net.c | 36 ++++++++++++++++++++++++++++++++----
13
3 files changed, 49 insertions(+), 28 deletions(-)
14
net/socket.c | 8 ++++----
15
5 files changed, 46 insertions(+), 13 deletions(-)
16
14
15
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/pci/pci.c
18
+++ b/hw/pci/pci.c
19
@@ -XXX,XX +XXX,XX @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
20
const char *default_devaddr)
21
{
22
const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
23
- GSList *list;
24
GPtrArray *pci_nic_models;
25
PCIBus *bus;
26
PCIDevice *pci_dev;
27
@@ -XXX,XX +XXX,XX @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
28
nd->model = g_strdup("virtio-net-pci");
29
}
30
31
- list = object_class_get_list_sorted(TYPE_PCI_DEVICE, false);
32
- pci_nic_models = g_ptr_array_new();
33
- while (list) {
34
- DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
35
- TYPE_DEVICE);
36
- GSList *next;
37
- if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
38
- dc->user_creatable) {
39
- const char *name = object_class_get_name(list->data);
40
- /*
41
- * A network device might also be something else than a NIC, see
42
- * e.g. the "rocker" device. Thus we have to look for the "netdev"
43
- * property, too. Unfortunately, some devices like virtio-net only
44
- * create this property during instance_init, so we have to create
45
- * a temporary instance here to be able to check it.
46
- */
47
- Object *obj = object_new_with_class(OBJECT_CLASS(dc));
48
- if (object_property_find(obj, "netdev")) {
49
- g_ptr_array_add(pci_nic_models, (gpointer)name);
50
- }
51
- object_unref(obj);
52
- }
53
- next = list->next;
54
- g_slist_free_1(list);
55
- list = next;
56
- }
57
- g_ptr_array_add(pci_nic_models, NULL);
58
+ pci_nic_models = qemu_get_nic_models(TYPE_PCI_DEVICE);
59
60
if (qemu_show_nic_models(nd->model, (const char **)pci_nic_models->pdata)) {
61
exit(0);
17
diff --git a/include/net/net.h b/include/net/net.h
62
diff --git a/include/net/net.h b/include/net/net.h
18
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
19
--- a/include/net/net.h
64
--- a/include/net/net.h
20
+++ b/include/net/net.h
65
+++ b/include/net/net.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct NICState {
66
@@ -XXX,XX +XXX,XX @@ void net_socket_rs_init(SocketReadState *rs,
22
} NICState;
67
bool vnet_hdr);
23
68
NetClientState *qemu_get_peer(NetClientState *nc, int queue_index);
24
struct SocketReadState {
69
25
- int state; /* 0 = getting length, 1 = getting data */
70
+/**
26
+ /* 0 = getting length, 1 = getting vnet header length, 2 = getting data */
71
+ * qemu_get_nic_models:
27
+ int state;
72
+ * @device_type: Defines which devices should be taken into consideration
28
+ /* This flag decide whether to read the vnet_hdr_len field */
73
+ * (e.g. TYPE_DEVICE for all devices, or TYPE_PCI_DEVICE for PCI)
29
+ bool vnet_hdr;
74
+ *
30
uint32_t index;
75
+ * Get an array of pointers to names of NIC devices that are available in
31
uint32_t packet_len;
76
+ * the QEMU binary. The array is terminated with a NULL pointer entry.
32
+ uint32_t vnet_hdr_len;
77
+ * The caller is responsible for freeing the memory when it is not required
33
uint8_t buf[NET_BUFSIZE];
78
+ * anymore, e.g. with g_ptr_array_free(..., true).
34
SocketReadStateFinalize *finalize;
79
+ *
35
};
80
+ * Returns: Pointer to the array that contains the pointers to the names.
36
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
81
+ */
37
void print_net_client(Monitor *mon, NetClientState *nc);
82
+GPtrArray *qemu_get_nic_models(const char *device_type);
38
void hmp_info_network(Monitor *mon, const QDict *qdict);
83
+
39
void net_socket_rs_init(SocketReadState *rs,
40
- SocketReadStateFinalize *finalize);
41
+ SocketReadStateFinalize *finalize,
42
+ bool vnet_hdr);
43
44
/* NIC info */
84
/* NIC info */
45
85
46
diff --git a/net/colo-compare.c b/net/colo-compare.c
86
#define MAX_NICS 8
47
index XXXXXXX..XXXXXXX 100644
48
--- a/net/colo-compare.c
49
+++ b/net/colo-compare.c
50
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
51
return;
52
}
53
54
- net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize);
55
- net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
56
+ net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, false);
57
+ net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, false);
58
59
g_queue_init(&s->conn_list);
60
61
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/net/filter-mirror.c
64
+++ b/net/filter-mirror.c
65
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
66
}
67
}
68
69
- net_socket_rs_init(&s->rs, redirector_rs_finalize);
70
+ net_socket_rs_init(&s->rs, redirector_rs_finalize, false);
71
72
if (s->indev) {
73
chr = qemu_chr_find(s->indev);
74
diff --git a/net/net.c b/net/net.c
87
diff --git a/net/net.c b/net/net.c
75
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
76
--- a/net/net.c
89
--- a/net/net.c
77
+++ b/net/net.c
90
+++ b/net/net.c
78
@@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_net_opts = {
91
@@ -XXX,XX +XXX,XX @@ static int nic_get_free_idx(void)
79
};
92
return -1;
80
93
}
81
void net_socket_rs_init(SocketReadState *rs,
94
82
- SocketReadStateFinalize *finalize)
95
+GPtrArray *qemu_get_nic_models(const char *device_type)
83
+ SocketReadStateFinalize *finalize,
96
+{
84
+ bool vnet_hdr)
97
+ GPtrArray *nic_models = g_ptr_array_new();
98
+ GSList *list = object_class_get_list_sorted(device_type, false);
99
+
100
+ while (list) {
101
+ DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
102
+ TYPE_DEVICE);
103
+ GSList *next;
104
+ if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
105
+ dc->user_creatable) {
106
+ const char *name = object_class_get_name(list->data);
107
+ /*
108
+ * A network device might also be something else than a NIC, see
109
+ * e.g. the "rocker" device. Thus we have to look for the "netdev"
110
+ * property, too. Unfortunately, some devices like virtio-net only
111
+ * create this property during instance_init, so we have to create
112
+ * a temporary instance here to be able to check it.
113
+ */
114
+ Object *obj = object_new_with_class(OBJECT_CLASS(dc));
115
+ if (object_property_find(obj, "netdev")) {
116
+ g_ptr_array_add(nic_models, (gpointer)name);
117
+ }
118
+ object_unref(obj);
119
+ }
120
+ next = list->next;
121
+ g_slist_free_1(list);
122
+ list = next;
123
+ }
124
+ g_ptr_array_add(nic_models, NULL);
125
+
126
+ return nic_models;
127
+}
128
+
129
int qemu_show_nic_models(const char *arg, const char *const *models)
85
{
130
{
86
rs->state = 0;
131
int i;
87
+ rs->vnet_hdr = vnet_hdr;
88
rs->index = 0;
89
rs->packet_len = 0;
90
+ rs->vnet_hdr_len = 0;
91
memset(rs->buf, 0, sizeof(rs->buf));
92
rs->finalize = finalize;
93
}
94
@@ -XXX,XX +XXX,XX @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
95
unsigned int l;
96
97
while (size > 0) {
98
- /* reassemble a packet from the network */
99
- switch (rs->state) { /* 0 = getting length, 1 = getting data */
100
+ /* Reassemble a packet from the network.
101
+ * 0 = getting length.
102
+ * 1 = getting vnet header length.
103
+ * 2 = getting data.
104
+ */
105
+ switch (rs->state) {
106
case 0:
107
l = 4 - rs->index;
108
if (l > size) {
109
@@ -XXX,XX +XXX,XX @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
110
/* got length */
111
rs->packet_len = ntohl(*(uint32_t *)rs->buf);
112
rs->index = 0;
113
- rs->state = 1;
114
+ if (rs->vnet_hdr) {
115
+ rs->state = 1;
116
+ } else {
117
+ rs->state = 2;
118
+ rs->vnet_hdr_len = 0;
119
+ }
120
}
121
break;
122
case 1:
123
+ l = 4 - rs->index;
124
+ if (l > size) {
125
+ l = size;
126
+ }
127
+ memcpy(rs->buf + rs->index, buf, l);
128
+ buf += l;
129
+ size -= l;
130
+ rs->index += l;
131
+ if (rs->index == 4) {
132
+ /* got vnet header length */
133
+ rs->vnet_hdr_len = ntohl(*(uint32_t *)rs->buf);
134
+ rs->index = 0;
135
+ rs->state = 2;
136
+ }
137
+ break;
138
+ case 2:
139
l = rs->packet_len - rs->index;
140
if (l > size) {
141
l = size;
142
diff --git a/net/socket.c b/net/socket.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/net/socket.c
145
+++ b/net/socket.c
146
@@ -XXX,XX +XXX,XX @@ static void net_socket_send(void *opaque)
147
closesocket(s->fd);
148
149
s->fd = -1;
150
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
151
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
152
s->nc.link_down = true;
153
memset(s->nc.info_str, 0, sizeof(s->nc.info_str));
154
155
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
156
s->fd = fd;
157
s->listen_fd = -1;
158
s->send_fn = net_socket_send_dgram;
159
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
160
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
161
net_socket_read_poll(s, true);
162
163
/* mcast: save bound address as dst */
164
@@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
165
166
s->fd = fd;
167
s->listen_fd = -1;
168
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
169
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
170
171
/* Disable Nagle algorithm on TCP sockets to reduce latency */
172
socket_set_nodelay(fd);
173
@@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer,
174
s->fd = -1;
175
s->listen_fd = fd;
176
s->nc.link_down = true;
177
- net_socket_rs_init(&s->rs, net_socket_rs_finalize);
178
+ net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
179
180
qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
181
return 0;
182
--
132
--
183
2.7.4
133
2.7.4
184
185
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
COLO-Proxy just focus on packet payload, so we skip vnet header.
3
Running QEMU with "-nic help" used to work in QEMU 5.2 and earlier versions
4
(it showed the available netdev backends), but this feature got broken during
5
some refactoring in version 6.0. Let's restore the old behavior, and while
6
we're at it, let's also print the available NIC models here now since this
7
option can be used to configure both, netdev backend and model in one go.
4
8
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
9
Fixes: ad6f932fe8 ("net: do not exit on "netdev_add help" monitor command")
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
12
---
8
net/colo-compare.c | 8 ++++++--
13
net/net.c | 14 ++++++++++++--
9
1 file changed, 6 insertions(+), 2 deletions(-)
14
1 file changed, 12 insertions(+), 2 deletions(-)
10
15
11
diff --git a/net/colo-compare.c b/net/colo-compare.c
16
diff --git a/net/net.c b/net/net.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo-compare.c
18
--- a/net/net.c
14
+++ b/net/colo-compare.c
19
+++ b/net/net.c
15
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
20
@@ -XXX,XX +XXX,XX @@ static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp)
16
sec_ip_src, sec_ip_dst);
21
const char *type;
22
23
type = qemu_opt_get(opts, "type");
24
- if (type && g_str_equal(type, "none")) {
25
- return 0; /* Nothing to do, default_net is cleared in vl.c */
26
+ if (type) {
27
+ if (g_str_equal(type, "none")) {
28
+ return 0; /* Nothing to do, default_net is cleared in vl.c */
29
+ }
30
+ if (is_help_option(type)) {
31
+ GPtrArray *nic_models = qemu_get_nic_models(TYPE_DEVICE);
32
+ show_netdevs();
33
+ printf("\n");
34
+ qemu_show_nic_models(type, (const char **)nic_models->pdata);
35
+ g_ptr_array_free(nic_models, true);
36
+ exit(0);
37
+ }
17
}
38
}
18
39
19
+ offset = ppkt->vnet_hdr_len + offset;
40
idx = nic_get_free_idx();
20
+
21
if (ppkt->size == spkt->size) {
22
- return memcmp(ppkt->data + offset, spkt->data + offset,
23
+ return memcmp(ppkt->data + offset,
24
+ spkt->data + offset,
25
spkt->size - offset);
26
} else {
27
trace_colo_compare_main("Net packet size are not the same");
28
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
29
*/
30
if (ptcp->th_off > 5) {
31
ptrdiff_t tcp_offset;
32
+
33
tcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
34
- + (ptcp->th_off * 4);
35
+ + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
36
res = colo_packet_compare_common(ppkt, spkt, tcp_offset);
37
} else if (ptcp->th_sum == stcp->th_sum) {
38
res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
39
--
41
--
40
2.7.4
42
2.7.4
41
42
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Add vnet_hdr_len arguments in NetClientState
3
Just because a NIC model is compiled into the QEMU binary does not
4
that make other module get real vnet_hdr_len easily.
4
necessary mean that it can be used with each and every machine.
5
So let's rather talk about "available" models instead of "supported"
6
models, just to avoid confusion.
5
7
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
8
Reviewed-by: Claudio Fontana <cfontana@suse.de>
9
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
11
---
9
include/net/net.h | 1 +
12
net/net.c | 2 +-
10
net/net.c | 1 +
13
1 file changed, 1 insertion(+), 1 deletion(-)
11
2 files changed, 2 insertions(+)
12
14
13
diff --git a/include/net/net.h b/include/net/net.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/net/net.h
16
+++ b/include/net/net.h
17
@@ -XXX,XX +XXX,XX @@ struct NetClientState {
18
unsigned int queue_index;
19
unsigned rxfilter_notify_enabled:1;
20
int vring_enable;
21
+ int vnet_hdr_len;
22
QTAILQ_HEAD(NetFilterHead, NetFilterState) filters;
23
};
24
25
diff --git a/net/net.c b/net/net.c
15
diff --git a/net/net.c b/net/net.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/net/net.c
17
--- a/net/net.c
28
+++ b/net/net.c
18
+++ b/net/net.c
29
@@ -XXX,XX +XXX,XX @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
19
@@ -XXX,XX +XXX,XX @@ int qemu_show_nic_models(const char *arg, const char *const *models)
30
return;
20
return 0;
31
}
21
}
32
22
33
+ nc->vnet_hdr_len = len;
23
- printf("Supported NIC models:\n");
34
nc->info->set_vnet_hdr_len(nc, len);
24
+ printf("Available NIC models:\n");
35
}
25
for (i = 0 ; models[i]; i++) {
36
26
printf("%s\n", models[i]);
27
}
37
--
28
--
38
2.7.4
29
2.7.4
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
This patch change the filter_send() parameter from CharBackend to MirrorState,
4
we can get more information like vnet_hdr(We use it to support packet with vnet_header).
5
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
net/filter-mirror.c | 10 +++++-----
10
1 file changed, 5 insertions(+), 5 deletions(-)
11
12
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/net/filter-mirror.c
15
+++ b/net/filter-mirror.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorState {
17
SocketReadState rs;
18
} MirrorState;
19
20
-static int filter_send(CharBackend *chr_out,
21
+static int filter_send(MirrorState *s,
22
const struct iovec *iov,
23
int iovcnt)
24
{
25
@@ -XXX,XX +XXX,XX @@ static int filter_send(CharBackend *chr_out,
26
}
27
28
len = htonl(size);
29
- ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)&len, sizeof(len));
30
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
31
if (ret != sizeof(len)) {
32
goto err;
33
}
34
35
buf = g_malloc(size);
36
iov_to_buf(iov, iovcnt, 0, buf, size);
37
- ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)buf, size);
38
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
39
g_free(buf);
40
if (ret != size) {
41
goto err;
42
@@ -XXX,XX +XXX,XX @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
43
MirrorState *s = FILTER_MIRROR(nf);
44
int ret;
45
46
- ret = filter_send(&s->chr_out, iov, iovcnt);
47
+ ret = filter_send(s, iov, iovcnt);
48
if (ret) {
49
error_report("filter mirror send failed(%s)", strerror(-ret));
50
}
51
@@ -XXX,XX +XXX,XX @@ static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
52
int ret;
53
54
if (qemu_chr_fe_backend_connected(&s->chr_out)) {
55
- ret = filter_send(&s->chr_out, iov, iovcnt);
56
+ ret = filter_send(s, iov, iovcnt);
57
if (ret) {
58
error_report("filter redirector send failed(%s)", strerror(-ret));
59
}
60
--
61
2.7.4
62
63
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
We add the vnet_hdr_support option for filter-mirror, default is disabled.
4
If you use virtio-net-pci or other driver needs vnet_hdr, please enable it.
5
You can use it for example:
6
-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support
7
8
If it has vnet_hdr_support flag, we will change the sending packet format from
9
struct {int size; const uint8_t buf[];} to {int size; int vnet_hdr_len; const uint8_t buf[];}.
10
make other module(like colo-compare) know how to parse net packet correctly.
11
12
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
15
net/filter-mirror.c | 42 +++++++++++++++++++++++++++++++++++++++++-
16
qemu-options.hx | 5 ++---
17
2 files changed, 43 insertions(+), 4 deletions(-)
18
19
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/net/filter-mirror.c
22
+++ b/net/filter-mirror.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorState {
24
CharBackend chr_in;
25
CharBackend chr_out;
26
SocketReadState rs;
27
+ bool vnet_hdr;
28
} MirrorState;
29
30
static int filter_send(MirrorState *s,
31
const struct iovec *iov,
32
int iovcnt)
33
{
34
+ NetFilterState *nf = NETFILTER(s);
35
int ret = 0;
36
ssize_t size = 0;
37
uint32_t len = 0;
38
@@ -XXX,XX +XXX,XX @@ static int filter_send(MirrorState *s,
39
goto err;
40
}
41
42
+ if (s->vnet_hdr) {
43
+ /*
44
+ * If vnet_hdr = on, we send vnet header len to make other
45
+ * module(like colo-compare) know how to parse net
46
+ * packet correctly.
47
+ */
48
+ ssize_t vnet_hdr_len;
49
+
50
+ vnet_hdr_len = nf->netdev->vnet_hdr_len;
51
+
52
+ len = htonl(vnet_hdr_len);
53
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
54
+ if (ret != sizeof(len)) {
55
+ goto err;
56
+ }
57
+ }
58
+
59
buf = g_malloc(size);
60
iov_to_buf(iov, iovcnt, 0, buf, size);
61
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
62
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
63
}
64
}
65
66
- net_socket_rs_init(&s->rs, redirector_rs_finalize, false);
67
+ net_socket_rs_init(&s->rs, redirector_rs_finalize, s->vnet_hdr);
68
69
if (s->indev) {
70
chr = qemu_chr_find(s->indev);
71
@@ -XXX,XX +XXX,XX @@ static void filter_mirror_set_outdev(Object *obj,
72
}
73
}
74
75
+static bool filter_mirror_get_vnet_hdr(Object *obj, Error **errp)
76
+{
77
+ MirrorState *s = FILTER_MIRROR(obj);
78
+
79
+ return s->vnet_hdr;
80
+}
81
+
82
+static void filter_mirror_set_vnet_hdr(Object *obj, bool value, Error **errp)
83
+{
84
+ MirrorState *s = FILTER_MIRROR(obj);
85
+
86
+ s->vnet_hdr = value;
87
+}
88
+
89
static char *filter_redirector_get_outdev(Object *obj, Error **errp)
90
{
91
MirrorState *s = FILTER_REDIRECTOR(obj);
92
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_set_outdev(Object *obj,
93
94
static void filter_mirror_init(Object *obj)
95
{
96
+ MirrorState *s = FILTER_MIRROR(obj);
97
+
98
object_property_add_str(obj, "outdev", filter_mirror_get_outdev,
99
filter_mirror_set_outdev, NULL);
100
+
101
+ s->vnet_hdr = false;
102
+ object_property_add_bool(obj, "vnet_hdr_support",
103
+ filter_mirror_get_vnet_hdr,
104
+ filter_mirror_set_vnet_hdr, NULL);
105
}
106
107
static void filter_redirector_init(Object *obj)
108
diff --git a/qemu-options.hx b/qemu-options.hx
109
index XXXXXXX..XXXXXXX 100644
110
--- a/qemu-options.hx
111
+++ b/qemu-options.hx
112
@@ -XXX,XX +XXX,XX @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
113
@option{tx}: the filter is attached to the transmit queue of the netdev,
114
where it will receive packets sent by the netdev.
115
116
-@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
117
+@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support]
118
119
-filter-mirror on netdev @var{netdevid},mirror net packet to chardev
120
-@var{chardevid}
121
+filter-mirror on netdev @var{netdevid},mirror net packet to chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror will mirror packet with vnet_hdr_len.
122
123
@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},
124
outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
125
--
126
2.7.4
127
128
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Qiang Liu <cyruscyliu@gmail.com>
2
2
3
We add the vnet_hdr_support option for colo-compare, default is disabled.
3
This patch replaces hw_error to guest error log for [read|write]b
4
If you use virtio-net-pci or other driver needs vnet_hdr, please enable it.
4
accesses when mode_16bit is enabled. This avoids aborting qemu.
5
You can use it for example:
6
-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support
7
5
8
COLO-compare can get vnet header length from filter,
6
Fixes: 1248f8d4cbc3 ("hw/lan9118: Add basic 16-bit mode support.")
9
Add vnet_hdr_len to struct packet and output packet with
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1433
10
the vnet_hdr_len.
8
Reported-by: Qiang Liu <cyruscyliu@gmail.com>
11
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
10
Signed-off-by: Qiang Liu <cyruscyliu@gmail.com>
11
Suggested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
13
---
15
net/colo-compare.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------
14
hw/net/lan9118.c | 17 ++++++++---------
16
qemu-options.hx | 4 ++--
15
1 file changed, 8 insertions(+), 9 deletions(-)
17
2 files changed, 55 insertions(+), 9 deletions(-)
18
16
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
17
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
19
--- a/hw/net/lan9118.c
22
+++ b/net/colo-compare.c
20
+++ b/hw/net/lan9118.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
21
@@ -XXX,XX +XXX,XX @@
24
CharBackend chr_out;
22
#include "migration/vmstate.h"
25
SocketReadState pri_rs;
23
#include "net/net.h"
26
SocketReadState sec_rs;
24
#include "net/eth.h"
27
+ bool vnet_hdr;
25
-#include "hw/hw.h"
28
26
#include "hw/irq.h"
29
/* connection list: the connections belonged to this NIC could be found
27
#include "hw/net/lan9118.h"
30
* in this list.
28
#include "hw/ptimer.h"
31
@@ -XXX,XX +XXX,XX @@ enum {
29
@@ -XXX,XX +XXX,XX @@
32
30
#ifdef DEBUG_LAN9118
33
static int compare_chr_send(CompareState *s,
31
#define DPRINTF(fmt, ...) \
34
const uint8_t *buf,
32
do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
35
- uint32_t size);
33
-#define BADF(fmt, ...) \
36
+ uint32_t size,
34
-do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
37
+ uint32_t vnet_hdr_len);
35
#else
38
36
#define DPRINTF(fmt, ...) do {} while(0)
39
static gint seq_sorter(Packet *a, Packet *b, gpointer data)
37
-#define BADF(fmt, ...) \
40
{
38
-do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
41
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
39
#endif
42
}
40
43
41
/* The tx and rx fifo ports are a range of aliased 32-bit registers */
44
if (result) {
42
@@ -XXX,XX +XXX,XX @@ static uint32_t do_phy_read(lan9118_state *s, int reg)
45
- ret = compare_chr_send(s, pkt->data, pkt->size);
43
case 30: /* Interrupt mask */
46
+ ret = compare_chr_send(s,
44
return s->phy_int_mask;
47
+ pkt->data,
45
default:
48
+ pkt->size,
46
- BADF("PHY read reg %d\n", reg);
49
+ pkt->vnet_hdr_len);
47
+ qemu_log_mask(LOG_GUEST_ERROR,
50
if (ret < 0) {
48
+ "do_phy_read: PHY read reg %d\n", reg);
51
error_report("colo_send_primary_packet failed");
49
return 0;
52
}
53
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
54
55
static int compare_chr_send(CompareState *s,
56
const uint8_t *buf,
57
- uint32_t size)
58
+ uint32_t size,
59
+ uint32_t vnet_hdr_len)
60
{
61
int ret = 0;
62
uint32_t len = htonl(size);
63
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s,
64
goto err;
65
}
50
}
66
67
+ if (s->vnet_hdr) {
68
+ /*
69
+ * We send vnet header len make other module(like filter-redirector)
70
+ * know how to parse net packet correctly.
71
+ */
72
+ len = htonl(vnet_hdr_len);
73
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
74
+ if (ret != sizeof(len)) {
75
+ goto err;
76
+ }
77
+ }
78
+
79
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
80
if (ret != size) {
81
goto err;
82
@@ -XXX,XX +XXX,XX @@ static void compare_set_outdev(Object *obj, const char *value, Error **errp)
83
s->outdev = g_strdup(value);
84
}
51
}
85
52
@@ -XXX,XX +XXX,XX @@ static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
86
+static bool compare_get_vnet_hdr(Object *obj, Error **errp)
53
phy_update_irq(s);
87
+{
54
break;
88
+ CompareState *s = COLO_COMPARE(obj);
55
default:
89
+
56
- BADF("PHY write reg %d = 0x%04x\n", reg, val);
90
+ return s->vnet_hdr;
57
+ qemu_log_mask(LOG_GUEST_ERROR,
91
+}
58
+ "do_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
92
+
59
}
93
+static void compare_set_vnet_hdr(Object *obj,
60
}
94
+ bool value,
61
95
+ Error **errp)
62
@@ -XXX,XX +XXX,XX @@ static void lan9118_16bit_mode_write(void *opaque, hwaddr offset,
96
+{
97
+ CompareState *s = COLO_COMPARE(obj);
98
+
99
+ s->vnet_hdr = value;
100
+}
101
+
102
static void compare_pri_rs_finalize(SocketReadState *pri_rs)
103
{
104
CompareState *s = container_of(pri_rs, CompareState, pri_rs);
105
106
if (packet_enqueue(s, PRIMARY_IN)) {
107
trace_colo_compare_main("primary: unsupported packet in");
108
- compare_chr_send(s, pri_rs->buf, pri_rs->packet_len);
109
+ compare_chr_send(s,
110
+ pri_rs->buf,
111
+ pri_rs->packet_len,
112
+ pri_rs->vnet_hdr_len);
113
} else {
114
/* compare connection */
115
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
116
@@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
117
return;
63
return;
118
}
64
}
119
65
120
- net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, false);
66
- hw_error("lan9118_write: Bad size 0x%x\n", size);
121
- net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, false);
67
+ qemu_log_mask(LOG_GUEST_ERROR,
122
+ net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
68
+ "lan9118_16bit_mode_write: Bad size 0x%x\n", size);
123
+ net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr);
69
}
124
70
125
g_queue_init(&s->conn_list);
71
static uint64_t lan9118_readl(void *opaque, hwaddr offset,
126
72
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_16bit_mode_read(void *opaque, hwaddr offset,
127
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
73
return lan9118_readl(opaque, offset, size);
128
129
while (!g_queue_is_empty(&conn->primary_list)) {
130
pkt = g_queue_pop_head(&conn->primary_list);
131
- compare_chr_send(s, pkt->data, pkt->size);
132
+ compare_chr_send(s,
133
+ pkt->data,
134
+ pkt->size,
135
+ pkt->vnet_hdr_len);
136
packet_destroy(pkt, NULL);
137
}
74
}
138
while (!g_queue_is_empty(&conn->secondary_list)) {
75
139
@@ -XXX,XX +XXX,XX @@ static void colo_compare_class_init(ObjectClass *oc, void *data)
76
- hw_error("lan9118_read: Bad size 0x%x\n", size);
140
77
+ qemu_log_mask(LOG_GUEST_ERROR,
141
static void colo_compare_init(Object *obj)
78
+ "lan9118_16bit_mode_read: Bad size 0x%x\n", size);
142
{
79
return 0;
143
+ CompareState *s = COLO_COMPARE(obj);
144
+
145
object_property_add_str(obj, "primary_in",
146
compare_get_pri_indev, compare_set_pri_indev,
147
NULL);
148
@@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj)
149
object_property_add_str(obj, "outdev",
150
compare_get_outdev, compare_set_outdev,
151
NULL);
152
+
153
+ s->vnet_hdr = false;
154
+ object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
155
+ compare_set_vnet_hdr, NULL);
156
}
80
}
157
158
static void colo_compare_finalize(Object *obj)
159
diff --git a/qemu-options.hx b/qemu-options.hx
160
index XXXXXXX..XXXXXXX 100644
161
--- a/qemu-options.hx
162
+++ b/qemu-options.hx
163
@@ -XXX,XX +XXX,XX @@ Dump the network traffic on netdev @var{dev} to the file specified by
164
The file format is libpcap, so it can be analyzed with tools such as tcpdump
165
or Wireshark.
166
167
-@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},
168
-outdev=@var{chardevid}
169
+@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid}[,vnet_hdr_support]
170
171
Colo-compare gets packet from primary_in@var{chardevid} and secondary_in@var{chardevid}, than compare primary packet with
172
secondary packet. If the packets are same, we will output primary
173
packet to outdev@var{chardevid}, else we will notify colo-frame
174
do checkpoint and send primary packet to outdev@var{chardevid}.
175
+if it has the vnet_hdr_support flag, colo compare will send/recv packet with vnet_hdr_len.
176
177
we must use it with the help of filter-mirror and filter-redirector.
178
81
179
--
82
--
180
2.7.4
83
2.7.4
181
84
182
85
diff view generated by jsdifflib
1
Spec said offloads should be le64, so use virtio_ldq_p() to guarantee
1
From: Fiona Ebner <f.ebner@proxmox.com>
2
valid endian.
3
2
4
Fixes: 644c98587d4c ("virtio-net: dynamic network offloads configuration")
3
Currently, VMXNET3_MAX_MTU itself (being 9000) is not considered a
5
Cc: qemu-stable@nongnu.org
4
valid value for the MTU, but a guest running ESXi 7.0 might try to
6
Cc: Dmitry Fleytman <dfleytma@redhat.com>
5
set it and fail the assert [0].
6
7
In the Linux kernel, dev->max_mtu itself is a valid value for the MTU
8
and for the vmxnet3 driver it's 9000, so a guest running Linux will
9
also fail the assert when trying to set an MTU of 9000.
10
11
VMXNET3_MAX_MTU and s->mtu don't seem to be used in relation to buffer
12
allocations/accesses, so allowing the upper limit itself as a value
13
should be fine.
14
15
[0]: https://forum.proxmox.com/threads/114011/
16
17
Fixes: d05dcd94ae ("net: vmxnet3: validate configuration values during activate (CVE-2021-20203)")
18
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
19
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
20
---
9
hw/net/virtio-net.c | 2 ++
21
hw/net/vmxnet3.c | 2 +-
10
1 file changed, 2 insertions(+)
22
1 file changed, 1 insertion(+), 1 deletion(-)
11
23
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
24
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
13
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
26
--- a/hw/net/vmxnet3.c
15
+++ b/hw/net/virtio-net.c
27
+++ b/hw/net/vmxnet3.c
16
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
28
@@ -XXX,XX +XXX,XX @@ static void vmxnet3_activate_device(VMXNET3State *s)
17
if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) {
29
vmxnet3_setup_rx_filtering(s);
18
uint64_t supported_offloads;
30
/* Cache fields from shared memory */
19
31
s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
20
+ offloads = virtio_ldq_p(vdev, &offloads);
32
- assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu < VMXNET3_MAX_MTU);
21
+
33
+ assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu <= VMXNET3_MAX_MTU);
22
if (!n->has_vnet_hdr) {
34
VMW_CFPRN("MTU is %u", s->mtu);
23
return VIRTIO_NET_ERR;
35
24
}
36
s->max_rx_frags =
25
--
37
--
26
2.7.4
38
2.7.4
27
28
diff view generated by jsdifflib
1
From: Michal Privoznik <mprivozn@redhat.com>
1
From: Christian Svensson <blue@cmd.nu>
2
2
3
We have a function that checks if given number is power of two.
3
Increase the allocated buffer size to fit larger packets.
4
We should prefer it instead of expanding the check on our own.
4
Given that jumboframes can commonly be up to 9000 bytes the closest suitable
5
value seems to be 16 KiB.
5
6
6
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
7
Tested by running qemu towards a Linux L2TPv3 endpoint and pushing
8
jumboframe traffic through the interfaces.
9
10
Signed-off-by: Christian Svensson <blue@cmd.nu>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
12
---
9
hw/net/virtio-net.c | 2 +-
13
net/l2tpv3.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
11
15
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
16
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
18
--- a/net/l2tpv3.c
15
+++ b/hw/net/virtio-net.c
19
+++ b/net/l2tpv3.c
16
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
20
@@ -XXX,XX +XXX,XX @@
17
*/
21
*/
18
if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE ||
22
19
n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE ||
23
#define BUFFER_ALIGN sysconf(_SC_PAGESIZE)
20
- (n->net_conf.rx_queue_size & (n->net_conf.rx_queue_size - 1))) {
24
-#define BUFFER_SIZE 2048
21
+ !is_power_of_2(n->net_conf.rx_queue_size)) {
25
+#define BUFFER_SIZE 16384
22
error_setg(errp, "Invalid rx_queue_size (= %" PRIu16 "), "
26
#define IOVSIZE 2
23
"must be a power of 2 between %d and %d.",
27
#define MAX_L2TPV3_MSGCNT 64
24
n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE,
28
#define MAX_L2TPV3_IOVCNT (MAX_L2TPV3_MSGCNT * IOVSIZE)
25
--
29
--
26
2.7.4
30
2.7.4
27
28
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Joelle van Dyne <j@getutm.app>
2
2
3
This patch change the compare_chr_send() parameter from CharBackend to CompareState,
3
When the VM is stopped using the HMP command "stop", soon the handler will
4
we can get more information like vnet_hdr(We use it to support packet with vnet_header).
4
stop reading from the vmnet interface. This causes a flood of
5
`VMNET_INTERFACE_PACKETS_AVAILABLE` events to arrive and puts the host CPU
6
at 100%. We fix this by removing the event handler from vmnet when the VM
7
is no longer in a running state and restore it when we return to a running
8
state.
5
9
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
10
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
12
---
9
net/colo-compare.c | 14 +++++++-------
13
net/vmnet-common.m | 48 +++++++++++++++++++++++++++++++++++-------------
10
1 file changed, 7 insertions(+), 7 deletions(-)
14
net/vmnet_int.h | 2 ++
15
2 files changed, 37 insertions(+), 13 deletions(-)
11
16
12
diff --git a/net/colo-compare.c b/net/colo-compare.c
17
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/net/colo-compare.c
19
--- a/net/vmnet-common.m
15
+++ b/net/colo-compare.c
20
+++ b/net/vmnet-common.m
16
@@ -XXX,XX +XXX,XX @@ enum {
21
@@ -XXX,XX +XXX,XX @@
17
SECONDARY_IN,
22
#include "clients.h"
18
};
23
#include "qemu/error-report.h"
19
24
#include "qapi/error.h"
20
-static int compare_chr_send(CharBackend *out,
25
+#include "sysemu/runstate.h"
21
+static int compare_chr_send(CompareState *s,
26
22
const uint8_t *buf,
27
#include <vmnet/vmnet.h>
23
uint32_t size);
28
#include <dispatch/dispatch.h>
24
29
@@ -XXX,XX +XXX,XX @@ static void vmnet_bufs_init(VmnetState *s)
25
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
26
}
27
28
if (result) {
29
- ret = compare_chr_send(&s->chr_out, pkt->data, pkt->size);
30
+ ret = compare_chr_send(s, pkt->data, pkt->size);
31
if (ret < 0) {
32
error_report("colo_send_primary_packet failed");
33
}
34
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
35
}
30
}
36
}
31
}
37
32
38
-static int compare_chr_send(CharBackend *out,
33
+/**
39
+static int compare_chr_send(CompareState *s,
34
+ * Called on state change to un-register/re-register handlers
40
const uint8_t *buf,
35
+ */
41
uint32_t size)
36
+static void vmnet_vm_state_change_cb(void *opaque, bool running, RunState state)
42
{
37
+{
43
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CharBackend *out,
38
+ VmnetState *s = opaque;
44
return 0;
39
+
40
+ if (running) {
41
+ vmnet_interface_set_event_callback(
42
+ s->vmnet_if,
43
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
44
+ s->if_queue,
45
+ ^(interface_event_t event_id, xpc_object_t event) {
46
+ assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
47
+ /*
48
+ * This function is being called from a non qemu thread, so
49
+ * we only schedule a BH, and do the rest of the io completion
50
+ * handling from vmnet_send_bh() which runs in a qemu context.
51
+ */
52
+ qemu_bh_schedule(s->send_bh);
53
+ });
54
+ } else {
55
+ vmnet_interface_set_event_callback(
56
+ s->vmnet_if,
57
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
58
+ NULL,
59
+ NULL);
60
+ }
61
+}
62
63
int vmnet_if_create(NetClientState *nc,
64
xpc_object_t if_desc,
65
@@ -XXX,XX +XXX,XX @@ int vmnet_if_create(NetClientState *nc,
66
s->packets_send_current_pos = 0;
67
s->packets_send_end_pos = 0;
68
69
- vmnet_interface_set_event_callback(
70
- s->vmnet_if,
71
- VMNET_INTERFACE_PACKETS_AVAILABLE,
72
- s->if_queue,
73
- ^(interface_event_t event_id, xpc_object_t event) {
74
- assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
75
- /*
76
- * This function is being called from a non qemu thread, so
77
- * we only schedule a BH, and do the rest of the io completion
78
- * handling from vmnet_send_bh() which runs in a qemu context.
79
- */
80
- qemu_bh_schedule(s->send_bh);
81
- });
82
+ vmnet_vm_state_change_cb(s, 1, RUN_STATE_RUNNING);
83
+
84
+ s->change = qemu_add_vm_change_state_handler(vmnet_vm_state_change_cb, s);
85
86
return 0;
87
}
88
@@ -XXX,XX +XXX,XX @@ void vmnet_cleanup_common(NetClientState *nc)
89
return;
45
}
90
}
46
91
47
- ret = qemu_chr_fe_write_all(out, (uint8_t *)&len, sizeof(len));
92
+ vmnet_vm_state_change_cb(s, 0, RUN_STATE_SHUTDOWN);
48
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
93
+ qemu_del_vm_change_state_handler(s->change);
49
if (ret != sizeof(len)) {
94
if_stopped_sem = dispatch_semaphore_create(0);
50
goto err;
95
vmnet_stop_interface(
51
}
96
s->vmnet_if,
52
97
diff --git a/net/vmnet_int.h b/net/vmnet_int.h
53
- ret = qemu_chr_fe_write_all(out, (uint8_t *)buf, size);
98
index XXXXXXX..XXXXXXX 100644
54
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
99
--- a/net/vmnet_int.h
55
if (ret != size) {
100
+++ b/net/vmnet_int.h
56
goto err;
101
@@ -XXX,XX +XXX,XX @@ typedef struct VmnetState {
57
}
102
int packets_send_end_pos;
58
@@ -XXX,XX +XXX,XX @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
103
59
104
struct iovec iov_buf[VMNET_PACKETS_LIMIT];
60
if (packet_enqueue(s, PRIMARY_IN)) {
105
+
61
trace_colo_compare_main("primary: unsupported packet in");
106
+ VMChangeStateEntry *change;
62
- compare_chr_send(&s->chr_out, pri_rs->buf, pri_rs->packet_len);
107
} VmnetState;
63
+ compare_chr_send(s, pri_rs->buf, pri_rs->packet_len);
108
64
} else {
109
const char *vmnet_status_map_str(vmnet_return_t status);
65
/* compare connection */
66
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
67
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
68
69
while (!g_queue_is_empty(&conn->primary_list)) {
70
pkt = g_queue_pop_head(&conn->primary_list);
71
- compare_chr_send(&s->chr_out, pkt->data, pkt->size);
72
+ compare_chr_send(s, pkt->data, pkt->size);
73
packet_destroy(pkt, NULL);
74
}
75
while (!g_queue_is_empty(&conn->secondary_list)) {
76
--
110
--
77
2.7.4
111
2.7.4
78
79
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Qiang Liu <cyruscyliu@gmail.com>
2
2
3
We can use this property flush and send packet with vnet_hdr_len.
3
Check fifos before poping data from and pushing data into it.
4
4
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
5
Fixes: 98e5d7a2b726 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1425
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1427
8
Reported-by: Qiang Liu <cyruscyliu@gmail.com>
9
Signed-off-by: Qiang Liu <cyruscyliu@gmail.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
11
---
8
net/colo-compare.c | 8 ++++++--
12
hw/net/can/xlnx-zynqmp-can.c | 9 ++++++++-
9
net/colo.c | 3 ++-
13
1 file changed, 8 insertions(+), 1 deletion(-)
10
net/colo.h | 4 +++-
11
net/filter-rewriter.c | 2 +-
12
4 files changed, 12 insertions(+), 5 deletions(-)
13
14
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo-compare.c
17
--- a/hw/net/can/xlnx-zynqmp-can.c
17
+++ b/net/colo-compare.c
18
+++ b/hw/net/can/xlnx-zynqmp-can.c
18
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode)
19
@@ -XXX,XX +XXX,XX @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
19
Connection *conn;
20
21
if (mode == PRIMARY_IN) {
22
- pkt = packet_new(s->pri_rs.buf, s->pri_rs.packet_len);
23
+ pkt = packet_new(s->pri_rs.buf,
24
+ s->pri_rs.packet_len,
25
+ s->pri_rs.vnet_hdr_len);
26
} else {
27
- pkt = packet_new(s->sec_rs.buf, s->sec_rs.packet_len);
28
+ pkt = packet_new(s->sec_rs.buf,
29
+ s->sec_rs.packet_len,
30
+ s->sec_rs.vnet_hdr_len);
31
}
20
}
32
21
33
if (parse_packet_early(pkt)) {
22
while (!fifo32_is_empty(fifo)) {
34
diff --git a/net/colo.c b/net/colo.c
23
+ if (fifo32_num_used(fifo) < (4 * CAN_FRAME_SIZE)) {
35
index XXXXXXX..XXXXXXX 100644
24
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
36
--- a/net/colo.c
25
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: data left in the fifo is not"
37
+++ b/net/colo.c
26
+ " enough for transfer.\n", path);
38
@@ -XXX,XX +XXX,XX @@ void connection_destroy(void *opaque)
27
+ break;
39
g_slice_free(Connection, conn);
28
+ }
40
}
29
for (i = 0; i < CAN_FRAME_SIZE; i++) {
41
30
data[i] = fifo32_pop(fifo);
42
-Packet *packet_new(const void *data, int size)
31
}
43
+Packet *packet_new(const void *data, int size, int vnet_hdr_len)
32
@@ -XXX,XX +XXX,XX @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
44
{
33
* acknowledged. The XlnxZynqMPCAN core receives any message
45
Packet *pkt = g_slice_new(Packet);
34
* that it transmits.
46
35
*/
47
pkt->data = g_memdup(data, size);
36
- if (fifo32_is_full(&s->rx_fifo)) {
48
pkt->size = size;
37
+ if (fifo32_is_full(&s->rx_fifo) ||
49
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
38
+ (fifo32_num_free(&s->rx_fifo) < (4 * CAN_FRAME_SIZE))) {
50
+ pkt->vnet_hdr_len = vnet_hdr_len;
39
ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
51
40
} else {
52
return pkt;
41
for (i = 0; i < CAN_FRAME_SIZE; i++) {
53
}
54
diff --git a/net/colo.h b/net/colo.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/net/colo.h
57
+++ b/net/colo.h
58
@@ -XXX,XX +XXX,XX @@ typedef struct Packet {
59
int size;
60
/* Time of packet creation, in wall clock ms */
61
int64_t creation_ms;
62
+ /* Get vnet_hdr_len from filter */
63
+ uint32_t vnet_hdr_len;
64
} Packet;
65
66
typedef struct ConnectionKey {
67
@@ -XXX,XX +XXX,XX @@ Connection *connection_get(GHashTable *connection_track_table,
68
ConnectionKey *key,
69
GQueue *conn_list);
70
void connection_hashtable_reset(GHashTable *connection_track_table);
71
-Packet *packet_new(const void *data, int size);
72
+Packet *packet_new(const void *data, int size, int vnet_hdr_len);
73
void packet_destroy(void *opaque, void *user_data);
74
75
#endif /* QEMU_COLO_PROXY_H */
76
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/net/filter-rewriter.c
79
+++ b/net/filter-rewriter.c
80
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
81
char *buf = g_malloc0(size);
82
83
iov_to_buf(iov, iovcnt, 0, buf, size);
84
- pkt = packet_new(buf, size);
85
+ pkt = packet_new(buf, size, 0);
86
g_free(buf);
87
88
/*
89
--
42
--
90
2.7.4
43
2.7.4
91
92
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Laurent Vivier <lvivier@redhat.com>
2
2
3
We add the vnet_hdr_support option for filter-redirector, default is disabled.
3
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
4
If you use virtio-net-pci net driver or other driver needs vnet_hdr, please enable it.
4
Acked-by: Michael S. Tsirkin <mst@redhat.com>
5
Because colo-compare or other modules needs the vnet_hdr_len to parse
5
Acked-by: Thomas Huth <thuth@redhat.com>
6
packet, we add this new option send the len to others.
7
You can use it for example:
8
-object filter-redirector,id=r0,netdev=hn0,queue=tx,outdev=red0,vnet_hdr_support
9
10
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
7
---
13
net/filter-mirror.c | 23 +++++++++++++++++++++++
8
tests/qtest/meson.build | 2 +
14
qemu-options.hx | 6 +++---
9
tests/qtest/netdev-socket.c | 448 ++++++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 26 insertions(+), 3 deletions(-)
10
2 files changed, 450 insertions(+)
11
create mode 100644 tests/qtest/netdev-socket.c
16
12
17
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
13
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/net/filter-mirror.c
15
--- a/tests/qtest/meson.build
20
+++ b/net/filter-mirror.c
16
+++ b/tests/qtest/meson.build
21
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_set_outdev(Object *obj,
17
@@ -XXX,XX +XXX,XX @@ qtests_generic = [
22
s->outdev = g_strdup(value);
18
'test-hmp',
19
'qos-test',
20
'readconfig-test',
21
+ 'netdev-socket',
22
]
23
if config_host.has_key('CONFIG_MODULES')
24
qtests_generic += [ 'modules-test' ]
25
@@ -XXX,XX +XXX,XX @@ qtests = {
26
'tpm-tis-device-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'],
27
'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'],
28
'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
29
+ 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'),
23
}
30
}
24
31
25
+static bool filter_redirector_get_vnet_hdr(Object *obj, Error **errp)
32
gvnc = dependency('gvnc-1.0', required: false)
26
+{
33
diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
27
+ MirrorState *s = FILTER_REDIRECTOR(obj);
34
new file mode 100644
28
+
35
index XXXXXXX..XXXXXXX
29
+ return s->vnet_hdr;
36
--- /dev/null
30
+}
37
+++ b/tests/qtest/netdev-socket.c
31
+
38
@@ -XXX,XX +XXX,XX @@
32
+static void filter_redirector_set_vnet_hdr(Object *obj,
39
+/*
33
+ bool value,
40
+ * QTest testcase for netdev stream and dgram
34
+ Error **errp)
41
+ *
35
+{
42
+ * Copyright (c) 2022 Red Hat, Inc.
36
+ MirrorState *s = FILTER_REDIRECTOR(obj);
43
+ *
37
+
44
+ * SPDX-License-Identifier: GPL-2.0-or-later
38
+ s->vnet_hdr = value;
45
+ */
39
+}
46
+
40
+
47
+#include "qemu/osdep.h"
41
static void filter_mirror_init(Object *obj)
48
+#include "qemu/sockets.h"
42
{
49
+#include <glib/gstdio.h>
43
MirrorState *s = FILTER_MIRROR(obj);
50
+#include "../unit/socket-helpers.h"
44
@@ -XXX,XX +XXX,XX @@ static void filter_mirror_init(Object *obj)
51
+#include "libqtest.h"
45
52
+
46
static void filter_redirector_init(Object *obj)
53
+#define CONNECTION_TIMEOUT 5
47
{
54
+
48
+ MirrorState *s = FILTER_REDIRECTOR(obj);
55
+#define EXPECT_STATE(q, e, t) \
49
+
56
+do { \
50
object_property_add_str(obj, "indev", filter_redirector_get_indev,
57
+ char *resp = NULL; \
51
filter_redirector_set_indev, NULL);
58
+ g_test_timer_start(); \
52
object_property_add_str(obj, "outdev", filter_redirector_get_outdev,
59
+ do { \
53
filter_redirector_set_outdev, NULL);
60
+ g_free(resp); \
54
+
61
+ resp = qtest_hmp(q, "info network"); \
55
+ s->vnet_hdr = false;
62
+ if (t) { \
56
+ object_property_add_bool(obj, "vnet_hdr_support",
63
+ strrchr(resp, t)[0] = 0; \
57
+ filter_redirector_get_vnet_hdr,
64
+ } \
58
+ filter_redirector_set_vnet_hdr, NULL);
65
+ if (g_str_equal(resp, e)) { \
59
}
66
+ break; \
60
67
+ } \
61
static void filter_mirror_fini(Object *obj)
68
+ } while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \
62
diff --git a/qemu-options.hx b/qemu-options.hx
69
+ g_assert_cmpstr(resp, ==, e); \
63
index XXXXXXX..XXXXXXX 100644
70
+ g_free(resp); \
64
--- a/qemu-options.hx
71
+} while (0)
65
+++ b/qemu-options.hx
72
+
66
@@ -XXX,XX +XXX,XX @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
73
+static gchar *tmpdir;
67
74
+
68
filter-mirror on netdev @var{netdevid},mirror net packet to chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror will mirror packet with vnet_hdr_len.
75
+static int inet_get_free_port_socket_ipv4(int sock)
69
76
+{
70
-@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},
77
+ struct sockaddr_in addr;
71
-outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
78
+ socklen_t len;
72
+@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support]
79
+
73
80
+ memset(&addr, 0, sizeof(addr));
74
filter-redirector on netdev @var{netdevid},redirect filter's net packet to chardev
81
+ addr.sin_family = AF_INET;
75
-@var{chardevid},and redirect indev's packet to filter.
82
+ addr.sin_addr.s_addr = INADDR_ANY;
76
+@var{chardevid},and redirect indev's packet to filter.if it has the vnet_hdr_support flag,
83
+ addr.sin_port = 0;
77
+filter-redirector will redirect packet with vnet_hdr_len.
84
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
78
Create a filter-redirector we need to differ outdev id from indev id, id can not
85
+ return -1;
79
be the same. we can just use indev or outdev, but at least one of indev or outdev
86
+ }
80
need to be specified.
87
+
88
+ len = sizeof(addr);
89
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) {
90
+ return -1;
91
+ }
92
+
93
+ return ntohs(addr.sin_port);
94
+}
95
+
96
+static int inet_get_free_port_socket_ipv6(int sock)
97
+{
98
+ struct sockaddr_in6 addr;
99
+ socklen_t len;
100
+
101
+ memset(&addr, 0, sizeof(addr));
102
+ addr.sin6_family = AF_INET6;
103
+ addr.sin6_addr = in6addr_any;
104
+ addr.sin6_port = 0;
105
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
106
+ return -1;
107
+ }
108
+
109
+ len = sizeof(addr);
110
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) {
111
+ return -1;
112
+ }
113
+
114
+ return ntohs(addr.sin6_port);
115
+}
116
+
117
+static int inet_get_free_port_multiple(int nb, int *port, bool ipv6)
118
+{
119
+ int sock[nb];
120
+ int i;
121
+
122
+ for (i = 0; i < nb; i++) {
123
+ sock[i] = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
124
+ if (sock[i] < 0) {
125
+ break;
126
+ }
127
+ port[i] = ipv6 ? inet_get_free_port_socket_ipv6(sock[i]) :
128
+ inet_get_free_port_socket_ipv4(sock[i]);
129
+ if (port[i] == -1) {
130
+ break;
131
+ }
132
+ }
133
+
134
+ nb = i;
135
+ for (i = 0; i < nb; i++) {
136
+ closesocket(sock[i]);
137
+ }
138
+
139
+ return nb;
140
+}
141
+
142
+static int inet_get_free_port(bool ipv6)
143
+{
144
+ int nb, port;
145
+
146
+ nb = inet_get_free_port_multiple(1, &port, ipv6);
147
+ g_assert_cmpint(nb, ==, 1);
148
+
149
+ return port;
150
+}
151
+
152
+static void test_stream_inet_ipv4(void)
153
+{
154
+ QTestState *qts0, *qts1;
155
+ char *expect;
156
+ int port;
157
+
158
+ port = inet_get_free_port(false);
159
+ qts0 = qtest_initf("-nodefaults -M none "
160
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
161
+ "addr.ipv4=on,addr.ipv6=off,"
162
+ "addr.host=127.0.0.1,addr.port=%d", port);
163
+
164
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
165
+
166
+ qts1 = qtest_initf("-nodefaults -M none "
167
+ "-netdev stream,server=false,id=st0,addr.type=inet,"
168
+ "addr.ipv4=on,addr.ipv6=off,"
169
+ "addr.host=127.0.0.1,addr.port=%d", port);
170
+
171
+ expect = g_strdup_printf("st0: index=0,type=stream,tcp:127.0.0.1:%d\r\n",
172
+ port);
173
+ EXPECT_STATE(qts1, expect, 0);
174
+ g_free(expect);
175
+
176
+ /* the port is unknown, check only the address */
177
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:127.0.0.1", ':');
178
+
179
+ qtest_quit(qts1);
180
+ qtest_quit(qts0);
181
+}
182
+
183
+static void test_stream_inet_ipv6(void)
184
+{
185
+ QTestState *qts0, *qts1;
186
+ char *expect;
187
+ int port;
188
+
189
+ port = inet_get_free_port(true);
190
+ qts0 = qtest_initf("-nodefaults -M none "
191
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
192
+ "addr.ipv4=off,addr.ipv6=on,"
193
+ "addr.host=::1,addr.port=%d", port);
194
+
195
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
196
+
197
+ qts1 = qtest_initf("-nodefaults -M none "
198
+ "-netdev stream,server=false,id=st0,addr.type=inet,"
199
+ "addr.ipv4=off,addr.ipv6=on,"
200
+ "addr.host=::1,addr.port=%d", port);
201
+
202
+ expect = g_strdup_printf("st0: index=0,type=stream,tcp:::1:%d\r\n",
203
+ port);
204
+ EXPECT_STATE(qts1, expect, 0);
205
+ g_free(expect);
206
+
207
+ /* the port is unknown, check only the address */
208
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:::1", ':');
209
+
210
+ qtest_quit(qts1);
211
+ qtest_quit(qts0);
212
+}
213
+
214
+static void test_stream_unix(void)
215
+{
216
+ QTestState *qts0, *qts1;
217
+ char *expect;
218
+ gchar *path;
219
+
220
+ path = g_strconcat(tmpdir, "/stream_unix", NULL);
221
+
222
+ qts0 = qtest_initf("-nodefaults -M none "
223
+ "-netdev stream,id=st0,server=true,"
224
+ "addr.type=unix,addr.path=%s,",
225
+ path);
226
+
227
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
228
+
229
+ qts1 = qtest_initf("-nodefaults -M none "
230
+ "-netdev stream,id=st0,server=false,"
231
+ "addr.type=unix,addr.path=%s",
232
+ path);
233
+
234
+ expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
235
+ EXPECT_STATE(qts1, expect, 0);
236
+ EXPECT_STATE(qts0, expect, 0);
237
+ g_free(expect);
238
+ g_free(path);
239
+
240
+ qtest_quit(qts1);
241
+ qtest_quit(qts0);
242
+}
243
+
244
+#ifdef CONFIG_LINUX
245
+static void test_stream_unix_abstract(void)
246
+{
247
+ QTestState *qts0, *qts1;
248
+ char *expect;
249
+ gchar *path;
250
+
251
+ path = g_strconcat(tmpdir, "/stream_unix_abstract", NULL);
252
+
253
+ qts0 = qtest_initf("-nodefaults -M none "
254
+ "-netdev stream,id=st0,server=true,"
255
+ "addr.type=unix,addr.path=%s,"
256
+ "addr.abstract=on",
257
+ path);
258
+
259
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
260
+
261
+ qts1 = qtest_initf("-nodefaults -M none "
262
+ "-netdev stream,id=st0,server=false,"
263
+ "addr.type=unix,addr.path=%s,addr.abstract=on",
264
+ path);
265
+
266
+ expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
267
+ EXPECT_STATE(qts1, expect, 0);
268
+ EXPECT_STATE(qts0, expect, 0);
269
+ g_free(expect);
270
+ g_free(path);
271
+
272
+ qtest_quit(qts1);
273
+ qtest_quit(qts0);
274
+}
275
+#endif
276
+
277
+#ifndef _WIN32
278
+static void test_stream_fd(void)
279
+{
280
+ QTestState *qts0, *qts1;
281
+ int sock[2];
282
+ int ret;
283
+
284
+ ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, sock);
285
+ g_assert_true(ret == 0);
286
+
287
+ qts0 = qtest_initf("-nodefaults -M none "
288
+ "-netdev stream,id=st0,addr.type=fd,addr.str=%d",
289
+ sock[0]);
290
+
291
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
292
+
293
+ qts1 = qtest_initf("-nodefaults -M none "
294
+ "-netdev stream,id=st0,addr.type=fd,addr.str=%d",
295
+ sock[1]);
296
+
297
+ EXPECT_STATE(qts1, "st0: index=0,type=stream,unix:\r\n", 0);
298
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
299
+
300
+ qtest_quit(qts1);
301
+ qtest_quit(qts0);
302
+
303
+ closesocket(sock[0]);
304
+ closesocket(sock[1]);
305
+}
306
+#endif
307
+
308
+static void test_dgram_inet(void)
309
+{
310
+ QTestState *qts0, *qts1;
311
+ char *expect;
312
+ int port[2];
313
+ int nb;
314
+
315
+ nb = inet_get_free_port_multiple(2, port, false);
316
+ g_assert_cmpint(nb, ==, 2);
317
+
318
+ qts0 = qtest_initf("-nodefaults -M none "
319
+ "-netdev dgram,id=st0,"
320
+ "local.type=inet,local.host=127.0.0.1,local.port=%d,"
321
+ "remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
322
+ port[0], port[1]);
323
+
324
+ expect = g_strdup_printf("st0: index=0,type=dgram,"
325
+ "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
326
+ port[0], port[1]);
327
+ EXPECT_STATE(qts0, expect, 0);
328
+ g_free(expect);
329
+
330
+ qts1 = qtest_initf("-nodefaults -M none "
331
+ "-netdev dgram,id=st0,"
332
+ "local.type=inet,local.host=127.0.0.1,local.port=%d,"
333
+ "remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
334
+ port[1], port[0]);
335
+
336
+ expect = g_strdup_printf("st0: index=0,type=dgram,"
337
+ "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
338
+ port[1], port[0]);
339
+ EXPECT_STATE(qts1, expect, 0);
340
+ g_free(expect);
341
+
342
+ qtest_quit(qts1);
343
+ qtest_quit(qts0);
344
+}
345
+
346
+#ifndef _WIN32
347
+static void test_dgram_mcast(void)
348
+{
349
+ QTestState *qts;
350
+
351
+ qts = qtest_initf("-nodefaults -M none "
352
+ "-netdev dgram,id=st0,"
353
+ "remote.type=inet,remote.host=230.0.0.1,remote.port=1234");
354
+
355
+ EXPECT_STATE(qts, "st0: index=0,type=dgram,mcast=230.0.0.1:1234\r\n", 0);
356
+
357
+ qtest_quit(qts);
358
+}
359
+
360
+static void test_dgram_unix(void)
361
+{
362
+ QTestState *qts0, *qts1;
363
+ char *expect;
364
+ gchar *path0, *path1;
365
+
366
+ path0 = g_strconcat(tmpdir, "/dgram_unix0", NULL);
367
+ path1 = g_strconcat(tmpdir, "/dgram_unix1", NULL);
368
+
369
+ qts0 = qtest_initf("-nodefaults -M none "
370
+ "-netdev dgram,id=st0,local.type=unix,local.path=%s,"
371
+ "remote.type=unix,remote.path=%s",
372
+ path0, path1);
373
+
374
+ expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
375
+ path0, path1);
376
+ EXPECT_STATE(qts0, expect, 0);
377
+ g_free(expect);
378
+
379
+ qts1 = qtest_initf("-nodefaults -M none "
380
+ "-netdev dgram,id=st0,local.type=unix,local.path=%s,"
381
+ "remote.type=unix,remote.path=%s",
382
+ path1, path0);
383
+
384
+
385
+ expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
386
+ path1, path0);
387
+ EXPECT_STATE(qts1, expect, 0);
388
+ g_free(expect);
389
+
390
+ unlink(path0);
391
+ g_free(path0);
392
+ unlink(path1);
393
+ g_free(path1);
394
+
395
+ qtest_quit(qts1);
396
+ qtest_quit(qts0);
397
+}
398
+
399
+static void test_dgram_fd(void)
400
+{
401
+ QTestState *qts0, *qts1;
402
+ char *expect;
403
+ int ret;
404
+ int sv[2];
405
+
406
+ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, sv);
407
+ g_assert_cmpint(ret, !=, -1);
408
+
409
+ qts0 = qtest_initf("-nodefaults -M none "
410
+ "-netdev dgram,id=st0,local.type=fd,local.str=%d",
411
+ sv[0]);
412
+
413
+ expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[0]);
414
+ EXPECT_STATE(qts0, expect, 0);
415
+ g_free(expect);
416
+
417
+ qts1 = qtest_initf("-nodefaults -M none "
418
+ "-netdev dgram,id=st0,local.type=fd,local.str=%d",
419
+ sv[1]);
420
+
421
+
422
+ expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[1]);
423
+ EXPECT_STATE(qts1, expect, 0);
424
+ g_free(expect);
425
+
426
+ qtest_quit(qts1);
427
+ qtest_quit(qts0);
428
+
429
+ closesocket(sv[0]);
430
+ closesocket(sv[1]);
431
+}
432
+#endif
433
+
434
+int main(int argc, char **argv)
435
+{
436
+ int ret;
437
+ bool has_ipv4, has_ipv6, has_afunix;
438
+ g_autoptr(GError) err = NULL;
439
+
440
+ socket_init();
441
+ g_test_init(&argc, &argv, NULL);
442
+
443
+ if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
444
+ g_error("socket_check_protocol_support() failed\n");
445
+ }
446
+
447
+ tmpdir = g_dir_make_tmp("netdev-socket.XXXXXX", &err);
448
+ if (tmpdir == NULL) {
449
+ g_error("Can't create temporary directory in %s: %s",
450
+ g_get_tmp_dir(), err->message);
451
+ }
452
+
453
+ if (has_ipv4) {
454
+ qtest_add_func("/netdev/stream/inet/ipv4", test_stream_inet_ipv4);
455
+ qtest_add_func("/netdev/dgram/inet", test_dgram_inet);
456
+#ifndef _WIN32
457
+ qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast);
458
+#endif
459
+ }
460
+ if (has_ipv6) {
461
+ qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6);
462
+ }
463
+
464
+ socket_check_afunix_support(&has_afunix);
465
+ if (has_afunix) {
466
+#ifndef _WIN32
467
+ qtest_add_func("/netdev/dgram/unix", test_dgram_unix);
468
+#endif
469
+ qtest_add_func("/netdev/stream/unix", test_stream_unix);
470
+#ifdef CONFIG_LINUX
471
+ qtest_add_func("/netdev/stream/unix/abstract",
472
+ test_stream_unix_abstract);
473
+#endif
474
+#ifndef _WIN32
475
+ qtest_add_func("/netdev/stream/fd", test_stream_fd);
476
+ qtest_add_func("/netdev/dgram/fd", test_dgram_fd);
477
+#endif
478
+ }
479
+
480
+ ret = g_test_run();
481
+
482
+ g_rmdir(tmpdir);
483
+ g_free(tmpdir);
484
+
485
+ return ret;
486
+}
81
--
487
--
82
2.7.4
488
2.7.4
83
84
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Laurent Vivier <lvivier@redhat.com>
2
2
3
We add the vnet_hdr_support option for filter-rewriter, default is disabled.
3
In stream mode, if the server shuts down there is currently
4
If you use virtio-net-pci or other driver needs vnet_hdr, please enable it.
4
no way to reconnect the client to a new server without removing
5
You can use it for example:
5
the NIC device and the netdev backend (or to reboot).
6
-object filter-rewriter,id=rew0,netdev=hn0,queue=all,vnet_hdr_support
6
7
7
This patch introduces a reconnect option that specifies a delay
8
We get the vnet_hdr_len from NetClientState that make us
8
to try to reconnect with the same parameters.
9
parse net packet correctly.
9
10
10
Add a new test in qtest to test the reconnect option and the
11
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
11
connect/disconnect events.
12
13
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
15
---
14
net/filter-rewriter.c | 37 ++++++++++++++++++++++++++++++++++++-
16
net/stream.c | 53 ++++++++++++++++++++++-
15
qemu-options.hx | 4 ++--
17
qapi/net.json | 7 ++-
16
2 files changed, 38 insertions(+), 3 deletions(-)
18
qemu-options.hx | 6 +--
17
19
tests/qtest/netdev-socket.c | 101 ++++++++++++++++++++++++++++++++++++++++++++
18
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
20
4 files changed, 162 insertions(+), 5 deletions(-)
21
22
diff --git a/net/stream.c b/net/stream.c
19
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
20
--- a/net/filter-rewriter.c
24
--- a/net/stream.c
21
+++ b/net/filter-rewriter.c
25
+++ b/net/stream.c
22
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
23
#include "qemu-common.h"
27
#include "io/channel-socket.h"
24
#include "qapi/error.h"
28
#include "io/net-listener.h"
25
#include "qapi/qmp/qerror.h"
29
#include "qapi/qapi-events-net.h"
26
+#include "qemu/error-report.h"
30
+#include "qapi/qapi-visit-sockets.h"
27
#include "qapi-visit.h"
31
+#include "qapi/clone-visitor.h"
28
#include "qom/object.h"
32
29
#include "qemu/main-loop.h"
33
typedef struct NetStreamState {
30
@@ -XXX,XX +XXX,XX @@ typedef struct RewriterState {
34
NetClientState nc;
31
NetQueue *incoming_queue;
35
@@ -XXX,XX +XXX,XX @@ typedef struct NetStreamState {
32
/* hashtable to save connection */
36
guint ioc_write_tag;
33
GHashTable *connection_track_table;
37
SocketReadState rs;
34
+ bool vnet_hdr;
38
unsigned int send_index; /* number of bytes sent*/
35
} RewriterState;
39
+ uint32_t reconnect;
36
40
+ guint timer_tag;
37
static void filter_rewriter_flush(NetFilterState *nf)
41
+ SocketAddress *addr;
38
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
42
} NetStreamState;
39
ConnectionKey key;
43
40
Packet *pkt;
44
static void net_stream_listen(QIONetListener *listener,
41
ssize_t size = iov_size(iov, iovcnt);
45
QIOChannelSocket *cioc,
42
+ ssize_t vnet_hdr_len = 0;
46
void *opaque);
43
char *buf = g_malloc0(size);
47
+static void net_stream_arm_reconnect(NetStreamState *s);
44
48
45
iov_to_buf(iov, iovcnt, 0, buf, size);
49
static gboolean net_stream_writable(QIOChannel *ioc,
46
- pkt = packet_new(buf, size, 0);
50
GIOCondition condition,
47
+
51
@@ -XXX,XX +XXX,XX @@ static gboolean net_stream_send(QIOChannel *ioc,
48
+ if (s->vnet_hdr) {
52
qemu_set_info_str(&s->nc, "%s", "");
49
+ vnet_hdr_len = nf->netdev->vnet_hdr_len;
53
50
+ }
54
qapi_event_send_netdev_stream_disconnected(s->nc.name);
51
+
55
+ net_stream_arm_reconnect(s);
52
+ pkt = packet_new(buf, size, vnet_hdr_len);
56
53
g_free(buf);
57
return G_SOURCE_REMOVE;
54
58
}
55
/*
59
@@ -XXX,XX +XXX,XX @@ static gboolean net_stream_send(QIOChannel *ioc,
56
@@ -XXX,XX +XXX,XX @@ static void colo_rewriter_setup(NetFilterState *nf, Error **errp)
60
static void net_stream_cleanup(NetClientState *nc)
57
s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
61
{
62
NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc);
63
+ if (s->timer_tag) {
64
+ g_source_remove(s->timer_tag);
65
+ s->timer_tag = 0;
66
+ }
67
+ if (s->addr) {
68
+ qapi_free_SocketAddress(s->addr);
69
+ s->addr = NULL;
70
+ }
71
if (s->ioc) {
72
if (QIO_CHANNEL_SOCKET(s->ioc)->fd != -1) {
73
if (s->ioc_read_tag) {
74
@@ -XXX,XX +XXX,XX @@ static void net_stream_client_connected(QIOTask *task, gpointer opaque)
75
error:
76
object_unref(OBJECT(s->ioc));
77
s->ioc = NULL;
78
+ net_stream_arm_reconnect(s);
79
+}
80
+
81
+static gboolean net_stream_reconnect(gpointer data)
82
+{
83
+ NetStreamState *s = data;
84
+ QIOChannelSocket *sioc;
85
+
86
+ s->timer_tag = 0;
87
+
88
+ sioc = qio_channel_socket_new();
89
+ s->ioc = QIO_CHANNEL(sioc);
90
+ qio_channel_socket_connect_async(sioc, s->addr,
91
+ net_stream_client_connected, s,
92
+ NULL, NULL);
93
+ return G_SOURCE_REMOVE;
94
+}
95
+
96
+static void net_stream_arm_reconnect(NetStreamState *s)
97
+{
98
+ if (s->reconnect && s->timer_tag == 0) {
99
+ s->timer_tag = g_timeout_add_seconds(s->reconnect,
100
+ net_stream_reconnect, s);
101
+ }
58
}
102
}
59
103
60
+static bool filter_rewriter_get_vnet_hdr(Object *obj, Error **errp)
104
static int net_stream_client_init(NetClientState *peer,
61
+{
105
const char *model,
62
+ RewriterState *s = FILTER_COLO_REWRITER(obj);
106
const char *name,
63
+
107
SocketAddress *addr,
64
+ return s->vnet_hdr;
108
+ uint32_t reconnect,
65
+}
109
Error **errp)
66
+
67
+static void filter_rewriter_set_vnet_hdr(Object *obj,
68
+ bool value,
69
+ Error **errp)
70
+{
71
+ RewriterState *s = FILTER_COLO_REWRITER(obj);
72
+
73
+ s->vnet_hdr = value;
74
+}
75
+
76
+static void filter_rewriter_init(Object *obj)
77
+{
78
+ RewriterState *s = FILTER_COLO_REWRITER(obj);
79
+
80
+ s->vnet_hdr = false;
81
+ object_property_add_bool(obj, "vnet_hdr_support",
82
+ filter_rewriter_get_vnet_hdr,
83
+ filter_rewriter_set_vnet_hdr, NULL);
84
+}
85
+
86
static void colo_rewriter_class_init(ObjectClass *oc, void *data)
87
{
110
{
88
NetFilterClass *nfc = NETFILTER_CLASS(oc);
111
NetStreamState *s;
89
@@ -XXX,XX +XXX,XX @@ static const TypeInfo colo_rewriter_info = {
112
@@ -XXX,XX +XXX,XX @@ static int net_stream_client_init(NetClientState *peer,
90
.name = TYPE_FILTER_REWRITER,
113
s->ioc = QIO_CHANNEL(sioc);
91
.parent = TYPE_NETFILTER,
114
s->nc.link_down = true;
92
.class_init = colo_rewriter_class_init,
115
93
+ .instance_init = filter_rewriter_init,
116
+ s->reconnect = reconnect;
94
.instance_size = sizeof(RewriterState),
117
+ if (reconnect) {
95
};
118
+ s->addr = QAPI_CLONE(SocketAddress, addr);
96
119
+ }
120
qio_channel_socket_connect_async(sioc, addr,
121
net_stream_client_connected, s,
122
NULL, NULL);
123
@@ -XXX,XX +XXX,XX @@ int net_init_stream(const Netdev *netdev, const char *name,
124
sock = &netdev->u.stream;
125
126
if (!sock->has_server || !sock->server) {
127
- return net_stream_client_init(peer, "stream", name, sock->addr, errp);
128
+ return net_stream_client_init(peer, "stream", name, sock->addr,
129
+ sock->has_reconnect ? sock->reconnect : 0,
130
+ errp);
131
+ }
132
+ if (sock->has_reconnect) {
133
+ error_setg(errp, "'reconnect' option is incompatible with "
134
+ "socket in server mode");
135
+ return -1;
136
}
137
return net_stream_server_init(peer, "stream", name, sock->addr, errp);
138
}
139
diff --git a/qapi/net.json b/qapi/net.json
140
index XXXXXXX..XXXXXXX 100644
141
--- a/qapi/net.json
142
+++ b/qapi/net.json
143
@@ -XXX,XX +XXX,XX @@
144
# @addr: socket address to listen on (server=true)
145
# or connect to (server=false)
146
# @server: create server socket (default: false)
147
+# @reconnect: For a client socket, if a socket is disconnected,
148
+# then attempt a reconnect after the given number of seconds.
149
+# Setting this to zero disables this function. (default: 0)
150
+# (since 8.0)
151
#
152
# Only SocketAddress types 'unix', 'inet' and 'fd' are supported.
153
#
154
@@ -XXX,XX +XXX,XX @@
155
{ 'struct': 'NetdevStreamOptions',
156
'data': {
157
'addr': 'SocketAddress',
158
- '*server': 'bool' } }
159
+ '*server': 'bool',
160
+ '*reconnect': 'uint32' } }
161
162
##
163
# @NetdevDgramOptions:
97
diff --git a/qemu-options.hx b/qemu-options.hx
164
diff --git a/qemu-options.hx b/qemu-options.hx
98
index XXXXXXX..XXXXXXX 100644
165
index XXXXXXX..XXXXXXX 100644
99
--- a/qemu-options.hx
166
--- a/qemu-options.hx
100
+++ b/qemu-options.hx
167
+++ b/qemu-options.hx
101
@@ -XXX,XX +XXX,XX @@ Create a filter-redirector we need to differ outdev id from indev id, id can not
168
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
102
be the same. we can just use indev or outdev, but at least one of indev or outdev
169
"-netdev socket,id=str[,fd=h][,udp=host:port][,localaddr=host:port]\n"
103
need to be specified.
170
" configure a network backend to connect to another network\n"
104
171
" using an UDP tunnel\n"
105
-@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid}[,queue=@var{all|rx|tx}]
172
- "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off]\n"
106
+@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx},[vnet_hdr_support]
173
- "-netdev stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off]\n"
107
174
- "-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor\n"
108
Filter-rewriter is a part of COLO project.It will rewrite tcp packet to
175
+ "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off][,reconnect=seconds]\n"
109
secondary from primary to keep secondary tcp connection,and rewrite
176
+ "-netdev stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off][,reconnect=seconds]\n"
110
tcp packet to primary from secondary make tcp packet can be handled by
177
+ "-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor[,reconnect=seconds]\n"
111
-client.
178
" configure a network backend to connect to another network\n"
112
+client.if it has the vnet_hdr_support flag, we can parse packet with vnet header.
179
" using a socket connection in stream mode.\n"
113
180
"-netdev dgram,id=str,remote.type=inet,remote.host=maddr,remote.port=port[,local.type=inet,local.host=addr]\n"
114
usage:
181
diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
115
colo secondary:
182
index XXXXXXX..XXXXXXX 100644
183
--- a/tests/qtest/netdev-socket.c
184
+++ b/tests/qtest/netdev-socket.c
185
@@ -XXX,XX +XXX,XX @@
186
#include <glib/gstdio.h>
187
#include "../unit/socket-helpers.h"
188
#include "libqtest.h"
189
+#include "qapi/qmp/qstring.h"
190
+#include "qemu/sockets.h"
191
+#include "qapi/qobject-input-visitor.h"
192
+#include "qapi/qapi-visit-sockets.h"
193
194
#define CONNECTION_TIMEOUT 5
195
196
@@ -XXX,XX +XXX,XX @@ static void test_stream_inet_ipv4(void)
197
qtest_quit(qts0);
198
}
199
200
+static void wait_stream_connected(QTestState *qts, const char *id,
201
+ SocketAddress **addr)
202
+{
203
+ QDict *resp, *data;
204
+ QString *qstr;
205
+ QObject *obj;
206
+ Visitor *v = NULL;
207
+
208
+ resp = qtest_qmp_eventwait_ref(qts, "NETDEV_STREAM_CONNECTED");
209
+ g_assert_nonnull(resp);
210
+ data = qdict_get_qdict(resp, "data");
211
+ g_assert_nonnull(data);
212
+
213
+ qstr = qobject_to(QString, qdict_get(data, "netdev-id"));
214
+ g_assert_nonnull(data);
215
+
216
+ g_assert(!strcmp(qstring_get_str(qstr), id));
217
+
218
+ obj = qdict_get(data, "addr");
219
+
220
+ v = qobject_input_visitor_new(obj);
221
+ visit_type_SocketAddress(v, NULL, addr, NULL);
222
+ visit_free(v);
223
+ qobject_unref(resp);
224
+}
225
+
226
+static void wait_stream_disconnected(QTestState *qts, const char *id)
227
+{
228
+ QDict *resp, *data;
229
+ QString *qstr;
230
+
231
+ resp = qtest_qmp_eventwait_ref(qts, "NETDEV_STREAM_DISCONNECTED");
232
+ g_assert_nonnull(resp);
233
+ data = qdict_get_qdict(resp, "data");
234
+ g_assert_nonnull(data);
235
+
236
+ qstr = qobject_to(QString, qdict_get(data, "netdev-id"));
237
+ g_assert_nonnull(data);
238
+
239
+ g_assert(!strcmp(qstring_get_str(qstr), id));
240
+ qobject_unref(resp);
241
+}
242
+
243
+static void test_stream_inet_reconnect(void)
244
+{
245
+ QTestState *qts0, *qts1;
246
+ int port;
247
+ SocketAddress *addr;
248
+
249
+ port = inet_get_free_port(false);
250
+ qts0 = qtest_initf("-nodefaults -M none "
251
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
252
+ "addr.ipv4=on,addr.ipv6=off,"
253
+ "addr.host=127.0.0.1,addr.port=%d", port);
254
+
255
+ EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
256
+
257
+ qts1 = qtest_initf("-nodefaults -M none "
258
+ "-netdev stream,server=false,id=st0,addr.type=inet,"
259
+ "addr.ipv4=on,addr.ipv6=off,reconnect=1,"
260
+ "addr.host=127.0.0.1,addr.port=%d", port);
261
+
262
+ wait_stream_connected(qts0, "st0", &addr);
263
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
264
+ g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
265
+ qapi_free_SocketAddress(addr);
266
+
267
+ /* kill server */
268
+ qtest_quit(qts0);
269
+
270
+ /* check client has been disconnected */
271
+ wait_stream_disconnected(qts1, "st0");
272
+
273
+ /* restart server */
274
+ qts0 = qtest_initf("-nodefaults -M none "
275
+ "-netdev stream,id=st0,server=true,addr.type=inet,"
276
+ "addr.ipv4=on,addr.ipv6=off,"
277
+ "addr.host=127.0.0.1,addr.port=%d", port);
278
+
279
+ /* wait connection events*/
280
+ wait_stream_connected(qts0, "st0", &addr);
281
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
282
+ g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
283
+ qapi_free_SocketAddress(addr);
284
+
285
+ wait_stream_connected(qts1, "st0", &addr);
286
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
287
+ g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
288
+ g_assert_cmpint(atoi(addr->u.inet.port), ==, port);
289
+ qapi_free_SocketAddress(addr);
290
+
291
+ qtest_quit(qts1);
292
+ qtest_quit(qts0);
293
+}
294
+
295
static void test_stream_inet_ipv6(void)
296
{
297
QTestState *qts0, *qts1;
298
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
299
#ifndef _WIN32
300
qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast);
301
#endif
302
+ qtest_add_func("/netdev/stream/inet/reconnect",
303
+ test_stream_inet_reconnect);
304
}
305
if (has_ipv6) {
306
qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6);
116
--
307
--
117
2.7.4
308
2.7.4
118
119
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Make colo-compare and filter-rewriter can parse vnet packet.
3
VHOST_BACKEND_F_IOTLB_ASID is the feature bit, not the bitmask. Since
4
the device under test also provided VHOST_BACKEND_F_IOTLB_MSG_V2 and
5
VHOST_BACKEND_F_IOTLB_BATCH, this went unnoticed.
4
6
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Fixes: c1a1008685 ("vdpa: always start CVQ in SVQ mode if possible")
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
10
Acked-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
12
---
8
net/colo.c | 6 +++---
13
net/vhost-vdpa.c | 2 +-
9
1 file changed, 3 insertions(+), 3 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
15
11
diff --git a/net/colo.c b/net/colo.c
16
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo.c
18
--- a/net/vhost-vdpa.c
14
+++ b/net/colo.c
19
+++ b/net/vhost-vdpa.c
15
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
20
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc)
16
{
21
g_strerror(errno), errno);
17
int network_length;
22
return -1;
18
static const uint8_t vlan[] = {0x81, 0x00};
19
- uint8_t *data = pkt->data;
20
+ uint8_t *data = pkt->data + pkt->vnet_hdr_len;
21
uint16_t l3_proto;
22
ssize_t l2hdr_len = eth_get_l2_hdr_length(data);
23
24
- if (pkt->size < ETH_HLEN) {
25
+ if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) {
26
trace_colo_proxy_main("pkt->size < ETH_HLEN");
27
return 1;
28
}
23
}
29
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
24
- if (!(backend_features & VHOST_BACKEND_F_IOTLB_ASID) ||
30
}
25
+ if (!(backend_features & BIT_ULL(VHOST_BACKEND_F_IOTLB_ASID)) ||
31
26
!vhost_vdpa_net_valid_svq_features(v->dev->features, NULL)) {
32
network_length = pkt->ip->ip_hl * 4;
27
return 0;
33
- if (pkt->size < l2hdr_len + network_length) {
34
+ if (pkt->size < l2hdr_len + network_length + pkt->vnet_hdr_len) {
35
trace_colo_proxy_main("pkt->size < network_header + network_length");
36
return 1;
37
}
28
}
38
--
29
--
39
2.7.4
30
2.7.4
40
31
41
32
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
4
Signed-off-by: Jason Wang <jasowang@redhat.com>
5
---
6
docs/colo-proxy.txt | 26 ++++++++++++++++++++++++++
7
1 file changed, 26 insertions(+)
8
9
diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt
10
index XXXXXXX..XXXXXXX 100644
11
--- a/docs/colo-proxy.txt
12
+++ b/docs/colo-proxy.txt
13
@@ -XXX,XX +XXX,XX @@ Secondary(ip:3.3.3.8):
14
-chardev socket,id=red1,host=3.3.3.3,port=9004
15
-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0
16
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
17
+-object filter-rewriter,id=f3,netdev=hn0,queue=all
18
+
19
+If you want to use virtio-net-pci or other driver with vnet_header:
20
+
21
+Primary(ip:3.3.3.3):
22
+-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
23
+-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
24
+-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait
25
+-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait
26
+-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait
27
+-chardev socket,id=compare0-0,host=3.3.3.3,port=9001
28
+-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait
29
+-chardev socket,id=compare_out0,host=3.3.3.3,port=9005
30
+-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support
31
+-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out,vnet_hdr_support
32
+-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0,vnet_hdr_support
33
+-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support
34
+
35
+Secondary(ip:3.3.3.8):
36
+-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown
37
+-device e1000,netdev=hn0,mac=52:a4:00:12:78:66
38
+-chardev socket,id=red0,host=3.3.3.3,port=9003
39
+-chardev socket,id=red1,host=3.3.3.3,port=9004
40
+-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0,vnet_hdr_support
41
+-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1,vnet_hdr_support
42
+-object filter-rewriter,id=f3,netdev=hn0,queue=all,vnet_hdr_support
43
44
Note:
45
a.COLO-proxy must work with COLO-frame and Block-replication.
46
--
47
2.7.4
48
49
diff view generated by jsdifflib