1
The following changes since commit 6632f6ff96f0537fc34cdc00c760656fc62e23c5:
1
The following changes since commit 187f35512106501fe9a11057f4d8705431e0026d:
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 remote-tracking branch 'remotes/stsquad/tags/pull-testing-next-251019-3' into staging (2019-10-26 10:13:48 +0100)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to 189ae6bb5ce1f5a322f8691d00fe942ba43dd601:
9
for you to fetch changes up to 1e907a32b77e5d418538453df5945242e43224fa:
10
10
11
virtio-net: fix offload ctrl endian (2017-07-17 20:13:56 +0800)
11
COLO-compare: Fix incorrect `if` logic (2019-10-29 10:28:07 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
- fix virtio-net ctrl offload endian
15
Changes from V1:
16
- vnet header support for variou COLO netfilters and compare thread
16
17
- Fix compling issue
17
18
18
----------------------------------------------------------------
19
----------------------------------------------------------------
19
Jason Wang (1):
20
Fan Yang (1):
20
virtio-net: fix offload ctrl endian
21
COLO-compare: Fix incorrect `if` logic
21
22
22
Michal Privoznik (1):
23
Michael S. Tsirkin (1):
23
virtion-net: Prefer is_power_of_2()
24
virtio: new post_load hook
24
25
25
Zhang Chen (12):
26
Mikhail Sennikovsky (1):
26
net: Add vnet_hdr_len arguments in NetClientState
27
virtio-net: prevent offloads reset on migration
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
28
39
docs/colo-proxy.txt | 26 ++++++++++++++++
29
Sven Schnelle (1):
40
hw/net/virtio-net.c | 4 ++-
30
net: add tulip (dec21143) driver
41
include/net/net.h | 10 ++++--
31
42
net/colo-compare.c | 84 ++++++++++++++++++++++++++++++++++++++++++---------
32
MAINTAINERS | 6 +
43
net/colo.c | 9 +++---
33
hw/net/Kconfig | 5 +
44
net/colo.h | 4 ++-
34
hw/net/Makefile.objs | 1 +
45
net/filter-mirror.c | 75 +++++++++++++++++++++++++++++++++++++++++----
35
hw/net/trace-events | 14 +
46
net/filter-rewriter.c | 37 ++++++++++++++++++++++-
36
hw/net/tulip.c | 1029 ++++++++++++++++++++++++++++++++++++++++
47
net/net.c | 37 ++++++++++++++++++++---
37
hw/net/tulip.h | 267 +++++++++++
48
net/socket.c | 8 ++---
38
hw/net/virtio-net.c | 27 +-
49
qemu-options.hx | 19 ++++++------
39
hw/virtio/virtio.c | 7 +
50
11 files changed, 265 insertions(+), 48 deletions(-)
40
include/hw/pci/pci_ids.h | 1 +
41
include/hw/virtio/virtio-net.h | 2 +
42
include/hw/virtio/virtio.h | 6 +
43
net/colo-compare.c | 6 +-
44
12 files changed, 1365 insertions(+), 6 deletions(-)
45
create mode 100644 hw/net/tulip.c
46
create mode 100644 hw/net/tulip.h
51
47
52
48
49
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
Add vnet_hdr_len arguments in NetClientState
4
that make other module get real vnet_hdr_len easily.
5
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
include/net/net.h | 1 +
10
net/net.c | 1 +
11
2 files changed, 2 insertions(+)
12
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
26
index XXXXXXX..XXXXXXX 100644
27
--- a/net/net.c
28
+++ b/net/net.c
29
@@ -XXX,XX +XXX,XX @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
30
return;
31
}
32
33
+ nc->vnet_hdr_len = len;
34
nc->info->set_vnet_hdr_len(nc, len);
35
}
36
37
--
38
2.7.4
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
We add a flag to decide whether net_fill_rstate() need read
4
the vnet_hdr_len or not.
5
6
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
7
Suggested-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
include/net/net.h | 9 +++++++--
11
net/colo-compare.c | 4 ++--
12
net/filter-mirror.c | 2 +-
13
net/net.c | 36 ++++++++++++++++++++++++++++++++----
14
net/socket.c | 8 ++++----
15
5 files changed, 46 insertions(+), 13 deletions(-)
16
17
diff --git a/include/net/net.h b/include/net/net.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/net/net.h
20
+++ b/include/net/net.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct NICState {
22
} NICState;
23
24
struct SocketReadState {
25
- int state; /* 0 = getting length, 1 = getting data */
26
+ /* 0 = getting length, 1 = getting vnet header length, 2 = getting data */
27
+ int state;
28
+ /* This flag decide whether to read the vnet_hdr_len field */
29
+ bool vnet_hdr;
30
uint32_t index;
31
uint32_t packet_len;
32
+ uint32_t vnet_hdr_len;
33
uint8_t buf[NET_BUFSIZE];
34
SocketReadStateFinalize *finalize;
35
};
36
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
37
void print_net_client(Monitor *mon, NetClientState *nc);
38
void hmp_info_network(Monitor *mon, const QDict *qdict);
39
void net_socket_rs_init(SocketReadState *rs,
40
- SocketReadStateFinalize *finalize);
41
+ SocketReadStateFinalize *finalize,
42
+ bool vnet_hdr);
43
44
/* NIC info */
45
46
diff --git a/net/colo-compare.c b/net/colo-compare.c
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
75
index XXXXXXX..XXXXXXX 100644
76
--- a/net/net.c
77
+++ b/net/net.c
78
@@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_net_opts = {
79
};
80
81
void net_socket_rs_init(SocketReadState *rs,
82
- SocketReadStateFinalize *finalize)
83
+ SocketReadStateFinalize *finalize,
84
+ bool vnet_hdr)
85
{
86
rs->state = 0;
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
--
183
2.7.4
184
185
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
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
We add the vnet_hdr_support option for filter-redirector, default is disabled.
4
If you use virtio-net-pci net driver or other driver needs vnet_hdr, please enable it.
5
Because colo-compare or other modules needs the vnet_hdr_len to parse
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>
12
---
13
net/filter-mirror.c | 23 +++++++++++++++++++++++
14
qemu-options.hx | 6 +++---
15
2 files changed, 26 insertions(+), 3 deletions(-)
16
17
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/net/filter-mirror.c
20
+++ b/net/filter-mirror.c
21
@@ -XXX,XX +XXX,XX @@ static void filter_redirector_set_outdev(Object *obj,
22
s->outdev = g_strdup(value);
23
}
24
25
+static bool filter_redirector_get_vnet_hdr(Object *obj, Error **errp)
26
+{
27
+ MirrorState *s = FILTER_REDIRECTOR(obj);
28
+
29
+ return s->vnet_hdr;
30
+}
31
+
32
+static void filter_redirector_set_vnet_hdr(Object *obj,
33
+ bool value,
34
+ Error **errp)
35
+{
36
+ MirrorState *s = FILTER_REDIRECTOR(obj);
37
+
38
+ s->vnet_hdr = value;
39
+}
40
+
41
static void filter_mirror_init(Object *obj)
42
{
43
MirrorState *s = FILTER_MIRROR(obj);
44
@@ -XXX,XX +XXX,XX @@ static void filter_mirror_init(Object *obj)
45
46
static void filter_redirector_init(Object *obj)
47
{
48
+ MirrorState *s = FILTER_REDIRECTOR(obj);
49
+
50
object_property_add_str(obj, "indev", filter_redirector_get_indev,
51
filter_redirector_set_indev, NULL);
52
object_property_add_str(obj, "outdev", filter_redirector_get_outdev,
53
filter_redirector_set_outdev, NULL);
54
+
55
+ s->vnet_hdr = false;
56
+ object_property_add_bool(obj, "vnet_hdr_support",
57
+ filter_redirector_get_vnet_hdr,
58
+ filter_redirector_set_vnet_hdr, NULL);
59
}
60
61
static void filter_mirror_fini(Object *obj)
62
diff --git a/qemu-options.hx b/qemu-options.hx
63
index XXXXXXX..XXXXXXX 100644
64
--- a/qemu-options.hx
65
+++ b/qemu-options.hx
66
@@ -XXX,XX +XXX,XX @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
67
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.
69
70
-@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},
71
-outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
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]
73
74
filter-redirector on netdev @var{netdevid},redirect filter's net packet to chardev
75
-@var{chardevid},and redirect indev's packet to filter.
76
+@var{chardevid},and redirect indev's packet to filter.if it has the vnet_hdr_support flag,
77
+filter-redirector will redirect packet with vnet_hdr_len.
78
Create a filter-redirector we need to differ outdev id from indev id, id can not
79
be the same. we can just use indev or outdev, but at least one of indev or outdev
80
need to be specified.
81
--
82
2.7.4
83
84
diff view generated by jsdifflib
1
Spec said offloads should be le64, so use virtio_ldq_p() to guarantee
1
From: Sven Schnelle <svens@stackframe.org>
2
valid endian.
3
2
4
Fixes: 644c98587d4c ("virtio-net: dynamic network offloads configuration")
3
This adds the basic functionality to emulate a Tulip NIC.
5
Cc: qemu-stable@nongnu.org
4
6
Cc: Dmitry Fleytman <dfleytma@redhat.com>
5
Implemented are:
6
7
- RX and TX functionality
8
- Perfect Frame Filtering
9
- Big/Little Endian descriptor support
10
- 93C46 EEPROM support
11
- LXT970 PHY
12
13
Not implemented, mostly because i had no OS using these functions:
14
15
- Imperfect frame filtering
16
- General Purpose Timer
17
- Transmit automatic polling
18
- Boot ROM support
19
- SIA interface
20
- Big/Little Endian data buffer conversion
21
22
Successfully tested with the following Operating Systems:
23
24
- MSDOS with Microsoft Network Client 3.0 and DEC ODI drivers
25
- HPPA Linux
26
- Windows XP
27
- HP-UX
28
29
Signed-off-by: Sven Schnelle <svens@stackframe.org>
30
Message-Id: <20191022155413.4619-1-svens@stackframe.org>
31
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
32
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
33
---
9
hw/net/virtio-net.c | 2 ++
34
MAINTAINERS | 6 +
10
1 file changed, 2 insertions(+)
35
hw/net/Kconfig | 5 +
36
hw/net/Makefile.objs | 1 +
37
hw/net/trace-events | 14 +
38
hw/net/tulip.c | 1029 ++++++++++++++++++++++++++++++++++++++++++++++
39
hw/net/tulip.h | 267 ++++++++++++
40
include/hw/pci/pci_ids.h | 1 +
41
7 files changed, 1323 insertions(+)
42
create mode 100644 hw/net/tulip.c
43
create mode 100644 hw/net/tulip.h
11
44
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
45
diff --git a/MAINTAINERS b/MAINTAINERS
13
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
47
--- a/MAINTAINERS
15
+++ b/hw/net/virtio-net.c
48
+++ b/MAINTAINERS
16
@@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
49
@@ -XXX,XX +XXX,XX @@ M: Stefan Weil <sw@weilnetz.de>
17
if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) {
50
S: Maintained
18
uint64_t supported_offloads;
51
F: hw/net/eepro100.c
19
52
20
+ offloads = virtio_ldq_p(vdev, &offloads);
53
+tulip
21
+
54
+M: Sven Schnelle <svens@stackframe.org>
22
if (!n->has_vnet_hdr) {
55
+S: Maintained
23
return VIRTIO_NET_ERR;
56
+F: hw/net/tulip.c
24
}
57
+F: hw/net/tulip.h
58
+
59
Generic Loader
60
M: Alistair Francis <alistair@alistair23.me>
61
S: Maintained
62
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
63
index XXXXXXX..XXXXXXX 100644
64
--- a/hw/net/Kconfig
65
+++ b/hw/net/Kconfig
66
@@ -XXX,XX +XXX,XX @@ config PCNET_PCI
67
config PCNET_COMMON
68
bool
69
70
+config TULIP
71
+ bool
72
+ default y if PCI_DEVICES
73
+ depends on PCI
74
+
75
config E1000_PCI
76
bool
77
default y if PCI_DEVICES
78
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/net/Makefile.objs
81
+++ b/hw/net/Makefile.objs
82
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_E1000E_PCI_EXPRESS) += e1000e.o e1000e_core.o e1000x_common.
83
common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
84
common-obj-$(CONFIG_VMXNET3_PCI) += net_tx_pkt.o net_rx_pkt.o
85
common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet3.o
86
+common-obj-$(CONFIG_TULIP) += tulip.o
87
88
common-obj-$(CONFIG_SMC91C111) += smc91c111.o
89
common-obj-$(CONFIG_LAN9118) += lan9118.o
90
diff --git a/hw/net/trace-events b/hw/net/trace-events
91
index XXXXXXX..XXXXXXX 100644
92
--- a/hw/net/trace-events
93
+++ b/hw/net/trace-events
94
@@ -XXX,XX +XXX,XX @@ virtio_net_announce_notify(void) ""
95
virtio_net_announce_timer(int round) "%d"
96
virtio_net_handle_announce(int round) "%d"
97
virtio_net_post_load_device(void)
98
+
99
+# tulip.c
100
+tulip_reg_write(uint64_t addr, const char *name, int size, uint64_t val) "addr 0x%02"PRIx64" (%s) size %d value 0x%08"PRIx64
101
+tulip_reg_read(uint64_t addr, const char *name, int size, uint64_t val) "addr 0x%02"PRIx64" (%s) size %d value 0x%08"PRIx64
102
+tulip_receive(const uint8_t *buf, size_t len) "buf %p size %zu"
103
+tulip_descriptor(const char *prefix, uint32_t addr, uint32_t status, uint32_t control, uint32_t len1, uint32_t len2, uint32_t buf1, uint32_t buf2) "%s 0x%08x: status 0x%08x control 0x%03x len1 %4d len2 %4d buf1 0x%08x buf2 0x%08x"
104
+tulip_rx_state(const char *state) "RX %s"
105
+tulip_tx_state(const char *state) "TX %s"
106
+tulip_irq(uint32_t mask, uint32_t en, const char *state) "mask 0x%08x ie 0x%08x %s"
107
+tulip_mii_write(int phy, int reg, uint16_t data) "phy 0x%x reg 0x%x data 0x%04x"
108
+tulip_mii_read(int phy, int reg, uint16_t data) "phy 0x%x, reg 0x%x data 0x%04x"
109
+tulip_reset(void) ""
110
+tulip_setup_frame(void) ""
111
+tulip_setup_filter(int n, uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f) "%d: %02x:%02x:%02x:%02x:%02x:%02x"
112
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
113
new file mode 100644
114
index XXXXXXX..XXXXXXX
115
--- /dev/null
116
+++ b/hw/net/tulip.c
117
@@ -XXX,XX +XXX,XX @@
118
+/*
119
+ * QEMU TULIP Emulation
120
+ *
121
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
122
+ *
123
+ * This work is licensed under the GNU GPL license version 2 or later.
124
+ */
125
+
126
+#include "qemu/osdep.h"
127
+#include "qemu/log.h"
128
+#include "hw/irq.h"
129
+#include "hw/pci/pci.h"
130
+#include "hw/qdev-properties.h"
131
+#include "hw/nvram/eeprom93xx.h"
132
+#include "migration/vmstate.h"
133
+#include "sysemu/sysemu.h"
134
+#include "tulip.h"
135
+#include "trace.h"
136
+#include "net/eth.h"
137
+
138
+typedef struct TULIPState {
139
+ PCIDevice dev;
140
+ MemoryRegion io;
141
+ MemoryRegion memory;
142
+ NICConf c;
143
+ qemu_irq irq;
144
+ NICState *nic;
145
+ eeprom_t *eeprom;
146
+ uint32_t csr[16];
147
+
148
+ /* state for MII */
149
+ uint32_t old_csr9;
150
+ uint32_t mii_word;
151
+ uint32_t mii_bitcnt;
152
+
153
+ hwaddr current_rx_desc;
154
+ hwaddr current_tx_desc;
155
+
156
+ uint8_t rx_frame[2048];
157
+ uint8_t tx_frame[2048];
158
+ uint16_t tx_frame_len;
159
+ uint16_t rx_frame_len;
160
+ uint16_t rx_frame_size;
161
+
162
+ uint32_t rx_status;
163
+ uint8_t filter[16][6];
164
+} TULIPState;
165
+
166
+static const VMStateDescription vmstate_pci_tulip = {
167
+ .name = "tulip",
168
+ .fields = (VMStateField[]) {
169
+ VMSTATE_PCI_DEVICE(dev, TULIPState),
170
+ VMSTATE_UINT32_ARRAY(csr, TULIPState, 16),
171
+ VMSTATE_UINT32(old_csr9, TULIPState),
172
+ VMSTATE_UINT32(mii_word, TULIPState),
173
+ VMSTATE_UINT32(mii_bitcnt, TULIPState),
174
+ VMSTATE_UINT64(current_rx_desc, TULIPState),
175
+ VMSTATE_UINT64(current_tx_desc, TULIPState),
176
+ VMSTATE_BUFFER(rx_frame, TULIPState),
177
+ VMSTATE_BUFFER(tx_frame, TULIPState),
178
+ VMSTATE_UINT16(rx_frame_len, TULIPState),
179
+ VMSTATE_UINT16(tx_frame_len, TULIPState),
180
+ VMSTATE_UINT16(rx_frame_size, TULIPState),
181
+ VMSTATE_UINT32(rx_status, TULIPState),
182
+ VMSTATE_UINT8_2DARRAY(filter, TULIPState, 16, 6),
183
+ VMSTATE_END_OF_LIST()
184
+ }
185
+};
186
+
187
+static void tulip_desc_read(TULIPState *s, hwaddr p,
188
+ struct tulip_descriptor *desc)
189
+{
190
+ if (s->csr[0] & CSR0_DBO) {
191
+ desc->status = ldl_be_pci_dma(&s->dev, p);
192
+ desc->control = ldl_be_pci_dma(&s->dev, p + 4);
193
+ desc->buf_addr1 = ldl_be_pci_dma(&s->dev, p + 8);
194
+ desc->buf_addr2 = ldl_be_pci_dma(&s->dev, p + 12);
195
+ } else {
196
+ desc->status = ldl_le_pci_dma(&s->dev, p);
197
+ desc->control = ldl_le_pci_dma(&s->dev, p + 4);
198
+ desc->buf_addr1 = ldl_le_pci_dma(&s->dev, p + 8);
199
+ desc->buf_addr2 = ldl_le_pci_dma(&s->dev, p + 12);
200
+ }
201
+}
202
+
203
+static void tulip_desc_write(TULIPState *s, hwaddr p,
204
+ struct tulip_descriptor *desc)
205
+{
206
+ if (s->csr[0] & CSR0_DBO) {
207
+ stl_be_pci_dma(&s->dev, p, desc->status);
208
+ stl_be_pci_dma(&s->dev, p + 4, desc->control);
209
+ stl_be_pci_dma(&s->dev, p + 8, desc->buf_addr1);
210
+ stl_be_pci_dma(&s->dev, p + 12, desc->buf_addr2);
211
+ } else {
212
+ stl_le_pci_dma(&s->dev, p, desc->status);
213
+ stl_le_pci_dma(&s->dev, p + 4, desc->control);
214
+ stl_le_pci_dma(&s->dev, p + 8, desc->buf_addr1);
215
+ stl_le_pci_dma(&s->dev, p + 12, desc->buf_addr2);
216
+ }
217
+}
218
+
219
+static void tulip_update_int(TULIPState *s)
220
+{
221
+ uint32_t ie = s->csr[5] & s->csr[7];
222
+ bool assert = false;
223
+
224
+ s->csr[5] &= ~(CSR5_AIS | CSR5_NIS);
225
+
226
+ if (ie & (CSR5_TI | CSR5_TU | CSR5_RI | CSR5_GTE | CSR5_ERI)) {
227
+ s->csr[5] |= CSR5_NIS;
228
+ }
229
+
230
+ if (ie & (CSR5_LC | CSR5_GPI | CSR5_FBE | CSR5_LNF | CSR5_ETI | CSR5_RWT |
231
+ CSR5_RPS | CSR5_RU | CSR5_UNF | CSR5_LNP_ANC | CSR5_TJT |
232
+ CSR5_TPS)) {
233
+ s->csr[5] |= CSR5_AIS;
234
+ }
235
+
236
+ assert = s->csr[5] & s->csr[7] & (CSR5_AIS | CSR5_NIS);
237
+ trace_tulip_irq(s->csr[5], s->csr[7], assert ? "assert" : "deassert");
238
+ qemu_set_irq(s->irq, assert);
239
+}
240
+
241
+static bool tulip_rx_stopped(TULIPState *s)
242
+{
243
+ return ((s->csr[5] >> CSR5_RS_SHIFT) & CSR5_RS_MASK) == CSR5_RS_STOPPED;
244
+}
245
+
246
+static void tulip_dump_tx_descriptor(TULIPState *s,
247
+ struct tulip_descriptor *desc)
248
+{
249
+ trace_tulip_descriptor("TX ", s->current_tx_desc,
250
+ desc->status, desc->control >> 22,
251
+ desc->control & 0x7ff, (desc->control >> 11) & 0x7ff,
252
+ desc->buf_addr1, desc->buf_addr2);
253
+}
254
+
255
+static void tulip_dump_rx_descriptor(TULIPState *s,
256
+ struct tulip_descriptor *desc)
257
+{
258
+ trace_tulip_descriptor("RX ", s->current_rx_desc,
259
+ desc->status, desc->control >> 22,
260
+ desc->control & 0x7ff, (desc->control >> 11) & 0x7ff,
261
+ desc->buf_addr1, desc->buf_addr2);
262
+}
263
+
264
+static void tulip_next_rx_descriptor(TULIPState *s,
265
+ struct tulip_descriptor *desc)
266
+{
267
+ if (desc->control & RDES1_RER) {
268
+ s->current_rx_desc = s->csr[3];
269
+ } else if (desc->control & RDES1_RCH) {
270
+ s->current_rx_desc = desc->buf_addr2;
271
+ } else {
272
+ s->current_rx_desc += sizeof(struct tulip_descriptor) +
273
+ (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2);
274
+ }
275
+ s->current_rx_desc &= ~3ULL;
276
+}
277
+
278
+static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
279
+{
280
+ int len1 = (desc->control >> RDES1_BUF1_SIZE_SHIFT) & RDES1_BUF1_SIZE_MASK;
281
+ int len2 = (desc->control >> RDES1_BUF2_SIZE_SHIFT) & RDES1_BUF2_SIZE_MASK;
282
+ int len;
283
+
284
+ if (s->rx_frame_len && len1) {
285
+ if (s->rx_frame_len > len1) {
286
+ len = len1;
287
+ } else {
288
+ len = s->rx_frame_len;
289
+ }
290
+ pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame +
291
+ (s->rx_frame_size - s->rx_frame_len), len);
292
+ s->rx_frame_len -= len;
293
+ }
294
+
295
+ if (s->rx_frame_len && len2) {
296
+ if (s->rx_frame_len > len2) {
297
+ len = len2;
298
+ } else {
299
+ len = s->rx_frame_len;
300
+ }
301
+ pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame +
302
+ (s->rx_frame_size - s->rx_frame_len), len);
303
+ s->rx_frame_len -= len;
304
+ }
305
+}
306
+
307
+static bool tulip_filter_address(TULIPState *s, const uint8_t *addr)
308
+{
309
+ static const char broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
310
+ bool ret = false;
311
+ int i;
312
+
313
+ for (i = 0; i < 16 && ret == false; i++) {
314
+ if (!memcmp(&s->filter[i], addr, ETH_ALEN)) {
315
+ ret = true;
316
+ }
317
+ }
318
+
319
+ if (!memcmp(addr, broadcast, ETH_ALEN)) {
320
+ return true;
321
+ }
322
+
323
+ if (s->csr[6] & (CSR6_PR | CSR6_RA)) {
324
+ /* Promiscuous mode enabled */
325
+ s->rx_status |= RDES0_FF;
326
+ return true;
327
+ }
328
+
329
+ if ((s->csr[6] & CSR6_PM) && (addr[0] & 1)) {
330
+ /* Pass all Multicast enabled */
331
+ s->rx_status |= RDES0_MF;
332
+ return true;
333
+ }
334
+
335
+ if (s->csr[6] & CSR6_IF) {
336
+ ret ^= true;
337
+ }
338
+ return ret;
339
+}
340
+
341
+static ssize_t tulip_receive(TULIPState *s, const uint8_t *buf, size_t size)
342
+{
343
+ struct tulip_descriptor desc;
344
+
345
+ trace_tulip_receive(buf, size);
346
+
347
+ if (size < 14 || size > 2048 || s->rx_frame_len || tulip_rx_stopped(s)) {
348
+ return 0;
349
+ }
350
+
351
+ if (!tulip_filter_address(s, buf)) {
352
+ return size;
353
+ }
354
+
355
+ do {
356
+ tulip_desc_read(s, s->current_rx_desc, &desc);
357
+ tulip_dump_rx_descriptor(s, &desc);
358
+
359
+ if (!(desc.status & RDES0_OWN)) {
360
+ s->csr[5] |= CSR5_RU;
361
+ tulip_update_int(s);
362
+ return s->rx_frame_size - s->rx_frame_len;
363
+ }
364
+ desc.status = 0;
365
+
366
+ if (!s->rx_frame_len) {
367
+ s->rx_frame_size = size + 4;
368
+ s->rx_status = RDES0_LS |
369
+ ((s->rx_frame_size & RDES0_FL_MASK) << RDES0_FL_SHIFT);
370
+ desc.status |= RDES0_FS;
371
+ memcpy(s->rx_frame, buf, size);
372
+ s->rx_frame_len = s->rx_frame_size;
373
+ }
374
+
375
+ tulip_copy_rx_bytes(s, &desc);
376
+
377
+ if (!s->rx_frame_len) {
378
+ desc.status |= s->rx_status;
379
+ s->csr[5] |= CSR5_RI;
380
+ tulip_update_int(s);
381
+ }
382
+ tulip_dump_rx_descriptor(s, &desc);
383
+ tulip_desc_write(s, s->current_rx_desc, &desc);
384
+ tulip_next_rx_descriptor(s, &desc);
385
+ } while (s->rx_frame_len);
386
+ return size;
387
+}
388
+
389
+static ssize_t tulip_receive_nc(NetClientState *nc,
390
+ const uint8_t *buf, size_t size)
391
+{
392
+ return tulip_receive(qemu_get_nic_opaque(nc), buf, size);
393
+}
394
+
395
+
396
+static NetClientInfo net_tulip_info = {
397
+ .type = NET_CLIENT_DRIVER_NIC,
398
+ .size = sizeof(NICState),
399
+ .receive = tulip_receive_nc,
400
+};
401
+
402
+static const char *tulip_reg_name(const hwaddr addr)
403
+{
404
+ switch (addr) {
405
+ case CSR(0):
406
+ return "CSR0";
407
+
408
+ case CSR(1):
409
+ return "CSR1";
410
+
411
+ case CSR(2):
412
+ return "CSR2";
413
+
414
+ case CSR(3):
415
+ return "CSR3";
416
+
417
+ case CSR(4):
418
+ return "CSR4";
419
+
420
+ case CSR(5):
421
+ return "CSR5";
422
+
423
+ case CSR(6):
424
+ return "CSR6";
425
+
426
+ case CSR(7):
427
+ return "CSR7";
428
+
429
+ case CSR(8):
430
+ return "CSR8";
431
+
432
+ case CSR(9):
433
+ return "CSR9";
434
+
435
+ case CSR(10):
436
+ return "CSR10";
437
+
438
+ case CSR(11):
439
+ return "CSR11";
440
+
441
+ case CSR(12):
442
+ return "CSR12";
443
+
444
+ case CSR(13):
445
+ return "CSR13";
446
+
447
+ case CSR(14):
448
+ return "CSR14";
449
+
450
+ case CSR(15):
451
+ return "CSR15";
452
+
453
+ default:
454
+ break;
455
+ }
456
+ return "";
457
+}
458
+
459
+static const char *tulip_rx_state_name(int state)
460
+{
461
+ switch (state) {
462
+ case CSR5_RS_STOPPED:
463
+ return "STOPPED";
464
+
465
+ case CSR5_RS_RUNNING_FETCH:
466
+ return "RUNNING/FETCH";
467
+
468
+ case CSR5_RS_RUNNING_CHECK_EOR:
469
+ return "RUNNING/CHECK EOR";
470
+
471
+ case CSR5_RS_RUNNING_WAIT_RECEIVE:
472
+ return "WAIT RECEIVE";
473
+
474
+ case CSR5_RS_SUSPENDED:
475
+ return "SUSPENDED";
476
+
477
+ case CSR5_RS_RUNNING_CLOSE:
478
+ return "RUNNING/CLOSE";
479
+
480
+ case CSR5_RS_RUNNING_FLUSH:
481
+ return "RUNNING/FLUSH";
482
+
483
+ case CSR5_RS_RUNNING_QUEUE:
484
+ return "RUNNING/QUEUE";
485
+
486
+ default:
487
+ break;
488
+ }
489
+ return "";
490
+}
491
+
492
+static const char *tulip_tx_state_name(int state)
493
+{
494
+ switch (state) {
495
+ case CSR5_TS_STOPPED:
496
+ return "STOPPED";
497
+
498
+ case CSR5_TS_RUNNING_FETCH:
499
+ return "RUNNING/FETCH";
500
+
501
+ case CSR5_TS_RUNNING_WAIT_EOT:
502
+ return "RUNNING/WAIT EOT";
503
+
504
+ case CSR5_TS_RUNNING_READ_BUF:
505
+ return "RUNNING/READ BUF";
506
+
507
+ case CSR5_TS_RUNNING_SETUP:
508
+ return "RUNNING/SETUP";
509
+
510
+ case CSR5_TS_SUSPENDED:
511
+ return "SUSPENDED";
512
+
513
+ case CSR5_TS_RUNNING_CLOSE:
514
+ return "RUNNING/CLOSE";
515
+
516
+ default:
517
+ break;
518
+ }
519
+ return "";
520
+}
521
+
522
+static void tulip_update_rs(TULIPState *s, int state)
523
+{
524
+ s->csr[5] &= ~(CSR5_RS_MASK << CSR5_RS_SHIFT);
525
+ s->csr[5] |= (state & CSR5_RS_MASK) << CSR5_RS_SHIFT;
526
+ trace_tulip_rx_state(tulip_rx_state_name(state));
527
+}
528
+
529
+static uint16_t tulip_mdi_default[] = {
530
+ /* MDI Registers 0 - 6, 7 */
531
+ 0x3100, 0xf02c, 0x7810, 0x0000, 0x0501, 0x4181, 0x0000, 0x0000,
532
+ /* MDI Registers 8 - 15 */
533
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
534
+ /* MDI Registers 16 - 31 */
535
+ 0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
536
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
537
+};
538
+
539
+/* Readonly mask for MDI (PHY) registers */
540
+static const uint16_t tulip_mdi_mask[] = {
541
+ 0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000,
542
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
543
+ 0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
544
+ 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
545
+};
546
+
547
+static uint16_t tulip_mii_read(TULIPState *s, int phy, int reg)
548
+{
549
+ uint16_t ret = 0;
550
+ if (phy == 1) {
551
+ ret = tulip_mdi_default[reg];
552
+ }
553
+ trace_tulip_mii_read(phy, reg, ret);
554
+ return ret;
555
+}
556
+
557
+static void tulip_mii_write(TULIPState *s, int phy, int reg, uint16_t data)
558
+{
559
+ trace_tulip_mii_write(phy, reg, data);
560
+
561
+ if (phy != 1) {
562
+ return;
563
+ }
564
+
565
+ tulip_mdi_default[reg] &= ~tulip_mdi_mask[reg];
566
+ tulip_mdi_default[reg] |= (data & tulip_mdi_mask[reg]);
567
+}
568
+
569
+static void tulip_mii(TULIPState *s)
570
+{
571
+ uint32_t changed = s->old_csr9 ^ s->csr[9];
572
+ uint16_t data;
573
+ int op, phy, reg;
574
+
575
+ if (!(changed & CSR9_MDC)) {
576
+ return;
577
+ }
578
+
579
+ if (!(s->csr[9] & CSR9_MDC)) {
580
+ return;
581
+ }
582
+
583
+ s->mii_bitcnt++;
584
+ s->mii_word <<= 1;
585
+
586
+ if (s->csr[9] & CSR9_MDO && (s->mii_bitcnt < 16 ||
587
+ !(s->csr[9] & CSR9_MII))) {
588
+ /* write op or address bits */
589
+ s->mii_word |= 1;
590
+ }
591
+
592
+ if (s->mii_bitcnt >= 16 && (s->csr[9] & CSR9_MII)) {
593
+ if (s->mii_word & 0x8000) {
594
+ s->csr[9] |= CSR9_MDI;
595
+ } else {
596
+ s->csr[9] &= ~CSR9_MDI;
597
+ }
598
+ }
599
+
600
+ if (s->mii_word == 0xffffffff) {
601
+ s->mii_bitcnt = 0;
602
+ } else if (s->mii_bitcnt == 16) {
603
+ op = (s->mii_word >> 12) & 0x0f;
604
+ phy = (s->mii_word >> 7) & 0x1f;
605
+ reg = (s->mii_word >> 2) & 0x1f;
606
+
607
+ if (op == 6) {
608
+ s->mii_word = tulip_mii_read(s, phy, reg);
609
+ }
610
+ } else if (s->mii_bitcnt == 32) {
611
+ op = (s->mii_word >> 28) & 0x0f;
612
+ phy = (s->mii_word >> 23) & 0x1f;
613
+ reg = (s->mii_word >> 18) & 0x1f;
614
+ data = s->mii_word & 0xffff;
615
+
616
+ if (op == 5) {
617
+ tulip_mii_write(s, phy, reg, data);
618
+ }
619
+ }
620
+}
621
+
622
+static uint32_t tulip_csr9_read(TULIPState *s)
623
+{
624
+ if (s->csr[9] & CSR9_SR) {
625
+ if (eeprom93xx_read(s->eeprom)) {
626
+ s->csr[9] |= CSR9_SR_DO;
627
+ } else {
628
+ s->csr[9] &= ~CSR9_SR_DO;
629
+ }
630
+ }
631
+
632
+ tulip_mii(s);
633
+ return s->csr[9];
634
+}
635
+
636
+static void tulip_update_ts(TULIPState *s, int state)
637
+{
638
+ s->csr[5] &= ~(CSR5_TS_MASK << CSR5_TS_SHIFT);
639
+ s->csr[5] |= (state & CSR5_TS_MASK) << CSR5_TS_SHIFT;
640
+ trace_tulip_tx_state(tulip_tx_state_name(state));
641
+}
642
+
643
+static uint64_t tulip_read(void *opaque, hwaddr addr,
644
+ unsigned size)
645
+{
646
+ TULIPState *s = opaque;
647
+ uint64_t data = 0;
648
+
649
+ switch (addr) {
650
+ case CSR(9):
651
+ data = tulip_csr9_read(s);
652
+ break;
653
+
654
+ case CSR(12):
655
+ /* Fake autocompletion complete until we have PHY emulation */
656
+ data = 5 << CSR12_ANS_SHIFT;
657
+ break;
658
+
659
+ default:
660
+ if (addr & 7) {
661
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read access at unknown address"
662
+ " 0x%"PRIx64"\n", __func__, addr);
663
+ } else {
664
+ data = s->csr[addr >> 3];
665
+ }
666
+ break;
667
+ }
668
+ trace_tulip_reg_read(addr, tulip_reg_name(addr), size, data);
669
+ return data;
670
+}
671
+
672
+static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc)
673
+{
674
+ if (s->tx_frame_len) {
675
+ if ((s->csr[6] >> CSR6_OM_SHIFT) & CSR6_OM_MASK) {
676
+ /* Internal or external Loopback */
677
+ tulip_receive(s, s->tx_frame, s->tx_frame_len);
678
+ } else {
679
+ qemu_send_packet(qemu_get_queue(s->nic),
680
+ s->tx_frame, s->tx_frame_len);
681
+ }
682
+ }
683
+
684
+ if (desc->control & TDES1_IC) {
685
+ s->csr[5] |= CSR5_TI;
686
+ tulip_update_int(s);
687
+ }
688
+}
689
+
690
+static void tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
691
+{
692
+ int len1 = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK;
693
+ int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK;
694
+
695
+ if (len1) {
696
+ pci_dma_read(&s->dev, desc->buf_addr1,
697
+ s->tx_frame + s->tx_frame_len, len1);
698
+ s->tx_frame_len += len1;
699
+ }
700
+
701
+ if (len2) {
702
+ pci_dma_read(&s->dev, desc->buf_addr2,
703
+ s->tx_frame + s->tx_frame_len, len2);
704
+ s->tx_frame_len += len2;
705
+ }
706
+ desc->status = (len1 + len2) ? 0 : 0x7fffffff;
707
+}
708
+
709
+static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n)
710
+{
711
+ int offset = n * 12;
712
+
713
+ s->filter[n][0] = buf[offset];
714
+ s->filter[n][1] = buf[offset + 1];
715
+
716
+ s->filter[n][2] = buf[offset + 4];
717
+ s->filter[n][3] = buf[offset + 5];
718
+
719
+ s->filter[n][4] = buf[offset + 8];
720
+ s->filter[n][5] = buf[offset + 9];
721
+
722
+ trace_tulip_setup_filter(n, s->filter[n][5], s->filter[n][4],
723
+ s->filter[n][3], s->filter[n][2], s->filter[n][1], s->filter[n][0]);
724
+}
725
+
726
+static void tulip_setup_frame(TULIPState *s,
727
+ struct tulip_descriptor *desc)
728
+{
729
+ uint8_t buf[4096];
730
+ int len = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK;
731
+ int i;
732
+
733
+ trace_tulip_setup_frame();
734
+
735
+ if (len == 192) {
736
+ pci_dma_read(&s->dev, desc->buf_addr1, buf, len);
737
+ for (i = 0; i < 16; i++) {
738
+ tulip_setup_filter_addr(s, buf, i);
739
+ }
740
+ }
741
+
742
+ desc->status = 0x7fffffff;
743
+
744
+ if (desc->control & TDES1_IC) {
745
+ s->csr[5] |= CSR5_TI;
746
+ tulip_update_int(s);
747
+ }
748
+}
749
+
750
+static void tulip_next_tx_descriptor(TULIPState *s,
751
+ struct tulip_descriptor *desc)
752
+{
753
+ if (desc->control & TDES1_TER) {
754
+ s->current_tx_desc = s->csr[4];
755
+ } else if (desc->control & TDES1_TCH) {
756
+ s->current_tx_desc = desc->buf_addr2;
757
+ } else {
758
+ s->current_tx_desc += sizeof(struct tulip_descriptor) +
759
+ (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2);
760
+ }
761
+ s->current_tx_desc &= ~3ULL;
762
+}
763
+
764
+static uint32_t tulip_ts(TULIPState *s)
765
+{
766
+ return (s->csr[5] >> CSR5_TS_SHIFT) & CSR5_TS_MASK;
767
+}
768
+
769
+static void tulip_xmit_list_update(TULIPState *s)
770
+{
771
+ struct tulip_descriptor desc;
772
+
773
+ if (tulip_ts(s) != CSR5_TS_SUSPENDED) {
774
+ return;
775
+ }
776
+
777
+ for (;;) {
778
+ tulip_desc_read(s, s->current_tx_desc, &desc);
779
+ tulip_dump_tx_descriptor(s, &desc);
780
+
781
+ if (!(desc.status & TDES0_OWN)) {
782
+ tulip_update_ts(s, CSR5_TS_SUSPENDED);
783
+ s->csr[5] |= CSR5_TU;
784
+ tulip_update_int(s);
785
+ return;
786
+ }
787
+
788
+ if (desc.control & TDES1_SET) {
789
+ tulip_setup_frame(s, &desc);
790
+ } else {
791
+ if (desc.control & TDES1_FS) {
792
+ s->tx_frame_len = 0;
793
+ }
794
+
795
+ tulip_copy_tx_buffers(s, &desc);
796
+
797
+ if (desc.control & TDES1_LS) {
798
+ tulip_tx(s, &desc);
799
+ }
800
+ }
801
+ tulip_desc_write(s, s->current_tx_desc, &desc);
802
+ tulip_next_tx_descriptor(s, &desc);
803
+ }
804
+}
805
+
806
+static void tulip_csr9_write(TULIPState *s, uint32_t old_val,
807
+ uint32_t new_val)
808
+{
809
+ if (new_val & CSR9_SR) {
810
+ eeprom93xx_write(s->eeprom,
811
+ !!(new_val & CSR9_SR_CS),
812
+ !!(new_val & CSR9_SR_SK),
813
+ !!(new_val & CSR9_SR_DI));
814
+ }
815
+}
816
+
817
+static void tulip_reset(TULIPState *s)
818
+{
819
+ trace_tulip_reset();
820
+
821
+ s->csr[0] = 0xfe000000;
822
+ s->csr[1] = 0xffffffff;
823
+ s->csr[2] = 0xffffffff;
824
+ s->csr[5] = 0xf0000000;
825
+ s->csr[6] = 0x32000040;
826
+ s->csr[7] = 0xf3fe0000;
827
+ s->csr[8] = 0xe0000000;
828
+ s->csr[9] = 0xfff483ff;
829
+ s->csr[11] = 0xfffe0000;
830
+ s->csr[12] = 0x000000c6;
831
+ s->csr[13] = 0xffff0000;
832
+ s->csr[14] = 0xffffffff;
833
+ s->csr[15] = 0x8ff00000;
834
+}
835
+
836
+static void tulip_qdev_reset(DeviceState *dev)
837
+{
838
+ PCIDevice *d = PCI_DEVICE(dev);
839
+ TULIPState *s = TULIP(d);
840
+
841
+ tulip_reset(s);
842
+}
843
+
844
+static void tulip_write(void *opaque, hwaddr addr,
845
+ uint64_t data, unsigned size)
846
+{
847
+ TULIPState *s = opaque;
848
+ trace_tulip_reg_write(addr, tulip_reg_name(addr), size, data);
849
+
850
+ switch (addr) {
851
+ case CSR(0):
852
+ s->csr[0] = data;
853
+ if (data & CSR0_SWR) {
854
+ tulip_reset(s);
855
+ tulip_update_int(s);
856
+ }
857
+ break;
858
+
859
+ case CSR(1):
860
+ tulip_xmit_list_update(s);
861
+ break;
862
+
863
+ case CSR(2):
864
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
865
+ break;
866
+
867
+ case CSR(3):
868
+ s->csr[3] = data & ~3ULL;
869
+ s->current_rx_desc = s->csr[3];
870
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
871
+ break;
872
+
873
+ case CSR(4):
874
+ s->csr[4] = data & ~3ULL;
875
+ s->current_tx_desc = s->csr[4];
876
+ tulip_xmit_list_update(s);
877
+ break;
878
+
879
+ case CSR(5):
880
+ /* Status register, write clears bit */
881
+ s->csr[5] &= ~(data & (CSR5_TI | CSR5_TPS | CSR5_TU | CSR5_TJT |
882
+ CSR5_LNP_ANC | CSR5_UNF | CSR5_RI | CSR5_RU |
883
+ CSR5_RPS | CSR5_RWT | CSR5_ETI | CSR5_GTE |
884
+ CSR5_LNF | CSR5_FBE | CSR5_ERI | CSR5_AIS |
885
+ CSR5_NIS | CSR5_GPI | CSR5_LC));
886
+ tulip_update_int(s);
887
+ break;
888
+
889
+ case CSR(6):
890
+ s->csr[6] = data;
891
+ if (s->csr[6] & CSR6_SR) {
892
+ tulip_update_rs(s, CSR5_RS_RUNNING_WAIT_RECEIVE);
893
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
894
+ } else {
895
+ tulip_update_rs(s, CSR5_RS_STOPPED);
896
+ }
897
+
898
+ if (s->csr[6] & CSR6_ST) {
899
+ tulip_update_ts(s, CSR5_TS_SUSPENDED);
900
+ tulip_xmit_list_update(s);
901
+ } else {
902
+ tulip_update_ts(s, CSR5_TS_STOPPED);
903
+ }
904
+ break;
905
+
906
+ case CSR(7):
907
+ s->csr[7] = data;
908
+ tulip_update_int(s);
909
+ break;
910
+
911
+ case CSR(8):
912
+ s->csr[9] = data;
913
+ break;
914
+
915
+ case CSR(9):
916
+ tulip_csr9_write(s, s->csr[9], data);
917
+ /* don't clear MII read data */
918
+ s->csr[9] &= CSR9_MDI;
919
+ s->csr[9] |= (data & ~CSR9_MDI);
920
+ tulip_mii(s);
921
+ s->old_csr9 = s->csr[9];
922
+ break;
923
+
924
+ case CSR(10):
925
+ s->csr[10] = data;
926
+ break;
927
+
928
+ case CSR(11):
929
+ s->csr[11] = data;
930
+ break;
931
+
932
+ case CSR(12):
933
+ /* SIA Status register, some bits are cleared by writing 1 */
934
+ s->csr[12] &= ~(data & (CSR12_MRA | CSR12_TRA | CSR12_ARA));
935
+ break;
936
+
937
+ case CSR(13):
938
+ s->csr[13] = data;
939
+ break;
940
+
941
+ case CSR(14):
942
+ s->csr[14] = data;
943
+ break;
944
+
945
+ case CSR(15):
946
+ s->csr[15] = data;
947
+ break;
948
+
949
+ default:
950
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to CSR at unknown address "
951
+ "0x%"PRIx64"\n", __func__, addr);
952
+ break;
953
+ }
954
+}
955
+
956
+static const MemoryRegionOps tulip_ops = {
957
+ .read = tulip_read,
958
+ .write = tulip_write,
959
+ .endianness = DEVICE_LITTLE_ENDIAN,
960
+ .impl = {
961
+ .min_access_size = 4,
962
+ .max_access_size = 4,
963
+ },
964
+};
965
+
966
+static void tulip_idblock_crc(TULIPState *s, uint16_t *srom)
967
+{
968
+ int word, n;
969
+ int bit;
970
+ unsigned char bitval, crc;
971
+ const int len = 9;
972
+ n = 0;
973
+ crc = -1;
974
+
975
+ for (word = 0; word < len; word++) {
976
+ for (bit = 15; bit >= 0; bit--) {
977
+ if ((word == (len - 1)) && (bit == 7)) {
978
+ /*
979
+ * Insert the correct CRC result into input data stream
980
+ * in place.
981
+ */
982
+ srom[len - 1] = (srom[len - 1] & 0xff00) | (unsigned short)crc;
983
+ break;
984
+ }
985
+ n++;
986
+ bitval = ((srom[word] >> bit) & 1) ^ ((crc >> 7) & 1);
987
+ crc = crc << 1;
988
+ if (bitval == 1) {
989
+ crc ^= 6;
990
+ crc |= 0x01;
991
+ }
992
+ }
993
+ }
994
+}
995
+
996
+static uint16_t tulip_srom_crc(TULIPState *s, uint8_t *eeprom, size_t len)
997
+{
998
+ unsigned long crc = 0xffffffff;
999
+ unsigned long flippedcrc = 0;
1000
+ unsigned char currentbyte;
1001
+ unsigned int msb, bit, i;
1002
+
1003
+ for (i = 0; i < len; i++) {
1004
+ currentbyte = eeprom[i];
1005
+ for (bit = 0; bit < 8; bit++) {
1006
+ msb = (crc >> 31) & 1;
1007
+ crc <<= 1;
1008
+ if (msb ^ (currentbyte & 1)) {
1009
+ crc ^= 0x04c11db6;
1010
+ crc |= 0x00000001;
1011
+ }
1012
+ currentbyte >>= 1;
1013
+ }
1014
+ }
1015
+
1016
+ for (i = 0; i < 32; i++) {
1017
+ flippedcrc <<= 1;
1018
+ bit = crc & 1;
1019
+ crc >>= 1;
1020
+ flippedcrc += bit;
1021
+ }
1022
+ return (flippedcrc ^ 0xffffffff) & 0xffff;
1023
+}
1024
+
1025
+static const uint8_t eeprom_default[128] = {
1026
+ 0x3c, 0x10, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00,
1027
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1028
+ 0x56, 0x08, 0x04, 0x01, 0x00, 0x80, 0x48, 0xb3,
1029
+ 0x0e, 0xa7, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08,
1030
+ 0x01, 0x8d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x78,
1031
+ 0xe0, 0x01, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00,
1032
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1033
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1034
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1035
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1036
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1037
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x6b,
1038
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1039
+ 0x48, 0xb3, 0x0e, 0xa7, 0x40, 0x00, 0x00, 0x00,
1040
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1041
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1042
+};
1043
+
1044
+static void tulip_fill_eeprom(TULIPState *s)
1045
+{
1046
+ uint16_t *eeprom = eeprom93xx_data(s->eeprom);
1047
+ memcpy(eeprom, eeprom_default, 128);
1048
+
1049
+ /* patch in our mac address */
1050
+ eeprom[10] = cpu_to_le16(s->c.macaddr.a[0] | (s->c.macaddr.a[1] << 8));
1051
+ eeprom[11] = cpu_to_le16(s->c.macaddr.a[2] | (s->c.macaddr.a[3] << 8));
1052
+ eeprom[12] = cpu_to_le16(s->c.macaddr.a[4] | (s->c.macaddr.a[5] << 8));
1053
+ tulip_idblock_crc(s, eeprom);
1054
+ eeprom[63] = cpu_to_le16(tulip_srom_crc(s, (uint8_t *)eeprom, 126));
1055
+}
1056
+
1057
+static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp)
1058
+{
1059
+ TULIPState *s = DO_UPCAST(TULIPState, dev, pci_dev);
1060
+ uint8_t *pci_conf;
1061
+
1062
+ pci_conf = s->dev.config;
1063
+ pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */
1064
+
1065
+ s->eeprom = eeprom93xx_new(&pci_dev->qdev, 64);
1066
+ tulip_fill_eeprom(s);
1067
+
1068
+ memory_region_init_io(&s->io, OBJECT(&s->dev), &tulip_ops, s,
1069
+ "tulip-io", 128);
1070
+
1071
+ memory_region_init_io(&s->memory, OBJECT(&s->dev), &tulip_ops, s,
1072
+ "tulip-mem", 128);
1073
+
1074
+ pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
1075
+ pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->memory);
1076
+
1077
+ s->irq = pci_allocate_irq(&s->dev);
1078
+
1079
+ qemu_macaddr_default_if_unset(&s->c.macaddr);
1080
+
1081
+ s->nic = qemu_new_nic(&net_tulip_info, &s->c,
1082
+ object_get_typename(OBJECT(pci_dev)),
1083
+ pci_dev->qdev.id, s);
1084
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
1085
+}
1086
+
1087
+static void pci_tulip_exit(PCIDevice *pci_dev)
1088
+{
1089
+ TULIPState *s = DO_UPCAST(TULIPState, dev, pci_dev);
1090
+
1091
+ qemu_del_nic(s->nic);
1092
+ qemu_free_irq(s->irq);
1093
+ eeprom93xx_free(&pci_dev->qdev, s->eeprom);
1094
+}
1095
+
1096
+static void tulip_instance_init(Object *obj)
1097
+{
1098
+ PCIDevice *pci_dev = PCI_DEVICE(obj);
1099
+ TULIPState *d = DO_UPCAST(TULIPState, dev, pci_dev);
1100
+
1101
+ device_add_bootindex_property(obj, &d->c.bootindex,
1102
+ "bootindex", "/ethernet-phy@0",
1103
+ &pci_dev->qdev, NULL);
1104
+}
1105
+
1106
+static Property tulip_properties[] = {
1107
+ DEFINE_NIC_PROPERTIES(TULIPState, c),
1108
+ DEFINE_PROP_END_OF_LIST(),
1109
+};
1110
+
1111
+static void tulip_class_init(ObjectClass *klass, void *data)
1112
+{
1113
+ DeviceClass *dc = DEVICE_CLASS(klass);
1114
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1115
+
1116
+ k->realize = pci_tulip_realize;
1117
+ k->exit = pci_tulip_exit;
1118
+ k->vendor_id = PCI_VENDOR_ID_DEC;
1119
+ k->device_id = PCI_DEVICE_ID_DEC_21143;
1120
+ k->subsystem_vendor_id = 0x103c;
1121
+ k->subsystem_id = 0x104f;
1122
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
1123
+ dc->vmsd = &vmstate_pci_tulip;
1124
+ dc->props = tulip_properties;
1125
+ dc->reset = tulip_qdev_reset;
1126
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
1127
+}
1128
+
1129
+static const TypeInfo tulip_info = {
1130
+ .name = TYPE_TULIP,
1131
+ .parent = TYPE_PCI_DEVICE,
1132
+ .instance_size = sizeof(TULIPState),
1133
+ .class_init = tulip_class_init,
1134
+ .instance_init = tulip_instance_init,
1135
+ .interfaces = (InterfaceInfo[]) {
1136
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
1137
+ { },
1138
+ },
1139
+};
1140
+
1141
+static void tulip_register_types(void)
1142
+{
1143
+ type_register_static(&tulip_info);
1144
+}
1145
+
1146
+type_init(tulip_register_types)
1147
diff --git a/hw/net/tulip.h b/hw/net/tulip.h
1148
new file mode 100644
1149
index XXXXXXX..XXXXXXX
1150
--- /dev/null
1151
+++ b/hw/net/tulip.h
1152
@@ -XXX,XX +XXX,XX @@
1153
+#ifndef HW_TULIP_H
1154
+#define HW_TULIP_H
1155
+
1156
+#include "qemu/units.h"
1157
+#include "net/net.h"
1158
+
1159
+#define TYPE_TULIP "tulip"
1160
+#define TULIP(obj) OBJECT_CHECK(TULIPState, (obj), TYPE_TULIP)
1161
+
1162
+#define CSR(_x) ((_x) << 3)
1163
+
1164
+#define CSR0_SWR BIT(0)
1165
+#define CSR0_BAR BIT(1)
1166
+#define CSR0_DSL_SHIFT 2
1167
+#define CSR0_DSL_MASK 0x1f
1168
+#define CSR0_BLE BIT(7)
1169
+#define CSR0_PBL_SHIFT 8
1170
+#define CSR0_PBL_MASK 0x3f
1171
+#define CSR0_CAC_SHIFT 14
1172
+#define CSR0_CAC_MASK 0x3
1173
+#define CSR0_DAS 0x10000
1174
+#define CSR0_TAP_SHIFT 17
1175
+#define CSR0_TAP_MASK 0x7
1176
+#define CSR0_DBO 0x100000
1177
+#define CSR1_TPD 0x01
1178
+#define CSR0_RLE BIT(23)
1179
+#define CSR0_WIE BIT(24)
1180
+
1181
+#define CSR2_RPD 0x01
1182
+
1183
+#define CSR5_TI BIT(0)
1184
+#define CSR5_TPS BIT(1)
1185
+#define CSR5_TU BIT(2)
1186
+#define CSR5_TJT BIT(3)
1187
+#define CSR5_LNP_ANC BIT(4)
1188
+#define CSR5_UNF BIT(5)
1189
+#define CSR5_RI BIT(6)
1190
+#define CSR5_RU BIT(7)
1191
+#define CSR5_RPS BIT(8)
1192
+#define CSR5_RWT BIT(9)
1193
+#define CSR5_ETI BIT(10)
1194
+#define CSR5_GTE BIT(11)
1195
+#define CSR5_LNF BIT(12)
1196
+#define CSR5_FBE BIT(13)
1197
+#define CSR5_ERI BIT(14)
1198
+#define CSR5_AIS BIT(15)
1199
+#define CSR5_NIS BIT(16)
1200
+#define CSR5_RS_SHIFT 17
1201
+#define CSR5_RS_MASK 7
1202
+#define CSR5_TS_SHIFT 20
1203
+#define CSR5_TS_MASK 7
1204
+
1205
+#define CSR5_TS_STOPPED 0
1206
+#define CSR5_TS_RUNNING_FETCH 1
1207
+#define CSR5_TS_RUNNING_WAIT_EOT 2
1208
+#define CSR5_TS_RUNNING_READ_BUF 3
1209
+#define CSR5_TS_RUNNING_SETUP 5
1210
+#define CSR5_TS_SUSPENDED 6
1211
+#define CSR5_TS_RUNNING_CLOSE 7
1212
+
1213
+#define CSR5_RS_STOPPED 0
1214
+#define CSR5_RS_RUNNING_FETCH 1
1215
+#define CSR5_RS_RUNNING_CHECK_EOR 2
1216
+#define CSR5_RS_RUNNING_WAIT_RECEIVE 3
1217
+#define CSR5_RS_SUSPENDED 4
1218
+#define CSR5_RS_RUNNING_CLOSE 5
1219
+#define CSR5_RS_RUNNING_FLUSH 6
1220
+#define CSR5_RS_RUNNING_QUEUE 7
1221
+
1222
+#define CSR5_EB_SHIFT 23
1223
+#define CSR5_EB_MASK 7
1224
+
1225
+#define CSR5_GPI BIT(26)
1226
+#define CSR5_LC BIT(27)
1227
+
1228
+#define CSR6_HP BIT(0)
1229
+#define CSR6_SR BIT(1)
1230
+#define CSR6_HO BIT(2)
1231
+#define CSR6_PB BIT(3)
1232
+#define CSR6_IF BIT(4)
1233
+#define CSR6_SB BIT(5)
1234
+#define CSR6_PR BIT(6)
1235
+#define CSR6_PM BIT(7)
1236
+#define CSR6_FKD BIT(8)
1237
+#define CSR6_FD BIT(9)
1238
+
1239
+#define CSR6_OM_SHIFT 10
1240
+#define CSR6_OM_MASK 3
1241
+#define CSR6_OM_NORMAL 0
1242
+#define CSR6_OM_INT_LOOPBACK 1
1243
+#define CSR6_OM_EXT_LOOPBACK 2
1244
+
1245
+#define CSR6_FC BIT(12)
1246
+#define CSR6_ST BIT(13)
1247
+
1248
+
1249
+#define CSR6_TR_SHIFT 14
1250
+#define CSR6_TR_MASK 3
1251
+#define CSR6_TR_72 0
1252
+#define CSR6_TR_96 1
1253
+#define CSR6_TR_128 2
1254
+#define CSR6_TR_160 3
1255
+
1256
+#define CSR6_CA BIT(17)
1257
+#define CSR6_RA BIT(30)
1258
+#define CSR6_SC BIT(31)
1259
+
1260
+#define CSR7_TIM BIT(0)
1261
+#define CSR7_TSM BIT(1)
1262
+#define CSR7_TUM BIT(2)
1263
+#define CSR7_TJM BIT(3)
1264
+#define CSR7_LPM BIT(4)
1265
+#define CSR7_UNM BIT(5)
1266
+#define CSR7_RIM BIT(6)
1267
+#define CSR7_RUM BIT(7)
1268
+#define CSR7_RSM BIT(8)
1269
+#define CSR7_RWM BIT(9)
1270
+#define CSR7_TMM BIT(11)
1271
+#define CSR7_LFM BIT(12)
1272
+#define CSR7_SEM BIT(13)
1273
+#define CSR7_ERM BIT(14)
1274
+#define CSR7_AIM BIT(15)
1275
+#define CSR7_NIM BIT(16)
1276
+
1277
+#define CSR8_MISSED_FRAME_OVL BIT(16)
1278
+#define CSR8_MISSED_FRAME_CNT_MASK 0xffff
1279
+
1280
+#define CSR9_DATA_MASK 0xff
1281
+#define CSR9_SR_CS BIT(0)
1282
+#define CSR9_SR_SK BIT(1)
1283
+#define CSR9_SR_DI BIT(2)
1284
+#define CSR9_SR_DO BIT(3)
1285
+#define CSR9_REG BIT(10)
1286
+#define CSR9_SR BIT(11)
1287
+#define CSR9_BR BIT(12)
1288
+#define CSR9_WR BIT(13)
1289
+#define CSR9_RD BIT(14)
1290
+#define CSR9_MOD BIT(15)
1291
+#define CSR9_MDC BIT(16)
1292
+#define CSR9_MDO BIT(17)
1293
+#define CSR9_MII BIT(18)
1294
+#define CSR9_MDI BIT(19)
1295
+
1296
+#define CSR11_CON BIT(16)
1297
+#define CSR11_TIMER_MASK 0xffff
1298
+
1299
+#define CSR12_MRA BIT(0)
1300
+#define CSR12_LS100 BIT(1)
1301
+#define CSR12_LS10 BIT(2)
1302
+#define CSR12_APS BIT(3)
1303
+#define CSR12_ARA BIT(8)
1304
+#define CSR12_TRA BIT(9)
1305
+#define CSR12_NSN BIT(10)
1306
+#define CSR12_TRF BIT(11)
1307
+#define CSR12_ANS_SHIFT 12
1308
+#define CSR12_ANS_MASK 7
1309
+#define CSR12_LPN BIT(15)
1310
+#define CSR12_LPC_SHIFT 16
1311
+#define CSR12_LPC_MASK 0xffff
1312
+
1313
+#define CSR13_SRL BIT(0)
1314
+#define CSR13_CAC BIT(2)
1315
+#define CSR13_AUI BIT(3)
1316
+#define CSR13_SDM_SHIFT 4
1317
+#define CSR13_SDM_MASK 0xfff
1318
+
1319
+#define CSR14_ECEN BIT(0)
1320
+#define CSR14_LBK BIT(1)
1321
+#define CSR14_DREN BIT(2)
1322
+#define CSR14_LSE BIT(3)
1323
+#define CSR14_CPEN_SHIFT 4
1324
+#define CSR14_CPEN_MASK 3
1325
+#define CSR14_MBO BIT(6)
1326
+#define CSR14_ANE BIT(7)
1327
+#define CSR14_RSQ BIT(8)
1328
+#define CSR14_CSQ BIT(9)
1329
+#define CSR14_CLD BIT(10)
1330
+#define CSR14_SQE BIT(11)
1331
+#define CSR14_LTE BIT(12)
1332
+#define CSR14_APE BIT(13)
1333
+#define CSR14_SPP BIT(14)
1334
+#define CSR14_TAS BIT(15)
1335
+
1336
+#define CSR15_JBD BIT(0)
1337
+#define CSR15_HUJ BIT(1)
1338
+#define CSR15_JCK BIT(2)
1339
+#define CSR15_ABM BIT(3)
1340
+#define CSR15_RWD BIT(4)
1341
+#define CSR15_RWR BIT(5)
1342
+#define CSR15_LE1 BIT(6)
1343
+#define CSR15_LV1 BIT(7)
1344
+#define CSR15_TSCK BIT(8)
1345
+#define CSR15_FUSQ BIT(9)
1346
+#define CSR15_FLF BIT(10)
1347
+#define CSR15_LSD BIT(11)
1348
+#define CSR15_DPST BIT(12)
1349
+#define CSR15_FRL BIT(13)
1350
+#define CSR15_LE2 BIT(14)
1351
+#define CSR15_LV2 BIT(15)
1352
+
1353
+#define RDES0_OF BIT(0)
1354
+#define RDES0_CE BIT(1)
1355
+#define RDES0_DB BIT(2)
1356
+#define RDES0_RJ BIT(4)
1357
+#define RDES0_FT BIT(5)
1358
+#define RDES0_CS BIT(6)
1359
+#define RDES0_TL BIT(7)
1360
+#define RDES0_LS BIT(8)
1361
+#define RDES0_FS BIT(9)
1362
+#define RDES0_MF BIT(10)
1363
+#define RDES0_RF BIT(11)
1364
+#define RDES0_DT_SHIFT 12
1365
+#define RDES0_DT_MASK 3
1366
+#define RDES0_LE BIT(14)
1367
+#define RDES0_ES BIT(15)
1368
+#define RDES0_FL_SHIFT 16
1369
+#define RDES0_FL_MASK 0x3fff
1370
+#define RDES0_FF BIT(30)
1371
+#define RDES0_OWN BIT(31)
1372
+
1373
+#define RDES1_BUF1_SIZE_SHIFT 0
1374
+#define RDES1_BUF1_SIZE_MASK 0x7ff
1375
+
1376
+#define RDES1_BUF2_SIZE_SHIFT 11
1377
+#define RDES1_BUF2_SIZE_MASK 0x7ff
1378
+#define RDES1_RCH BIT(24)
1379
+#define RDES1_RER BIT(25)
1380
+
1381
+#define TDES0_DE BIT(0)
1382
+#define TDES0_UF BIT(1)
1383
+#define TDES0_LF BIT(2)
1384
+#define TDES0_CC_SHIFT 3
1385
+#define TDES0_CC_MASK 0xf
1386
+#define TDES0_HF BIT(7)
1387
+#define TDES0_EC BIT(8)
1388
+#define TDES0_LC BIT(9)
1389
+#define TDES0_NC BIT(10)
1390
+#define TDES0_LO BIT(11)
1391
+#define TDES0_TO BIT(14)
1392
+#define TDES0_ES BIT(15)
1393
+#define TDES0_OWN BIT(31)
1394
+
1395
+#define TDES1_BUF1_SIZE_SHIFT 0
1396
+#define TDES1_BUF1_SIZE_MASK 0x7ff
1397
+
1398
+#define TDES1_BUF2_SIZE_SHIFT 11
1399
+#define TDES1_BUF2_SIZE_MASK 0x7ff
1400
+
1401
+#define TDES1_FT0 BIT(22)
1402
+#define TDES1_DPD BIT(23)
1403
+#define TDES1_TCH BIT(24)
1404
+#define TDES1_TER BIT(25)
1405
+#define TDES1_AC BIT(26)
1406
+#define TDES1_SET BIT(27)
1407
+#define TDES1_FT1 BIT(28)
1408
+#define TDES1_FS BIT(29)
1409
+#define TDES1_LS BIT(30)
1410
+#define TDES1_IC BIT(31)
1411
+
1412
+struct tulip_descriptor {
1413
+ uint32_t status;
1414
+ uint32_t control;
1415
+ uint32_t buf_addr1;
1416
+ uint32_t buf_addr2;
1417
+};
1418
+
1419
+#endif
1420
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
1421
index XXXXXXX..XXXXXXX 100644
1422
--- a/include/hw/pci/pci_ids.h
1423
+++ b/include/hw/pci/pci_ids.h
1424
@@ -XXX,XX +XXX,XX @@
1425
#define PCI_DEVICE_ID_LSI_SAS0079 0x0079
1426
1427
#define PCI_VENDOR_ID_DEC 0x1011
1428
+#define PCI_DEVICE_ID_DEC_21143 0x0019
1429
#define PCI_DEVICE_ID_DEC_21154 0x0026
1430
1431
#define PCI_VENDOR_ID_CIRRUS 0x1013
25
--
1432
--
26
2.7.4
1433
2.5.0
27
1434
28
1435
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: "Michael S. Tsirkin" <mst@redhat.com>
2
2
3
We add the vnet_hdr_support option for colo-compare, default is disabled.
3
Post load hook in virtio vmsd is called early while device is processed,
4
If you use virtio-net-pci or other driver needs vnet_hdr, please enable it.
4
and when VirtIODevice core isn't fully initialized. Most device
5
You can use it for example:
5
specific code isn't ready to deal with a device in such state, and
6
-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support
6
behaves weirdly.
7
7
8
COLO-compare can get vnet header length from filter,
8
Add a new post_load hook in a device class instead. Devices should use
9
Add vnet_hdr_len to struct packet and output packet with
9
this unless they specifically want to verify the migration stream as
10
the vnet_hdr_len.
10
it's processed, e.g. for bounds checking.
11
11
12
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
12
Cc: qemu-stable@nongnu.org
13
Suggested-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
14
Cc: Mikhail Sennikovsky <mikhail.sennikovskii@cloud.ionos.com>
15
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
17
---
15
net/colo-compare.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------
18
hw/virtio/virtio.c | 7 +++++++
16
qemu-options.hx | 4 ++--
19
include/hw/virtio/virtio.h | 6 ++++++
17
2 files changed, 55 insertions(+), 9 deletions(-)
20
2 files changed, 13 insertions(+)
18
21
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
22
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo-compare.c
24
--- a/hw/virtio/virtio.c
22
+++ b/net/colo-compare.c
25
+++ b/hw/virtio/virtio.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct CompareState {
26
@@ -XXX,XX +XXX,XX @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
24
CharBackend chr_out;
25
SocketReadState pri_rs;
26
SocketReadState sec_rs;
27
+ bool vnet_hdr;
28
29
/* connection list: the connections belonged to this NIC could be found
30
* in this list.
31
@@ -XXX,XX +XXX,XX @@ enum {
32
33
static int compare_chr_send(CompareState *s,
34
const uint8_t *buf,
35
- uint32_t size);
36
+ uint32_t size,
37
+ uint32_t vnet_hdr_len);
38
39
static gint seq_sorter(Packet *a, Packet *b, gpointer data)
40
{
41
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
42
}
43
44
if (result) {
45
- ret = compare_chr_send(s, pkt->data, pkt->size);
46
+ ret = compare_chr_send(s,
47
+ pkt->data,
48
+ pkt->size,
49
+ pkt->vnet_hdr_len);
50
if (ret < 0) {
51
error_report("colo_send_primary_packet failed");
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
}
27
}
66
28
rcu_read_unlock();
67
+ if (s->vnet_hdr) {
29
68
+ /*
30
+ if (vdc->post_load) {
69
+ * We send vnet header len make other module(like filter-redirector)
31
+ ret = vdc->post_load(vdev);
70
+ * know how to parse net packet correctly.
32
+ if (ret) {
71
+ */
33
+ return ret;
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
+ }
34
+ }
77
+ }
35
+ }
78
+
36
+
79
ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
37
return 0;
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
}
38
}
85
39
86
+static bool compare_get_vnet_hdr(Object *obj, Error **errp)
40
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
87
+{
88
+ CompareState *s = COLO_COMPARE(obj);
89
+
90
+ return s->vnet_hdr;
91
+}
92
+
93
+static void compare_set_vnet_hdr(Object *obj,
94
+ bool value,
95
+ Error **errp)
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;
118
}
119
120
- net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, false);
121
- net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, false);
122
+ net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
123
+ net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr);
124
125
g_queue_init(&s->conn_list);
126
127
@@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data)
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
}
138
while (!g_queue_is_empty(&conn->secondary_list)) {
139
@@ -XXX,XX +XXX,XX @@ static void colo_compare_class_init(ObjectClass *oc, void *data)
140
141
static void colo_compare_init(Object *obj)
142
{
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
}
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
41
index XXXXXXX..XXXXXXX 100644
161
--- a/qemu-options.hx
42
--- a/include/hw/virtio/virtio.h
162
+++ b/qemu-options.hx
43
+++ b/include/hw/virtio/virtio.h
163
@@ -XXX,XX +XXX,XX @@ Dump the network traffic on netdev @var{dev} to the file specified by
44
@@ -XXX,XX +XXX,XX @@ typedef struct VirtioDeviceClass {
164
The file format is libpcap, so it can be analyzed with tools such as tcpdump
45
*/
165
or Wireshark.
46
void (*save)(VirtIODevice *vdev, QEMUFile *f);
166
47
int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id);
167
-@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},
48
+ /* Post load hook in vmsd is called early while device is processed, and
168
-outdev=@var{chardevid}
49
+ * when VirtIODevice isn't fully initialized. Devices should use this instead,
169
+@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid}[,vnet_hdr_support]
50
+ * unless they specifically want to verify the migration stream as it's
170
51
+ * processed, e.g. for bounds checking.
171
Colo-compare gets packet from primary_in@var{chardevid} and secondary_in@var{chardevid}, than compare primary packet with
52
+ */
172
secondary packet. If the packets are same, we will output primary
53
+ int (*post_load)(VirtIODevice *vdev);
173
packet to outdev@var{chardevid}, else we will notify colo-frame
54
const VMStateDescription *vmsd;
174
do checkpoint and send primary packet to outdev@var{chardevid}.
55
} VirtioDeviceClass;
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
56
179
--
57
--
180
2.7.4
58
2.5.0
181
59
182
60
diff view generated by jsdifflib
1
From: Michal Privoznik <mprivozn@redhat.com>
1
From: Mikhail Sennikovsky <mikhail.sennikovskii@cloud.ionos.com>
2
2
3
We have a function that checks if given number is power of two.
3
Currently offloads disabled by guest via the VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET
4
We should prefer it instead of expanding the check on our own.
4
command are not preserved on VM migration.
5
Instead all offloads reported by guest features (via VIRTIO_PCI_GUEST_FEATURES)
6
get enabled.
7
What happens is: first the VirtIONet::curr_guest_offloads gets restored and offloads
8
are getting set correctly:
5
9
6
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
10
#0 qemu_set_offload (nc=0x555556a11400, csum=1, tso4=0, tso6=0, ecn=0, ufo=0) at net/net.c:474
11
#1 virtio_net_apply_guest_offloads (n=0x555557701ca0) at hw/net/virtio-net.c:720
12
#2 virtio_net_post_load_device (opaque=0x555557701ca0, version_id=11) at hw/net/virtio-net.c:2334
13
#3 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577c80 <vmstate_virtio_net_device>, opaque=0x555557701ca0, version_id=11)
14
at migration/vmstate.c:168
15
#4 virtio_load (vdev=0x555557701ca0, f=0x5555569dc010, version_id=11) at hw/virtio/virtio.c:2197
16
#5 virtio_device_get (f=0x5555569dc010, opaque=0x555557701ca0, size=0, field=0x55555668cd00 <__compound_literal.5>) at hw/virtio/virtio.c:2036
17
#6 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577ce0 <vmstate_virtio_net>, opaque=0x555557701ca0, version_id=11) at migration/vmstate.c:143
18
#7 vmstate_load (f=0x5555569dc010, se=0x5555578189e0) at migration/savevm.c:829
19
#8 qemu_loadvm_section_start_full (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2211
20
#9 qemu_loadvm_state_main (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2395
21
#10 qemu_loadvm_state (f=0x5555569dc010) at migration/savevm.c:2467
22
#11 process_incoming_migration_co (opaque=0x0) at migration/migration.c:449
23
24
However later on the features are getting restored, and offloads get reset to
25
everything supported by features:
26
27
#0 qemu_set_offload (nc=0x555556a11400, csum=1, tso4=1, tso6=1, ecn=0, ufo=0) at net/net.c:474
28
#1 virtio_net_apply_guest_offloads (n=0x555557701ca0) at hw/net/virtio-net.c:720
29
#2 virtio_net_set_features (vdev=0x555557701ca0, features=5104441767) at hw/net/virtio-net.c:773
30
#3 virtio_set_features_nocheck (vdev=0x555557701ca0, val=5104441767) at hw/virtio/virtio.c:2052
31
#4 virtio_load (vdev=0x555557701ca0, f=0x5555569dc010, version_id=11) at hw/virtio/virtio.c:2220
32
#5 virtio_device_get (f=0x5555569dc010, opaque=0x555557701ca0, size=0, field=0x55555668cd00 <__compound_literal.5>) at hw/virtio/virtio.c:2036
33
#6 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577ce0 <vmstate_virtio_net>, opaque=0x555557701ca0, version_id=11) at migration/vmstate.c:143
34
#7 vmstate_load (f=0x5555569dc010, se=0x5555578189e0) at migration/savevm.c:829
35
#8 qemu_loadvm_section_start_full (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2211
36
#9 qemu_loadvm_state_main (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2395
37
#10 qemu_loadvm_state (f=0x5555569dc010) at migration/savevm.c:2467
38
#11 process_incoming_migration_co (opaque=0x0) at migration/migration.c:449
39
40
Fix this by preserving the state in saved_guest_offloads field and
41
pushing out offload initialization to the new post load hook.
42
43
Cc: qemu-stable@nongnu.org
44
Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@cloud.ionos.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
45
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
46
---
9
hw/net/virtio-net.c | 2 +-
47
hw/net/virtio-net.c | 27 ++++++++++++++++++++++++---
10
1 file changed, 1 insertion(+), 1 deletion(-)
48
include/hw/virtio/virtio-net.h | 2 ++
49
2 files changed, 26 insertions(+), 3 deletions(-)
11
50
12
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
51
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
13
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/virtio-net.c
53
--- a/hw/net/virtio-net.c
15
+++ b/hw/net/virtio-net.c
54
+++ b/hw/net/virtio-net.c
16
@@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
55
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
17
*/
56
n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
18
if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE ||
57
}
19
n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE ||
58
20
- (n->net_conf.rx_queue_size & (n->net_conf.rx_queue_size - 1))) {
59
- if (peer_has_vnet_hdr(n)) {
21
+ !is_power_of_2(n->net_conf.rx_queue_size)) {
60
- virtio_net_apply_guest_offloads(n);
22
error_setg(errp, "Invalid rx_queue_size (= %" PRIu16 "), "
61
- }
23
"must be a power of 2 between %d and %d.",
62
+ /*
24
n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE,
63
+ * curr_guest_offloads will be later overwritten by the
64
+ * virtio_set_features_nocheck call done from the virtio_load.
65
+ * Here we make sure it is preserved and restored accordingly
66
+ * in the virtio_net_post_load_virtio callback.
67
+ */
68
+ n->saved_guest_offloads = n->curr_guest_offloads;
69
70
virtio_net_set_queues(n);
71
72
@@ -XXX,XX +XXX,XX @@ static int virtio_net_post_load_device(void *opaque, int version_id)
73
return 0;
74
}
75
76
+static int virtio_net_post_load_virtio(VirtIODevice *vdev)
77
+{
78
+ VirtIONet *n = VIRTIO_NET(vdev);
79
+ /*
80
+ * The actual needed state is now in saved_guest_offloads,
81
+ * see virtio_net_post_load_device for detail.
82
+ * Restore it back and apply the desired offloads.
83
+ */
84
+ n->curr_guest_offloads = n->saved_guest_offloads;
85
+ if (peer_has_vnet_hdr(n)) {
86
+ virtio_net_apply_guest_offloads(n);
87
+ }
88
+
89
+ return 0;
90
+}
91
+
92
/* tx_waiting field of a VirtIONetQueue */
93
static const VMStateDescription vmstate_virtio_net_queue_tx_waiting = {
94
.name = "virtio-net-queue-tx_waiting",
95
@@ -XXX,XX +XXX,XX @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
96
vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
97
vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
98
vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO);
99
+ vdc->post_load = virtio_net_post_load_virtio;
100
vdc->vmsd = &vmstate_virtio_net_device;
101
}
102
103
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
104
index XXXXXXX..XXXXXXX 100644
105
--- a/include/hw/virtio/virtio-net.h
106
+++ b/include/hw/virtio/virtio-net.h
107
@@ -XXX,XX +XXX,XX @@ struct VirtIONet {
108
char *netclient_name;
109
char *netclient_type;
110
uint64_t curr_guest_offloads;
111
+ /* used on saved state restore phase to preserve the curr_guest_offloads */
112
+ uint64_t saved_guest_offloads;
113
AnnounceTimer announce_timer;
114
bool needs_vnet_hdr_swap;
115
bool mtu_bypass_backend;
25
--
116
--
26
2.7.4
117
2.5.0
27
118
28
119
diff view generated by jsdifflib
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
1
From: Fan Yang <Fan_Yang@sjtu.edu.cn>
2
2
3
We can use this property flush and send packet with vnet_hdr_len.
3
'colo_mark_tcp_pkt' should return 'true' when packets are the same, and
4
'false' otherwise. However, it returns 'true' when
5
'colo_compare_packet_payload' returns non-zero while
6
'colo_compare_packet_payload' is just a 'memcmp'. The result is that
7
COLO-compare reports inconsistent TCP packets when they are actually
8
the same.
4
9
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
10
Fixes: f449c9e549c ("colo: compare the packet based on the tcp sequence number")
11
Cc: qemu-stable@nongnu.org
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Signed-off-by: Fan Yang <Fan_Yang@sjtu.edu.cn>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
15
---
8
net/colo-compare.c | 8 ++++++--
16
net/colo-compare.c | 6 +++---
9
net/colo.c | 3 ++-
17
1 file changed, 3 insertions(+), 3 deletions(-)
10
net/colo.h | 4 +++-
11
net/filter-rewriter.c | 2 +-
12
4 files changed, 12 insertions(+), 5 deletions(-)
13
18
14
diff --git a/net/colo-compare.c b/net/colo-compare.c
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/net/colo-compare.c
21
--- a/net/colo-compare.c
17
+++ b/net/colo-compare.c
22
+++ b/net/colo-compare.c
18
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode)
23
@@ -XXX,XX +XXX,XX @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
19
Connection *conn;
24
*mark = 0;
20
25
21
if (mode == PRIMARY_IN) {
26
if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
22
- pkt = packet_new(s->pri_rs.buf, s->pri_rs.packet_len);
27
- if (colo_compare_packet_payload(ppkt, spkt,
23
+ pkt = packet_new(s->pri_rs.buf,
28
+ if (!colo_compare_packet_payload(ppkt, spkt,
24
+ s->pri_rs.packet_len,
29
ppkt->header_size, spkt->header_size,
25
+ s->pri_rs.vnet_hdr_len);
30
ppkt->payload_size)) {
26
} else {
31
*mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
27
- pkt = packet_new(s->sec_rs.buf, s->sec_rs.packet_len);
32
@@ -XXX,XX +XXX,XX @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
28
+ pkt = packet_new(s->sec_rs.buf,
33
29
+ s->sec_rs.packet_len,
34
/* one part of secondary packet payload still need to be compared */
30
+ s->sec_rs.vnet_hdr_len);
35
if (!after(ppkt->seq_end, spkt->seq_end)) {
31
}
36
- if (colo_compare_packet_payload(ppkt, spkt,
32
37
+ if (!colo_compare_packet_payload(ppkt, spkt,
33
if (parse_packet_early(pkt)) {
38
ppkt->header_size + ppkt->offset,
34
diff --git a/net/colo.c b/net/colo.c
39
spkt->header_size + spkt->offset,
35
index XXXXXXX..XXXXXXX 100644
40
ppkt->payload_size - ppkt->offset)) {
36
--- a/net/colo.c
41
@@ -XXX,XX +XXX,XX @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
37
+++ b/net/colo.c
42
/* primary packet is longer than secondary packet, compare
38
@@ -XXX,XX +XXX,XX @@ void connection_destroy(void *opaque)
43
* the same part and mark the primary packet offset
39
g_slice_free(Connection, conn);
44
*/
40
}
45
- if (colo_compare_packet_payload(ppkt, spkt,
41
46
+ if (!colo_compare_packet_payload(ppkt, spkt,
42
-Packet *packet_new(const void *data, int size)
47
ppkt->header_size + ppkt->offset,
43
+Packet *packet_new(const void *data, int size, int vnet_hdr_len)
48
spkt->header_size + spkt->offset,
44
{
49
spkt->payload_size - spkt->offset)) {
45
Packet *pkt = g_slice_new(Packet);
46
47
pkt->data = g_memdup(data, size);
48
pkt->size = size;
49
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
50
+ pkt->vnet_hdr_len = vnet_hdr_len;
51
52
return pkt;
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
--
50
--
90
2.7.4
51
2.5.0
91
52
92
53
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
This patch change the compare_chr_send() parameter from CharBackend to CompareState,
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/colo-compare.c | 14 +++++++-------
10
1 file changed, 7 insertions(+), 7 deletions(-)
11
12
diff --git a/net/colo-compare.c b/net/colo-compare.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/net/colo-compare.c
15
+++ b/net/colo-compare.c
16
@@ -XXX,XX +XXX,XX @@ enum {
17
SECONDARY_IN,
18
};
19
20
-static int compare_chr_send(CharBackend *out,
21
+static int compare_chr_send(CompareState *s,
22
const uint8_t *buf,
23
uint32_t size);
24
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
}
36
}
37
38
-static int compare_chr_send(CharBackend *out,
39
+static int compare_chr_send(CompareState *s,
40
const uint8_t *buf,
41
uint32_t size)
42
{
43
@@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CharBackend *out,
44
return 0;
45
}
46
47
- ret = qemu_chr_fe_write_all(out, (uint8_t *)&len, sizeof(len));
48
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len));
49
if (ret != sizeof(len)) {
50
goto err;
51
}
52
53
- ret = qemu_chr_fe_write_all(out, (uint8_t *)buf, size);
54
+ ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size);
55
if (ret != size) {
56
goto err;
57
}
58
@@ -XXX,XX +XXX,XX @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
59
60
if (packet_enqueue(s, PRIMARY_IN)) {
61
trace_colo_compare_main("primary: unsupported packet in");
62
- compare_chr_send(&s->chr_out, pri_rs->buf, pri_rs->packet_len);
63
+ compare_chr_send(s, pri_rs->buf, pri_rs->packet_len);
64
} else {
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
--
77
2.7.4
78
79
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
Make colo-compare and filter-rewriter can parse vnet packet.
4
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
net/colo.c | 6 +++---
9
1 file changed, 3 insertions(+), 3 deletions(-)
10
11
diff --git a/net/colo.c b/net/colo.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo.c
14
+++ b/net/colo.c
15
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
16
{
17
int network_length;
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
}
29
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
30
}
31
32
network_length = pkt->ip->ip_hl * 4;
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
}
38
--
39
2.7.4
40
41
diff view generated by jsdifflib
Deleted patch
1
From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
2
1
3
COLO-Proxy just focus on packet payload, so we skip vnet header.
4
5
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
---
8
net/colo-compare.c | 8 ++++++--
9
1 file changed, 6 insertions(+), 2 deletions(-)
10
11
diff --git a/net/colo-compare.c b/net/colo-compare.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/net/colo-compare.c
14
+++ b/net/colo-compare.c
15
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
16
sec_ip_src, sec_ip_dst);
17
}
18
19
+ offset = ppkt->vnet_hdr_len + offset;
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
--
40
2.7.4
41
42
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-rewriter, 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-rewriter,id=rew0,netdev=hn0,queue=all,vnet_hdr_support
7
8
We get the vnet_hdr_len from NetClientState that make us
9
parse net packet correctly.
10
11
Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
14
net/filter-rewriter.c | 37 ++++++++++++++++++++++++++++++++++++-
15
qemu-options.hx | 4 ++--
16
2 files changed, 38 insertions(+), 3 deletions(-)
17
18
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/net/filter-rewriter.c
21
+++ b/net/filter-rewriter.c
22
@@ -XXX,XX +XXX,XX @@
23
#include "qemu-common.h"
24
#include "qapi/error.h"
25
#include "qapi/qmp/qerror.h"
26
+#include "qemu/error-report.h"
27
#include "qapi-visit.h"
28
#include "qom/object.h"
29
#include "qemu/main-loop.h"
30
@@ -XXX,XX +XXX,XX @@ typedef struct RewriterState {
31
NetQueue *incoming_queue;
32
/* hashtable to save connection */
33
GHashTable *connection_track_table;
34
+ bool vnet_hdr;
35
} RewriterState;
36
37
static void filter_rewriter_flush(NetFilterState *nf)
38
@@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
39
ConnectionKey key;
40
Packet *pkt;
41
ssize_t size = iov_size(iov, iovcnt);
42
+ ssize_t vnet_hdr_len = 0;
43
char *buf = g_malloc0(size);
44
45
iov_to_buf(iov, iovcnt, 0, buf, size);
46
- pkt = packet_new(buf, size, 0);
47
+
48
+ if (s->vnet_hdr) {
49
+ vnet_hdr_len = nf->netdev->vnet_hdr_len;
50
+ }
51
+
52
+ pkt = packet_new(buf, size, vnet_hdr_len);
53
g_free(buf);
54
55
/*
56
@@ -XXX,XX +XXX,XX @@ static void colo_rewriter_setup(NetFilterState *nf, Error **errp)
57
s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
58
}
59
60
+static bool filter_rewriter_get_vnet_hdr(Object *obj, Error **errp)
61
+{
62
+ RewriterState *s = FILTER_COLO_REWRITER(obj);
63
+
64
+ return s->vnet_hdr;
65
+}
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
{
88
NetFilterClass *nfc = NETFILTER_CLASS(oc);
89
@@ -XXX,XX +XXX,XX @@ static const TypeInfo colo_rewriter_info = {
90
.name = TYPE_FILTER_REWRITER,
91
.parent = TYPE_NETFILTER,
92
.class_init = colo_rewriter_class_init,
93
+ .instance_init = filter_rewriter_init,
94
.instance_size = sizeof(RewriterState),
95
};
96
97
diff --git a/qemu-options.hx b/qemu-options.hx
98
index XXXXXXX..XXXXXXX 100644
99
--- a/qemu-options.hx
100
+++ 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
102
be the same. we can just use indev or outdev, but at least one of indev or outdev
103
need to be specified.
104
105
-@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid}[,queue=@var{all|rx|tx}]
106
+@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx},[vnet_hdr_support]
107
108
Filter-rewriter is a part of COLO project.It will rewrite tcp packet to
109
secondary from primary to keep secondary tcp connection,and rewrite
110
tcp packet to primary from secondary make tcp packet can be handled by
111
-client.
112
+client.if it has the vnet_hdr_support flag, we can parse packet with vnet header.
113
114
usage:
115
colo secondary:
116
--
117
2.7.4
118
119
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