1
The following changes since commit 43ab9a5376c95c61ae898a222c4d04bdf60e239b:
1
The following changes since commit e607bbee553cfe73072870cef458cfa4e78133e2:
2
2
3
hw/i386/vmport: fix missing definitions with non-log trace backends (2017-12-21 22:52:28 +0000)
3
Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2018-01-26.for-upstream' into staging (2018-01-26 14:24:25 +0000)
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 0065e915192cdf83c2700bb377e5323c2649476e:
9
for you to fetch changes up to bf4835a4d5338bb7424827715df22570a8adc67c:
10
10
11
qemu-doc: Update the deprecation information of -tftp, -bootp, -redir and -smb (2017-12-22 10:06:05 +0800)
11
MAINTAINERS: update Dmitry Fleytman email (2018-01-29 16:05:38 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Ed Swierk via Qemu-devel (2):
16
Mao Zhongyi (2):
17
e1000, e1000e: Move per-packet TX offload flags out of context state
17
colo: modified the payload compare function
18
e1000: Separate TSO and non-TSO contexts, fixing UDP TX corruption
18
colo: compare the packet based on the tcp sequence number
19
19
20
Mark Cave-Ayland (13):
20
Philippe Mathieu-Daudé (1):
21
net: move CRC32 calculation from compute_mcast_idx() into its own net_crc32() function
21
MAINTAINERS: update Dmitry Fleytman email
22
net: introduce net_crc32_le() function
23
pcnet: switch pcnet over to use net_crc32_le()
24
eepro100: switch eepro100 e100_compute_mcast_idx() over to use net_crc32()
25
sunhme: switch sunhme over to use net_crc32_le()
26
sungem: fix multicast filter CRC calculation
27
eepro100: use inline net_crc32() and bitshift instead of compute_mcast_idx()
28
opencores_eth: use inline net_crc32() and bitshift instead of compute_mcast_idx()
29
lan9118: use inline net_crc32() and bitshift instead of compute_mcast_idx()
30
ftgmac100: use inline net_crc32() and bitshift instead of compute_mcast_idx()
31
ne2000: use inline net_crc32() and bitshift instead of compute_mcast_idx()
32
rtl8139: use inline net_crc32() and bitshift instead of compute_mcast_idx()
33
net: remove unused compute_mcast_idx() function
34
22
35
Thomas Huth (3):
23
Thomas Huth (3):
36
net: Remove the legacy "-net channel" parameter
24
net: Allow hubports to connect to other netdevs
37
qemu-doc: The "-net nic" option can be used with "netdev=...", too
25
net: Allow netdevs to be used with 'hostfwd_add' and 'hostfwd_remove'
38
qemu-doc: Update the deprecation information of -tftp, -bootp, -redir and -smb
26
qemu-doc: Get rid of "vlan=X" example in the documentation
39
27
40
hw/net/e1000.c | 92 ++++++++++++++++++++++++++++----------------------
28
MAINTAINERS | 8 +-
41
hw/net/e1000e.c | 4 +--
29
hmp-commands.hx | 4 +-
42
hw/net/e1000e_core.c | 16 ++++-----
30
net/colo-compare.c | 411 +++++++++++++++++++++++++++++++++--------------------
43
hw/net/e1000e_core.h | 2 ++
31
net/colo.c | 9 ++
44
hw/net/e1000x_common.h | 2 --
32
net/colo.h | 15 ++
45
hw/net/eepro100.c | 32 +++---------------
33
net/hub.c | 27 +++-
46
hw/net/ftgmac100.c | 2 +-
34
net/hub.h | 3 +-
47
hw/net/lan9118.c | 3 +-
35
net/net.c | 2 +-
48
hw/net/ne2000.c | 4 ++-
36
net/slirp.c | 33 +++--
49
hw/net/opencores_eth.c | 3 +-
37
net/trace-events | 2 +-
50
hw/net/pcnet.c | 22 ++----------
38
qapi/net.json | 4 +-
51
hw/net/rtl8139.c | 2 +-
39
qemu-options.hx | 12 +-
52
hw/net/sungem.c | 5 ++-
40
12 files changed, 347 insertions(+), 183 deletions(-)
53
hw/net/sunhme.c | 25 +-------------
54
include/net/net.h | 5 ++-
55
include/net/slirp.h | 2 --
56
net/net.c | 40 +++++++++++++++-------
57
net/slirp.c | 34 -------------------
58
qemu-doc.texi | 38 +++++++++++----------
59
qemu-options.hx | 14 ++++----
60
20 files changed, 144 insertions(+), 203 deletions(-)
61
41
62
42
diff view generated by jsdifflib
1
From: Ed Swierk via Qemu-devel <qemu-devel@nongnu.org>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
sum_needed and cptse flags are received from the guest within each
3
Modified the function colo_packet_compare_common to prepare for the
4
transmit data descriptor. They are not part of the offload context;
4
tcp packet comparison in the next patch.
5
instead, they determine how to apply a previously received context to
6
the packet being transmitted:
7
5
8
- If cptse is set, perform both segmentation and checksum offload
6
Cc: Zhang Chen <zhangckid@gmail.com>
9
using the parameters in the TSO context; otherwise just do checksum
7
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
10
offload. (Currently the e1000 device incorrectly stores only one
8
Cc: Jason Wang <jasowang@redhat.com>
11
context, which will be fixed in a subsequent patch.)
12
9
13
- Depending on the bits set in sum_needed, possibly perform L4
10
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
14
checksum offload and/or IP checksum offload, using the parameters in
11
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
15
the appropriate context.
12
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
16
13
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
17
Move these flags out of struct e1000x_txd_props, which is otherwise
18
dedicated to storing values from a context descriptor, and into the
19
per-packet TX struct.
20
21
Signed-off-by: Ed Swierk <eswierk@skyportsystems.com>
22
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
Signed-off-by: Jason Wang <jasowang@redhat.com>
23
---
15
---
24
hw/net/e1000.c | 30 ++++++++++++++++--------------
16
net/colo-compare.c | 88 +++++++++++++++++++++++++++---------------------------
25
hw/net/e1000e.c | 4 ++--
17
1 file changed, 44 insertions(+), 44 deletions(-)
26
hw/net/e1000e_core.c | 16 ++++++++--------
27
hw/net/e1000e_core.h | 2 ++
28
hw/net/e1000x_common.h | 2 --
29
5 files changed, 28 insertions(+), 26 deletions(-)
30
18
31
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
19
diff --git a/net/colo-compare.c b/net/colo-compare.c
32
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/net/e1000.c
21
--- a/net/colo-compare.c
34
+++ b/hw/net/e1000.c
22
+++ b/net/colo-compare.c
35
@@ -XXX,XX +XXX,XX @@ typedef struct E1000State_st {
23
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
36
unsigned char data[0x10000];
24
* return: 0 means packet same
37
uint16_t size;
25
* > 0 || < 0 means packet different
38
unsigned char vlan_needed;
26
*/
39
+ unsigned char sum_needed;
27
-static int colo_packet_compare_common(Packet *ppkt,
40
+ bool cptse;
28
- Packet *spkt,
41
e1000x_txd_props props;
29
- int poffset,
42
uint16_t tso_frames;
30
- int soffset)
43
} tx;
31
+static int colo_compare_packet_payload(Packet *ppkt,
44
@@ -XXX,XX +XXX,XX @@ xmit_seg(E1000State *s)
32
+ Packet *spkt,
45
unsigned int frames = s->tx.tso_frames, css, sofar;
33
+ uint16_t poffset,
46
struct e1000_tx *tp = &s->tx;
34
+ uint16_t soffset,
47
35
+ uint16_t len)
48
- if (tp->props.tse && tp->props.cptse) {
36
+
49
+ if (tp->props.tse && tp->cptse) {
37
{
50
css = tp->props.ipcss;
38
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
51
DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
39
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
52
frames, tp->size, css);
40
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt,
53
@@ -XXX,XX +XXX,XX @@ xmit_seg(E1000State *s)
41
sec_ip_src, sec_ip_dst);
54
}
55
} else /* UDP */
56
stw_be_p(tp->data+css+4, len);
57
- if (tp->props.sum_needed & E1000_TXD_POPTS_TXSM) {
58
+ if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
59
unsigned int phsum;
60
// add pseudo-header length before checksum calculation
61
void *sp = tp->data + tp->props.tucso;
62
@@ -XXX,XX +XXX,XX @@ xmit_seg(E1000State *s)
63
tp->tso_frames++;
64
}
42
}
65
43
66
- if (tp->props.sum_needed & E1000_TXD_POPTS_TXSM) {
44
- poffset = ppkt->vnet_hdr_len + poffset;
67
+ if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
45
- soffset = ppkt->vnet_hdr_len + soffset;
68
putsum(tp->data, tp->size, tp->props.tucso,
46
-
69
tp->props.tucss, tp->props.tucse);
47
- if (ppkt->size - poffset == spkt->size - soffset) {
48
- return memcmp(ppkt->data + poffset,
49
- spkt->data + soffset,
50
- spkt->size - soffset);
51
- } else {
52
- trace_colo_compare_main("Net packet size are not the same");
53
- return -1;
54
- }
55
+ return memcmp(ppkt->data + poffset, spkt->data + soffset, len);
56
}
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
60
* the secondary guest's timestamp. COLO just focus on payload,
61
* so we just need skip this field.
62
*/
63
- if (ptcp->th_off > 5) {
64
- ptrdiff_t ptcp_offset, stcp_offset;
65
66
- ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
67
- + (ptcp->th_off * 4) - ppkt->vnet_hdr_len;
68
- stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
69
- + (stcp->th_off * 4) - spkt->vnet_hdr_len;
70
+ ptrdiff_t ptcp_offset, stcp_offset;
71
72
- /*
73
- * When network is busy, some tcp options(like sack) will unpredictable
74
- * occur in primary side or secondary side. it will make packet size
75
- * not same, but the two packet's payload is identical. colo just
76
- * care about packet payload, so we skip the option field.
77
- */
78
- res = colo_packet_compare_common(ppkt, spkt, ptcp_offset, stcp_offset);
79
- } else if (ptcp->th_sum == stcp->th_sum) {
80
- res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN, ETH_HLEN);
81
+ ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
82
+ + (ptcp->th_off << 2) - ppkt->vnet_hdr_len;
83
+ stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
84
+ + (stcp->th_off << 2) - spkt->vnet_hdr_len;
85
+ if (ppkt->size - ptcp_offset == spkt->size - stcp_offset) {
86
+ res = colo_compare_packet_payload(ppkt, spkt,
87
+ ptcp_offset, stcp_offset,
88
+ ppkt->size - ptcp_offset);
89
} else {
90
+ trace_colo_compare_main("TCP: payload size of packets are different");
91
res = -1;
70
}
92
}
71
- if (tp->props.sum_needed & E1000_TXD_POPTS_IXSM) {
93
72
+ if (tp->sum_needed & E1000_TXD_POPTS_IXSM) {
94
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
73
putsum(tp->data, tp->size, tp->props.ipcso,
95
*/
74
tp->props.ipcss, tp->props.ipcse);
96
static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
97
{
98
- int ret;
99
- int network_header_length = ppkt->ip->ip_hl * 4;
100
+ uint16_t network_header_length = ppkt->ip->ip_hl << 2;
101
+ uint16_t offset = network_header_length + ETH_HLEN + ppkt->vnet_hdr_len;
102
103
trace_colo_compare_main("compare udp");
104
105
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
106
* other field like TOS,TTL,IP Checksum. we only need to compare
107
* the ip payload here.
108
*/
109
- ret = colo_packet_compare_common(ppkt, spkt,
110
- network_header_length + ETH_HLEN,
111
- network_header_length + ETH_HLEN);
112
-
113
- if (ret) {
114
+ if (ppkt->size != spkt->size) {
115
+ trace_colo_compare_main("UDP: payload size of packets are different");
116
+ return -1;
117
+ }
118
+ if (colo_compare_packet_payload(ppkt, spkt, offset, offset,
119
+ ppkt->size - offset)) {
120
trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
121
trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
122
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
123
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
124
qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
125
spkt->size);
126
}
127
+ return -1;
128
+ } else {
129
+ return 0;
75
}
130
}
76
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
131
-
77
} else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
132
- return ret;
78
// data descriptor
133
}
79
if (tp->size == 0) {
134
80
- tp->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;
135
/*
81
+ tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
136
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
82
}
137
*/
83
- tp->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
138
static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
84
+ tp->cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
139
{
85
} else {
140
- int network_header_length = ppkt->ip->ip_hl * 4;
86
// legacy descriptor
141
+ uint16_t network_header_length = ppkt->ip->ip_hl << 2;
87
- tp->props.cptse = 0;
142
+ uint16_t offset = network_header_length + ETH_HLEN + ppkt->vnet_hdr_len;
88
+ tp->cptse = 0;
143
144
trace_colo_compare_main("compare icmp");
145
146
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
147
* other field like TOS,TTL,IP Checksum. we only need to compare
148
* the ip payload here.
149
*/
150
- if (colo_packet_compare_common(ppkt, spkt,
151
- network_header_length + ETH_HLEN,
152
- network_header_length + ETH_HLEN)) {
153
+ if (ppkt->size != spkt->size) {
154
+ trace_colo_compare_main("ICMP: payload size of packets are different");
155
+ return -1;
156
+ }
157
+ if (colo_compare_packet_payload(ppkt, spkt, offset, offset,
158
+ ppkt->size - offset)) {
159
trace_colo_compare_icmp_miscompare("primary pkt size",
160
ppkt->size);
161
trace_colo_compare_icmp_miscompare("Secondary pkt size",
162
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
163
*/
164
static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
165
{
166
+ uint16_t offset = ppkt->vnet_hdr_len;
167
+
168
trace_colo_compare_main("compare other");
169
if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
170
char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
171
@@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
172
sec_ip_src, sec_ip_dst);
89
}
173
}
90
174
91
if (e1000x_vlan_enabled(s->mac_reg) &&
175
- return colo_packet_compare_common(ppkt, spkt, 0, 0);
92
e1000x_is_vlan_txd(txd_lower) &&
176
+ if (ppkt->size != spkt->size) {
93
- (tp->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) {
177
+ trace_colo_compare_main("Other: payload size of packets are different");
94
+ (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
178
+ return -1;
95
tp->vlan_needed = 1;
179
+ }
96
stw_be_p(tp->vlan_header,
180
+ return colo_compare_packet_payload(ppkt, spkt, offset, offset,
97
le16_to_cpu(s->mac_reg[VET]));
181
+ ppkt->size - offset);
98
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
99
}
100
101
addr = le64_to_cpu(dp->buffer_addr);
102
- if (tp->props.tse && tp->props.cptse) {
103
+ if (tp->props.tse && tp->cptse) {
104
msh = tp->props.hdr_len + tp->props.mss;
105
do {
106
bytes = split_size;
107
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
108
}
109
split_size -= bytes;
110
} while (bytes && split_size);
111
- } else if (!tp->props.tse && tp->props.cptse) {
112
+ } else if (!tp->props.tse && tp->cptse) {
113
// context descriptor TSE is not set, while data descriptor TSE is set
114
DBGOUT(TXERR, "TCP segmentation error\n");
115
} else {
116
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
117
118
if (!(txd_lower & E1000_TXD_CMD_EOP))
119
return;
120
- if (!(tp->props.tse && tp->props.cptse && tp->size < tp->props.hdr_len)) {
121
+ if (!(tp->props.tse && tp->cptse && tp->size < tp->props.hdr_len)) {
122
xmit_seg(s);
123
}
124
tp->tso_frames = 0;
125
- tp->props.sum_needed = 0;
126
+ tp->sum_needed = 0;
127
tp->vlan_needed = 0;
128
tp->size = 0;
129
- tp->props.cptse = 0;
130
+ tp->cptse = 0;
131
}
182
}
132
183
133
static uint32_t
184
static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
134
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_e1000 = {
135
VMSTATE_UINT16(tx.props.mss, E1000State),
136
VMSTATE_UINT16(tx.size, E1000State),
137
VMSTATE_UINT16(tx.tso_frames, E1000State),
138
- VMSTATE_UINT8(tx.props.sum_needed, E1000State),
139
+ VMSTATE_UINT8(tx.sum_needed, E1000State),
140
VMSTATE_INT8(tx.props.ip, E1000State),
141
VMSTATE_INT8(tx.props.tcp, E1000State),
142
VMSTATE_BUFFER(tx.header, E1000State),
143
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/hw/net/e1000e.c
146
+++ b/hw/net/e1000e.c
147
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription e1000e_vmstate_tx = {
148
.version_id = 1,
149
.minimum_version_id = 1,
150
.fields = (VMStateField[]) {
151
- VMSTATE_UINT8(props.sum_needed, struct e1000e_tx),
152
+ VMSTATE_UINT8(sum_needed, struct e1000e_tx),
153
VMSTATE_UINT8(props.ipcss, struct e1000e_tx),
154
VMSTATE_UINT8(props.ipcso, struct e1000e_tx),
155
VMSTATE_UINT16(props.ipcse, struct e1000e_tx),
156
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription e1000e_vmstate_tx = {
157
VMSTATE_INT8(props.ip, struct e1000e_tx),
158
VMSTATE_INT8(props.tcp, struct e1000e_tx),
159
VMSTATE_BOOL(props.tse, struct e1000e_tx),
160
- VMSTATE_BOOL(props.cptse, struct e1000e_tx),
161
+ VMSTATE_BOOL(cptse, struct e1000e_tx),
162
VMSTATE_BOOL(skip_cp, struct e1000e_tx),
163
VMSTATE_END_OF_LIST()
164
}
165
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/hw/net/e1000e_core.c
168
+++ b/hw/net/e1000e_core.c
169
@@ -XXX,XX +XXX,XX @@ e1000e_rss_parse_packet(E1000ECore *core,
170
static void
171
e1000e_setup_tx_offloads(E1000ECore *core, struct e1000e_tx *tx)
172
{
173
- if (tx->props.tse && tx->props.cptse) {
174
+ if (tx->props.tse && tx->cptse) {
175
net_tx_pkt_build_vheader(tx->tx_pkt, true, true, tx->props.mss);
176
net_tx_pkt_update_ip_checksums(tx->tx_pkt);
177
e1000x_inc_reg_if_not_full(core->mac, TSCTC);
178
return;
179
}
180
181
- if (tx->props.sum_needed & E1000_TXD_POPTS_TXSM) {
182
+ if (tx->sum_needed & E1000_TXD_POPTS_TXSM) {
183
net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0);
184
}
185
186
- if (tx->props.sum_needed & E1000_TXD_POPTS_IXSM) {
187
+ if (tx->sum_needed & E1000_TXD_POPTS_IXSM) {
188
net_tx_pkt_update_ip_hdr_checksum(tx->tx_pkt);
189
}
190
}
191
@@ -XXX,XX +XXX,XX @@ e1000e_process_tx_desc(E1000ECore *core,
192
return;
193
} else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
194
/* data descriptor */
195
- tx->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;
196
- tx->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
197
+ tx->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
198
+ tx->cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
199
e1000e_process_ts_option(core, dp);
200
} else {
201
/* legacy descriptor */
202
e1000e_process_ts_option(core, dp);
203
- tx->props.cptse = 0;
204
+ tx->cptse = 0;
205
}
206
207
addr = le64_to_cpu(dp->buffer_addr);
208
@@ -XXX,XX +XXX,XX @@ e1000e_process_tx_desc(E1000ECore *core,
209
tx->skip_cp = false;
210
net_tx_pkt_reset(tx->tx_pkt);
211
212
- tx->props.sum_needed = 0;
213
- tx->props.cptse = 0;
214
+ tx->sum_needed = 0;
215
+ tx->cptse = 0;
216
}
217
}
218
219
diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
220
index XXXXXXX..XXXXXXX 100644
221
--- a/hw/net/e1000e_core.h
222
+++ b/hw/net/e1000e_core.h
223
@@ -XXX,XX +XXX,XX @@ struct E1000Core {
224
e1000x_txd_props props;
225
226
bool skip_cp;
227
+ unsigned char sum_needed;
228
+ bool cptse;
229
struct NetTxPkt *tx_pkt;
230
} tx[E1000E_NUM_QUEUES];
231
232
diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h
233
index XXXXXXX..XXXXXXX 100644
234
--- a/hw/net/e1000x_common.h
235
+++ b/hw/net/e1000x_common.h
236
@@ -XXX,XX +XXX,XX @@ void e1000x_update_regs_on_autoneg_done(uint32_t *mac, uint16_t *phy);
237
void e1000x_increase_size_stats(uint32_t *mac, const int *size_regs, int size);
238
239
typedef struct e1000x_txd_props {
240
- unsigned char sum_needed;
241
uint8_t ipcss;
242
uint8_t ipcso;
243
uint16_t ipcse;
244
@@ -XXX,XX +XXX,XX @@ typedef struct e1000x_txd_props {
245
int8_t ip;
246
int8_t tcp;
247
bool tse;
248
- bool cptse;
249
} e1000x_txd_props;
250
251
void e1000x_read_tx_ctx_descr(struct e1000_context_desc *d,
252
--
185
--
253
2.7.4
186
2.7.4
254
187
255
188
diff view generated by jsdifflib
Deleted patch
1
From: Ed Swierk via Qemu-devel <qemu-devel@nongnu.org>
2
1
3
The device is supposed to maintain two distinct contexts for transmit
4
offloads: one has parameters for both segmentation and checksum
5
offload, the other only for checksum offload. The guest driver can
6
send two context descriptors, one for each context (the TSE flag
7
specifies which). Then the guest can refer to one or the other context
8
in subsequent transmit data descriptors, depending on what offloads it
9
wants applied to each packet.
10
11
Currently the e1000 device stores just one context, and misinterprets
12
the TSE flags in the context and data descriptors. This is often okay:
13
Linux happens to send a fresh context descriptor before every data
14
descriptor, so forgetting the other context doesn't matter. Windows
15
does rely on separate contexts for TSO vs. non-TSO packets, but for
16
mostly-TCP traffic the two contexts have identical TCP-specific
17
offload parameters so confusing them doesn't matter.
18
19
One case where this confusion matters is when a Windows guest sets up
20
a TSO context for TCP and a non-TSO context for UDP, and then
21
transmits both TCP and UDP traffic in parallel. The e1000 device
22
sometimes ends up using TCP-specific parameters while doing checksum
23
offload on a UDP datagram: it writes the checksum to offset 16 (the
24
correct location for a TCP checksum), stomping on two bytes of UDP
25
data, and leaving the wrong value in the actual UDP checksum field at
26
offset 6. (Even worse, the host network stack may then recompute the
27
UDP checksum, "correcting" it to match the corrupt data before sending
28
it out a physical interface.)
29
30
Correct this by tracking the TSO context independently of the non-TSO
31
context, and selecting the appropriate context based on the TSE flag
32
in each transmit data descriptor.
33
34
Signed-off-by: Ed Swierk <eswierk@skyportsystems.com>
35
Signed-off-by: Jason Wang <jasowang@redhat.com>
36
---
37
hw/net/e1000.c | 70 +++++++++++++++++++++++++++++++++-------------------------
38
1 file changed, 40 insertions(+), 30 deletions(-)
39
40
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/net/e1000.c
43
+++ b/hw/net/e1000.c
44
@@ -XXX,XX +XXX,XX @@ typedef struct E1000State_st {
45
unsigned char sum_needed;
46
bool cptse;
47
e1000x_txd_props props;
48
+ e1000x_txd_props tso_props;
49
uint16_t tso_frames;
50
} tx;
51
52
@@ -XXX,XX +XXX,XX @@ xmit_seg(E1000State *s)
53
uint16_t len;
54
unsigned int frames = s->tx.tso_frames, css, sofar;
55
struct e1000_tx *tp = &s->tx;
56
+ struct e1000x_txd_props *props = tp->cptse ? &tp->tso_props : &tp->props;
57
58
- if (tp->props.tse && tp->cptse) {
59
- css = tp->props.ipcss;
60
+ if (tp->cptse) {
61
+ css = props->ipcss;
62
DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
63
frames, tp->size, css);
64
- if (tp->props.ip) { /* IPv4 */
65
+ if (props->ip) { /* IPv4 */
66
stw_be_p(tp->data+css+2, tp->size - css);
67
stw_be_p(tp->data+css+4,
68
lduw_be_p(tp->data + css + 4) + frames);
69
} else { /* IPv6 */
70
stw_be_p(tp->data+css+4, tp->size - css);
71
}
72
- css = tp->props.tucss;
73
+ css = props->tucss;
74
len = tp->size - css;
75
- DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->props.tcp, css, len);
76
- if (tp->props.tcp) {
77
- sofar = frames * tp->props.mss;
78
+ DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", props->tcp, css, len);
79
+ if (props->tcp) {
80
+ sofar = frames * props->mss;
81
stl_be_p(tp->data+css+4, ldl_be_p(tp->data+css+4)+sofar); /* seq */
82
- if (tp->props.paylen - sofar > tp->props.mss) {
83
+ if (props->paylen - sofar > props->mss) {
84
tp->data[css + 13] &= ~9; /* PSH, FIN */
85
} else if (frames) {
86
e1000x_inc_reg_if_not_full(s->mac_reg, TSCTC);
87
}
88
- } else /* UDP */
89
+ } else { /* UDP */
90
stw_be_p(tp->data+css+4, len);
91
+ }
92
if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
93
unsigned int phsum;
94
// add pseudo-header length before checksum calculation
95
- void *sp = tp->data + tp->props.tucso;
96
+ void *sp = tp->data + props->tucso;
97
98
phsum = lduw_be_p(sp) + len;
99
phsum = (phsum >> 16) + (phsum & 0xffff);
100
@@ -XXX,XX +XXX,XX @@ xmit_seg(E1000State *s)
101
}
102
103
if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
104
- putsum(tp->data, tp->size, tp->props.tucso,
105
- tp->props.tucss, tp->props.tucse);
106
+ putsum(tp->data, tp->size, props->tucso, props->tucss, props->tucse);
107
}
108
if (tp->sum_needed & E1000_TXD_POPTS_IXSM) {
109
- putsum(tp->data, tp->size, tp->props.ipcso,
110
- tp->props.ipcss, tp->props.ipcse);
111
+ putsum(tp->data, tp->size, props->ipcso, props->ipcss, props->ipcse);
112
}
113
if (tp->vlan_needed) {
114
memmove(tp->vlan, tp->data, 4);
115
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
116
117
s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);
118
if (dtype == E1000_TXD_CMD_DEXT) { /* context descriptor */
119
- e1000x_read_tx_ctx_descr(xp, &tp->props);
120
- tp->tso_frames = 0;
121
- if (tp->props.tucso == 0) { /* this is probably wrong */
122
- DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");
123
- tp->props.tucso = tp->props.tucss + (tp->props.tcp ? 16 : 6);
124
+ if (le32_to_cpu(xp->cmd_and_length) & E1000_TXD_CMD_TSE) {
125
+ e1000x_read_tx_ctx_descr(xp, &tp->tso_props);
126
+ tp->tso_frames = 0;
127
+ } else {
128
+ e1000x_read_tx_ctx_descr(xp, &tp->props);
129
}
130
return;
131
} else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
132
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
133
}
134
135
addr = le64_to_cpu(dp->buffer_addr);
136
- if (tp->props.tse && tp->cptse) {
137
- msh = tp->props.hdr_len + tp->props.mss;
138
+ if (tp->cptse) {
139
+ msh = tp->tso_props.hdr_len + tp->tso_props.mss;
140
do {
141
bytes = split_size;
142
if (tp->size + bytes > msh)
143
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
144
bytes = MIN(sizeof(tp->data) - tp->size, bytes);
145
pci_dma_read(d, addr, tp->data + tp->size, bytes);
146
sz = tp->size + bytes;
147
- if (sz >= tp->props.hdr_len && tp->size < tp->props.hdr_len) {
148
- memmove(tp->header, tp->data, tp->props.hdr_len);
149
+ if (sz >= tp->tso_props.hdr_len
150
+ && tp->size < tp->tso_props.hdr_len) {
151
+ memmove(tp->header, tp->data, tp->tso_props.hdr_len);
152
}
153
tp->size = sz;
154
addr += bytes;
155
if (sz == msh) {
156
xmit_seg(s);
157
- memmove(tp->data, tp->header, tp->props.hdr_len);
158
- tp->size = tp->props.hdr_len;
159
+ memmove(tp->data, tp->header, tp->tso_props.hdr_len);
160
+ tp->size = tp->tso_props.hdr_len;
161
}
162
split_size -= bytes;
163
} while (bytes && split_size);
164
- } else if (!tp->props.tse && tp->cptse) {
165
- // context descriptor TSE is not set, while data descriptor TSE is set
166
- DBGOUT(TXERR, "TCP segmentation error\n");
167
} else {
168
split_size = MIN(sizeof(tp->data) - tp->size, split_size);
169
pci_dma_read(d, addr, tp->data + tp->size, split_size);
170
@@ -XXX,XX +XXX,XX @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
171
172
if (!(txd_lower & E1000_TXD_CMD_EOP))
173
return;
174
- if (!(tp->props.tse && tp->cptse && tp->size < tp->props.hdr_len)) {
175
+ if (!(tp->cptse && tp->size < tp->tso_props.hdr_len)) {
176
xmit_seg(s);
177
}
178
tp->tso_frames = 0;
179
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_e1000_full_mac_state = {
180
181
static const VMStateDescription vmstate_e1000 = {
182
.name = "e1000",
183
- .version_id = 2,
184
+ .version_id = 3,
185
.minimum_version_id = 1,
186
.pre_save = e1000_pre_save,
187
.post_load = e1000_post_load,
188
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_e1000 = {
189
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32),
190
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128),
191
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
192
+ VMSTATE_UINT8_V(tx.tso_props.ipcss, E1000State, 3),
193
+ VMSTATE_UINT8_V(tx.tso_props.ipcso, E1000State, 3),
194
+ VMSTATE_UINT16_V(tx.tso_props.ipcse, E1000State, 3),
195
+ VMSTATE_UINT8_V(tx.tso_props.tucss, E1000State, 3),
196
+ VMSTATE_UINT8_V(tx.tso_props.tucso, E1000State, 3),
197
+ VMSTATE_UINT16_V(tx.tso_props.tucse, E1000State, 3),
198
+ VMSTATE_UINT32_V(tx.tso_props.paylen, E1000State, 3),
199
+ VMSTATE_UINT8_V(tx.tso_props.hdr_len, E1000State, 3),
200
+ VMSTATE_UINT16_V(tx.tso_props.mss, E1000State, 3),
201
+ VMSTATE_INT8_V(tx.tso_props.ip, E1000State, 3),
202
+ VMSTATE_INT8_V(tx.tso_props.tcp, E1000State, 3),
203
VMSTATE_END_OF_LIST()
204
},
205
.subsections = (const VMStateDescription*[]) {
206
--
207
2.7.4
208
209
diff view generated by jsdifflib
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
From the Linux sungem driver, we know that the multicast filter CRC is
3
Packet size some time different or when network is busy.
4
implemented using ether_crc_le() which isn't the same as calling zlib's
4
Based on same payload size, but TCP protocol can not
5
crc32() function (the zlib implementation requires a complemented initial value
5
guarantee send the same one packet in the same way,
6
and also returns the complemented result).
6
7
7
like that:
8
Fix the multicast filter by simply using the new net_crc32_le() function.
8
We send this payload:
9
9
------------------------------
10
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
10
| header |1|2|3|4|5|6|7|8|9|0|
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
------------------------------
12
13
primary:
14
ppkt1:
15
----------------
16
| header |1|2|3|
17
----------------
18
ppkt2:
19
------------------------
20
| header |4|5|6|7|8|9|0|
21
------------------------
22
23
secondary:
24
spkt1:
25
------------------------------
26
| header |1|2|3|4|5|6|7|8|9|0|
27
------------------------------
28
29
In the original method, ppkt1 and ppkt2 are different in size and
30
spkt1, so they can't compare and trigger the checkpoint.
31
32
I have tested FTP get 200M and 1G file many times, I found that
33
the performance was less than 1% of the native.
34
35
Now I reconstructed the comparison of TCP packets based on the
36
TCP sequence number. first of all, ppkt1 and spkt1 have the same
37
starting sequence number, so they can compare, even though their
38
length is different. And then ppkt1 with a smaller payload length
39
is used as the comparison length, if the payload is same, send
40
out the ppkt1 and record the offset(the length of ppkt1 payload)
41
in spkt1. The next comparison, ppkt2 and spkt1 can be compared
42
from the recorded position of spkt1.
43
44
like that:
45
----------------
46
| header |1|2|3| ppkt1
47
---------|-----|
48
| |
49
---------v-----v--------------
50
| header |1|2|3|4|5|6|7|8|9|0| spkt1
51
---------------|\------------|
52
| \offset |
53
---------v-------------v
54
| header |4|5|6|7|8|9|0| ppkt2
55
------------------------
56
57
In this way, the performance can reach native 20% in my multiple
58
tests.
59
60
Cc: Zhang Chen <zhangckid@gmail.com>
61
Cc: Li Zhijian <lizhijian@cn.fujitsu.com>
62
Cc: Jason Wang <jasowang@redhat.com>
63
64
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
65
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
66
Signed-off-by: Zhang Chen <zhangckid@gmail.com>
67
Reviewed-by: Zhang Chen <zhangckid@gmail.com>
68
Tested-by: Zhang Chen <zhangckid@gmail.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
69
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
70
---
14
hw/net/sungem.c | 5 ++---
71
net/colo-compare.c | 343 +++++++++++++++++++++++++++++++++++------------------
15
1 file changed, 2 insertions(+), 3 deletions(-)
72
net/colo.c | 9 ++
16
73
net/colo.h | 15 +++
17
diff --git a/hw/net/sungem.c b/hw/net/sungem.c
74
net/trace-events | 2 +-
75
4 files changed, 250 insertions(+), 119 deletions(-)
76
77
diff --git a/net/colo-compare.c b/net/colo-compare.c
18
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/sungem.c
79
--- a/net/colo-compare.c
20
+++ b/hw/net/sungem.c
80
+++ b/net/colo-compare.c
21
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
22
#include "hw/pci/pci.h"
82
#define COMPARE_READ_LEN_MAX NET_BUFSIZE
23
#include "qemu/log.h"
83
#define MAX_QUEUE_SIZE 1024
24
#include "net/net.h"
84
25
+#include "net/eth.h"
85
+#define COLO_COMPARE_FREE_PRIMARY 0x01
26
#include "net/checksum.h"
86
+#define COLO_COMPARE_FREE_SECONDARY 0x02
27
#include "hw/net/mii.h"
87
+
28
#include "sysemu/sysemu.h"
88
/* TODO: Should be configurable */
29
#include "trace.h"
89
#define REGULAR_PACKET_CHECK_MS 3000
30
-/* For crc32 */
90
31
-#include <zlib.h>
91
@@ -XXX,XX +XXX,XX @@ static gint seq_sorter(Packet *a, Packet *b, gpointer data)
32
92
return ntohl(atcp->th_seq) - ntohl(btcp->th_seq);
33
#define TYPE_SUNGEM "sungem"
93
}
34
94
35
@@ -XXX,XX +XXX,XX @@ static ssize_t sungem_receive(NetClientState *nc, const uint8_t *buf,
95
+static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
96
+{
97
+ Packet *pkt = data;
98
+ struct tcphdr *tcphd;
99
+
100
+ tcphd = (struct tcphdr *)pkt->transport_header;
101
+
102
+ pkt->tcp_seq = ntohl(tcphd->th_seq);
103
+ pkt->tcp_ack = ntohl(tcphd->th_ack);
104
+ *max_ack = *max_ack > pkt->tcp_ack ? *max_ack : pkt->tcp_ack;
105
+ pkt->header_size = pkt->transport_header - (uint8_t *)pkt->data
106
+ + (tcphd->th_off << 2) - pkt->vnet_hdr_len;
107
+ pkt->payload_size = pkt->size - pkt->header_size;
108
+ pkt->seq_end = pkt->tcp_seq + pkt->payload_size;
109
+ pkt->flags = tcphd->th_flags;
110
+}
111
+
112
/*
113
* Return 1 on success, if return 0 means the
114
* packet will be dropped
115
*/
116
-static int colo_insert_packet(GQueue *queue, Packet *pkt)
117
+static int colo_insert_packet(GQueue *queue, Packet *pkt, uint32_t *max_ack)
118
{
119
if (g_queue_get_length(queue) <= MAX_QUEUE_SIZE) {
120
if (pkt->ip->ip_p == IPPROTO_TCP) {
121
+ fill_pkt_tcp_info(pkt, max_ack);
122
g_queue_insert_sorted(queue,
123
pkt,
124
(GCompareDataFunc)seq_sorter,
125
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
36
}
126
}
37
127
38
/* Get MAC crc */
128
if (mode == PRIMARY_IN) {
39
- mac_crc = crc32(~0, buf, 6);
129
- if (!colo_insert_packet(&conn->primary_list, pkt)) {
40
+ mac_crc = net_crc32_le(buf, ETH_ALEN);
130
+ if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
41
131
error_report("colo compare primary queue size too big,"
42
/* Packet isn't for me ? */
132
"drop packet");
43
rx_cond = sungem_check_rx_mac(s, buf, mac_crc);
133
}
134
} else {
135
- if (!colo_insert_packet(&conn->secondary_list, pkt)) {
136
+ if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
137
error_report("colo compare secondary queue size too big,"
138
"drop packet");
139
}
140
@@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
141
return 0;
142
}
143
144
+static inline bool after(uint32_t seq1, uint32_t seq2)
145
+{
146
+ return (int32_t)(seq1 - seq2) > 0;
147
+}
148
+
149
+static void colo_release_primary_pkt(CompareState *s, Packet *pkt)
150
+{
151
+ int ret;
152
+ ret = compare_chr_send(s,
153
+ pkt->data,
154
+ pkt->size,
155
+ pkt->vnet_hdr_len);
156
+ if (ret < 0) {
157
+ error_report("colo send primary packet failed");
158
+ }
159
+ trace_colo_compare_main("packet same and release packet");
160
+ packet_destroy(pkt, NULL);
161
+}
162
+
163
/*
164
* The IP packets sent by primary and secondary
165
* will be compared in here
166
@@ -XXX,XX +XXX,XX @@ static int colo_compare_packet_payload(Packet *ppkt,
167
}
168
169
/*
170
- * Called from the compare thread on the primary
171
- * for compare tcp packet
172
- * compare_tcp copied from Dr. David Alan Gilbert's branch
173
- */
174
-static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt)
175
+ * return true means that the payload is consist and
176
+ * need to make the next comparison, false means do
177
+ * the checkpoint
178
+*/
179
+static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
180
+ int8_t *mark, uint32_t max_ack)
181
{
182
- struct tcphdr *ptcp, *stcp;
183
- int res;
184
+ *mark = 0;
185
+
186
+ if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
187
+ if (colo_compare_packet_payload(ppkt, spkt,
188
+ ppkt->header_size, spkt->header_size,
189
+ ppkt->payload_size)) {
190
+ *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
191
+ return true;
192
+ }
193
+ }
194
+ if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
195
+ if (colo_compare_packet_payload(ppkt, spkt,
196
+ ppkt->header_size, spkt->header_size,
197
+ ppkt->payload_size)) {
198
+ *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
199
+ return true;
200
+ }
201
+ }
202
+
203
+ /* one part of secondary packet payload still need to be compared */
204
+ if (!after(ppkt->seq_end, spkt->seq_end)) {
205
+ if (colo_compare_packet_payload(ppkt, spkt,
206
+ ppkt->header_size + ppkt->offset,
207
+ spkt->header_size + spkt->offset,
208
+ ppkt->payload_size - ppkt->offset)) {
209
+ if (!after(ppkt->tcp_ack, max_ack)) {
210
+ *mark = COLO_COMPARE_FREE_PRIMARY;
211
+ spkt->offset += ppkt->payload_size - ppkt->offset;
212
+ return true;
213
+ } else {
214
+ /* secondary guest hasn't ack the data, don't send
215
+ * out this packet
216
+ */
217
+ return false;
218
+ }
219
+ }
220
+ } else {
221
+ /* primary packet is longer than secondary packet, compare
222
+ * the same part and mark the primary packet offset
223
+ */
224
+ if (colo_compare_packet_payload(ppkt, spkt,
225
+ ppkt->header_size + ppkt->offset,
226
+ spkt->header_size + spkt->offset,
227
+ spkt->payload_size - spkt->offset)) {
228
+ *mark = COLO_COMPARE_FREE_SECONDARY;
229
+ ppkt->offset += spkt->payload_size - spkt->offset;
230
+ return true;
231
+ }
232
+ }
233
234
- trace_colo_compare_main("compare tcp");
235
+ return false;
236
+}
237
238
- ptcp = (struct tcphdr *)ppkt->transport_header;
239
- stcp = (struct tcphdr *)spkt->transport_header;
240
+static void colo_compare_tcp(CompareState *s, Connection *conn)
241
+{
242
+ Packet *ppkt = NULL, *spkt = NULL;
243
+ int8_t mark;
244
245
/*
246
- * The 'identification' field in the IP header is *very* random
247
- * it almost never matches. Fudge this by ignoring differences in
248
- * unfragmented packets; they'll normally sort themselves out if different
249
- * anyway, and it should recover at the TCP level.
250
- * An alternative would be to get both the primary and secondary to rewrite
251
- * somehow; but that would need some sync traffic to sync the state
252
- */
253
- if (ntohs(ppkt->ip->ip_off) & IP_DF) {
254
- spkt->ip->ip_id = ppkt->ip->ip_id;
255
- /* and the sum will be different if the IDs were different */
256
- spkt->ip->ip_sum = ppkt->ip->ip_sum;
257
+ * If ppkt and spkt have the same payload, but ppkt's ACK
258
+ * is greater than spkt's ACK, in this case we can not
259
+ * send the ppkt because it will cause the secondary guest
260
+ * to miss sending some data in the next. Therefore, we
261
+ * record the maximum ACK in the current queue at both
262
+ * primary side and secondary side. Only when the ack is
263
+ * less than the smaller of the two maximum ack, then we
264
+ * can ensure that the packet's payload is acknowledged by
265
+ * primary and secondary.
266
+ */
267
+ uint32_t min_ack = conn->pack > conn->sack ? conn->sack : conn->pack;
268
+
269
+pri:
270
+ if (g_queue_is_empty(&conn->primary_list)) {
271
+ return;
272
}
273
+ ppkt = g_queue_pop_head(&conn->primary_list);
274
+sec:
275
+ if (g_queue_is_empty(&conn->secondary_list)) {
276
+ g_queue_push_head(&conn->primary_list, ppkt);
277
+ return;
278
+ }
279
+ spkt = g_queue_pop_head(&conn->secondary_list);
280
281
- /*
282
- * Check tcp header length for tcp option field.
283
- * th_off > 5 means this tcp packet have options field.
284
- * The tcp options maybe always different.
285
- * for example:
286
- * From RFC 7323.
287
- * TCP Timestamps option (TSopt):
288
- * Kind: 8
289
- *
290
- * Length: 10 bytes
291
- *
292
- * +-------+-------+---------------------+---------------------+
293
- * |Kind=8 | 10 | TS Value (TSval) |TS Echo Reply (TSecr)|
294
- * +-------+-------+---------------------+---------------------+
295
- * 1 1 4 4
296
- *
297
- * In this case the primary guest's timestamp always different with
298
- * the secondary guest's timestamp. COLO just focus on payload,
299
- * so we just need skip this field.
300
- */
301
+ if (ppkt->tcp_seq == ppkt->seq_end) {
302
+ colo_release_primary_pkt(s, ppkt);
303
+ ppkt = NULL;
304
+ }
305
306
- ptrdiff_t ptcp_offset, stcp_offset;
307
+ if (ppkt && conn->compare_seq && !after(ppkt->seq_end, conn->compare_seq)) {
308
+ trace_colo_compare_main("pri: this packet has compared");
309
+ colo_release_primary_pkt(s, ppkt);
310
+ ppkt = NULL;
311
+ }
312
313
- ptcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data
314
- + (ptcp->th_off << 2) - ppkt->vnet_hdr_len;
315
- stcp_offset = spkt->transport_header - (uint8_t *)spkt->data
316
- + (stcp->th_off << 2) - spkt->vnet_hdr_len;
317
- if (ppkt->size - ptcp_offset == spkt->size - stcp_offset) {
318
- res = colo_compare_packet_payload(ppkt, spkt,
319
- ptcp_offset, stcp_offset,
320
- ppkt->size - ptcp_offset);
321
+ if (spkt->tcp_seq == spkt->seq_end) {
322
+ packet_destroy(spkt, NULL);
323
+ if (!ppkt) {
324
+ goto pri;
325
+ } else {
326
+ goto sec;
327
+ }
328
} else {
329
- trace_colo_compare_main("TCP: payload size of packets are different");
330
- res = -1;
331
+ if (conn->compare_seq && !after(spkt->seq_end, conn->compare_seq)) {
332
+ trace_colo_compare_main("sec: this packet has compared");
333
+ packet_destroy(spkt, NULL);
334
+ if (!ppkt) {
335
+ goto pri;
336
+ } else {
337
+ goto sec;
338
+ }
339
+ }
340
+ if (!ppkt) {
341
+ g_queue_push_head(&conn->secondary_list, spkt);
342
+ goto pri;
343
+ }
344
}
345
346
- if (res != 0 &&
347
- trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
348
- char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
349
-
350
- strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src));
351
- strcpy(pri_ip_dst, inet_ntoa(ppkt->ip->ip_dst));
352
- strcpy(sec_ip_src, inet_ntoa(spkt->ip->ip_src));
353
- strcpy(sec_ip_dst, inet_ntoa(spkt->ip->ip_dst));
354
-
355
- trace_colo_compare_ip_info(ppkt->size, pri_ip_src,
356
- pri_ip_dst, spkt->size,
357
- sec_ip_src, sec_ip_dst);
358
-
359
- trace_colo_compare_tcp_info("pri tcp packet",
360
- ntohl(ptcp->th_seq),
361
- ntohl(ptcp->th_ack),
362
- res, ptcp->th_flags,
363
- ppkt->size);
364
-
365
- trace_colo_compare_tcp_info("sec tcp packet",
366
- ntohl(stcp->th_seq),
367
- ntohl(stcp->th_ack),
368
- res, stcp->th_flags,
369
- spkt->size);
370
+ if (colo_mark_tcp_pkt(ppkt, spkt, &mark, min_ack)) {
371
+ trace_colo_compare_tcp_info("pri",
372
+ ppkt->tcp_seq, ppkt->tcp_ack,
373
+ ppkt->header_size, ppkt->payload_size,
374
+ ppkt->offset, ppkt->flags);
375
+
376
+ trace_colo_compare_tcp_info("sec",
377
+ spkt->tcp_seq, spkt->tcp_ack,
378
+ spkt->header_size, spkt->payload_size,
379
+ spkt->offset, spkt->flags);
380
+
381
+ if (mark == COLO_COMPARE_FREE_PRIMARY) {
382
+ conn->compare_seq = ppkt->seq_end;
383
+ colo_release_primary_pkt(s, ppkt);
384
+ g_queue_push_head(&conn->secondary_list, spkt);
385
+ goto pri;
386
+ }
387
+ if (mark == COLO_COMPARE_FREE_SECONDARY) {
388
+ conn->compare_seq = spkt->seq_end;
389
+ packet_destroy(spkt, NULL);
390
+ goto sec;
391
+ }
392
+ if (mark == (COLO_COMPARE_FREE_PRIMARY | COLO_COMPARE_FREE_SECONDARY)) {
393
+ conn->compare_seq = ppkt->seq_end;
394
+ colo_release_primary_pkt(s, ppkt);
395
+ packet_destroy(spkt, NULL);
396
+ goto pri;
397
+ }
398
+ } else {
399
+ g_queue_push_head(&conn->primary_list, ppkt);
400
+ g_queue_push_head(&conn->secondary_list, spkt);
401
402
qemu_hexdump((char *)ppkt->data, stderr,
403
"colo-compare ppkt", ppkt->size);
404
qemu_hexdump((char *)spkt->data, stderr,
405
"colo-compare spkt", spkt->size);
406
- }
407
408
- return res;
409
+ /*
410
+ * colo_compare_inconsistent_notify();
411
+ * TODO: notice to checkpoint();
412
+ */
413
+ }
414
}
415
416
+
417
/*
418
* Called from the compare thread on the primary
419
* for compare udp packet
420
@@ -XXX,XX +XXX,XX @@ static void colo_old_packet_check(void *opaque)
421
(GCompareFunc)colo_old_packet_check_one_conn);
422
}
423
424
-/*
425
- * Called from the compare thread on the primary
426
- * for compare packet with secondary list of the
427
- * specified connection when a new packet was
428
- * queued to it.
429
- */
430
-static void colo_compare_connection(void *opaque, void *user_data)
431
+static void colo_compare_packet(CompareState *s, Connection *conn,
432
+ int (*HandlePacket)(Packet *spkt,
433
+ Packet *ppkt))
434
{
435
- CompareState *s = user_data;
436
- Connection *conn = opaque;
437
Packet *pkt = NULL;
438
GList *result = NULL;
439
- int ret;
440
441
while (!g_queue_is_empty(&conn->primary_list) &&
442
!g_queue_is_empty(&conn->secondary_list)) {
443
pkt = g_queue_pop_head(&conn->primary_list);
444
- switch (conn->ip_proto) {
445
- case IPPROTO_TCP:
446
- result = g_queue_find_custom(&conn->secondary_list,
447
- pkt, (GCompareFunc)colo_packet_compare_tcp);
448
- break;
449
- case IPPROTO_UDP:
450
- result = g_queue_find_custom(&conn->secondary_list,
451
- pkt, (GCompareFunc)colo_packet_compare_udp);
452
- break;
453
- case IPPROTO_ICMP:
454
- result = g_queue_find_custom(&conn->secondary_list,
455
- pkt, (GCompareFunc)colo_packet_compare_icmp);
456
- break;
457
- default:
458
- result = g_queue_find_custom(&conn->secondary_list,
459
- pkt, (GCompareFunc)colo_packet_compare_other);
460
- break;
461
- }
462
+ result = g_queue_find_custom(&conn->secondary_list,
463
+ pkt, (GCompareFunc)HandlePacket);
464
465
if (result) {
466
- ret = compare_chr_send(s,
467
- pkt->data,
468
- pkt->size,
469
- pkt->vnet_hdr_len);
470
- if (ret < 0) {
471
- error_report("colo_send_primary_packet failed");
472
- }
473
- trace_colo_compare_main("packet same and release packet");
474
+ colo_release_primary_pkt(s, pkt);
475
g_queue_remove(&conn->secondary_list, result->data);
476
- packet_destroy(pkt, NULL);
477
} else {
478
/*
479
* If one packet arrive late, the secondary_list or
480
@@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data)
481
}
482
}
483
484
+/*
485
+ * Called from the compare thread on the primary
486
+ * for compare packet with secondary list of the
487
+ * specified connection when a new packet was
488
+ * queued to it.
489
+ */
490
+static void colo_compare_connection(void *opaque, void *user_data)
491
+{
492
+ CompareState *s = user_data;
493
+ Connection *conn = opaque;
494
+
495
+ switch (conn->ip_proto) {
496
+ case IPPROTO_TCP:
497
+ colo_compare_tcp(s, conn);
498
+ break;
499
+ case IPPROTO_UDP:
500
+ colo_compare_packet(s, conn, colo_packet_compare_udp);
501
+ break;
502
+ case IPPROTO_ICMP:
503
+ colo_compare_packet(s, conn, colo_packet_compare_icmp);
504
+ break;
505
+ default:
506
+ colo_compare_packet(s, conn, colo_packet_compare_other);
507
+ break;
508
+ }
509
+}
510
+
511
static int compare_chr_send(CompareState *s,
512
const uint8_t *buf,
513
uint32_t size,
514
diff --git a/net/colo.c b/net/colo.c
515
index XXXXXXX..XXXXXXX 100644
516
--- a/net/colo.c
517
+++ b/net/colo.c
518
@@ -XXX,XX +XXX,XX @@ Connection *connection_new(ConnectionKey *key)
519
conn->processing = false;
520
conn->offset = 0;
521
conn->syn_flag = 0;
522
+ conn->pack = 0;
523
+ conn->sack = 0;
524
g_queue_init(&conn->primary_list);
525
g_queue_init(&conn->secondary_list);
526
527
@@ -XXX,XX +XXX,XX @@ Packet *packet_new(const void *data, int size, int vnet_hdr_len)
528
pkt->size = size;
529
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
530
pkt->vnet_hdr_len = vnet_hdr_len;
531
+ pkt->tcp_seq = 0;
532
+ pkt->tcp_ack = 0;
533
+ pkt->seq_end = 0;
534
+ pkt->header_size = 0;
535
+ pkt->payload_size = 0;
536
+ pkt->offset = 0;
537
+ pkt->flags = 0;
538
539
return pkt;
540
}
541
diff --git a/net/colo.h b/net/colo.h
542
index XXXXXXX..XXXXXXX 100644
543
--- a/net/colo.h
544
+++ b/net/colo.h
545
@@ -XXX,XX +XXX,XX @@ typedef struct Packet {
546
int64_t creation_ms;
547
/* Get vnet_hdr_len from filter */
548
uint32_t vnet_hdr_len;
549
+ uint32_t tcp_seq; /* sequence number */
550
+ uint32_t tcp_ack; /* acknowledgement number */
551
+ /* the sequence number of the last byte of the packet */
552
+ uint32_t seq_end;
553
+ uint8_t header_size; /* the header length */
554
+ uint16_t payload_size; /* the payload length */
555
+ /* record the payload offset(the length that has been compared) */
556
+ uint16_t offset;
557
+ uint8_t flags; /* Flags(aka Control bits) */
558
} Packet;
559
560
typedef struct ConnectionKey {
561
@@ -XXX,XX +XXX,XX @@ typedef struct Connection {
562
/* flag to enqueue unprocessed_connections */
563
bool processing;
564
uint8_t ip_proto;
565
+ /* record the sequence number that has been compared */
566
+ uint32_t compare_seq;
567
+ /* the maximum of acknowledgement number in primary_list queue */
568
+ uint32_t pack;
569
+ /* the maximum of acknowledgement number in secondary_list queue */
570
+ uint32_t sack;
571
/* offset = secondary_seq - primary_seq */
572
tcp_seq offset;
573
/*
574
diff --git a/net/trace-events b/net/trace-events
575
index XXXXXXX..XXXXXXX 100644
576
--- a/net/trace-events
577
+++ b/net/trace-events
578
@@ -XXX,XX +XXX,XX @@ colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
579
colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
580
colo_old_packet_check_found(int64_t old_time) "%" PRId64
581
colo_compare_miscompare(void) ""
582
-colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int res, uint32_t flag, int size) "side: %s seq/ack= %u/%u res= %d flags= 0x%x pkt_size: %d\n"
583
+colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int hdlen, int pdlen, int offset, int flags) "%s: seq/ack= %u/%u hdlen= %d pdlen= %d offset= %d flags=%d\n"
584
585
# net/filter-rewriter.c
586
colo_filter_rewriter_debug(void) ""
44
--
587
--
45
2.7.4
588
2.7.4
46
589
47
590
diff view generated by jsdifflib
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Separate out the standard ethernet CRC32 calculation into a new net_crc32()
3
QEMU can emulate hubs to connect NICs and netdevs. This is currently
4
function, renaming the constant POLYNOMIAL to POLYNOMIAL_BE to make it clear
4
primarily used for the mis-named 'vlan' feature of the networking
5
that this is a big-endian CRC32 calculation.
5
subsystem. Now the 'vlan' feature has been marked as deprecated, since
6
6
its name is rather confusing and the users often rather mis-configure
7
As part of the constant rename, remove the duplicate definition of POLYNOMIAL
7
their network when trying to use it. But while the 'vlan' parameter
8
from eepro100.c and use the new POLYNOMIAL_BE constant instead.
8
should be removed at one point in time, the basic idea of emulating
9
9
a hub in QEMU is still good: It's useful for bundling up the output of
10
Once this is complete remove the existing CRC32 implementation from
10
multiple NICs into one single l2tp netdev for example.
11
compute_mcast_idx() and call the new net_crc32() function in its place.
11
12
12
Now to be able to use the hubport feature without 'vlan's, there is one
13
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
13
missing piece: The possibility to connect a hubport to a netdev, too.
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
This patch adds this possibility by introducing a new "netdev=..."
15
parameter to the hubports.
16
17
To bundle up the output of multiple NICs into one socket netdev, you can
18
now run QEMU with these parameters for example:
19
20
qemu-system-ppc64 ... -netdev socket,id=s1,connect=:11122 \
21
-netdev hubport,hubid=1,id=h1,netdev=s1 \
22
-netdev hubport,hubid=1,id=h2 -device e1000,netdev=h2 \
23
-netdev hubport,hubid=1,id=h3 -device virtio-net-pci,netdev=h3
24
25
For using the socket netdev, you have got to start another QEMU as the
26
receiving side first, for example with network dumping enabled:
27
28
qemu-system-x86_64 -M isapc -netdev socket,id=s0,listen=:11122 \
29
-device ne2k_isa,netdev=s0 \
30
-object filter-dump,id=f1,netdev=s0,file=/tmp/dump.dat
31
32
After the ppc64 guest tried to boot from both NICs, you can see in the
33
dump file (using Wireshark, for example), that the output of both NICs
34
(the e1000 and the virtio-net-pci) has been successfully transfered
35
via the socket netdev in this case.
36
37
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
38
Signed-off-by: Thomas Huth <thuth@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
39
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
---
40
---
17
hw/net/eepro100.c | 4 +---
41
net/hub.c | 27 +++++++++++++++++++++------
18
include/net/net.h | 3 ++-
42
net/hub.h | 3 ++-
19
net/net.c | 16 +++++++++++-----
43
net/net.c | 2 +-
20
3 files changed, 14 insertions(+), 9 deletions(-)
44
qapi/net.json | 4 +++-
21
45
qemu-options.hx | 8 +++++---
22
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
46
5 files changed, 32 insertions(+), 12 deletions(-)
23
index XXXXXXX..XXXXXXX 100644
47
24
--- a/hw/net/eepro100.c
48
diff --git a/net/hub.c b/net/hub.c
25
+++ b/hw/net/eepro100.c
49
index XXXXXXX..XXXXXXX 100644
26
@@ -XXX,XX +XXX,XX @@ static const uint16_t eepro100_mdi_mask[] = {
50
--- a/net/hub.c
27
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
51
+++ b/net/hub.c
52
@@ -XXX,XX +XXX,XX @@
53
*/
54
55
#include "qemu/osdep.h"
56
+#include "qapi/error.h"
57
#include "monitor/monitor.h"
58
#include "net/net.h"
59
#include "clients.h"
60
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_hub_port_info = {
61
.cleanup = net_hub_port_cleanup,
28
};
62
};
29
63
30
-#define POLYNOMIAL 0x04c11db6
64
-static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
31
-
65
+static NetHubPort *net_hub_port_new(NetHub *hub, const char *name,
32
static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
66
+ NetClientState *hubpeer)
33
67
{
34
/* From FreeBSD (locally modified). */
68
NetClientState *nc;
35
@@ -XXX,XX +XXX,XX @@ static unsigned e100_compute_mcast_idx(const uint8_t *ep)
69
NetHubPort *port;
36
crc <<= 1;
70
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
37
b >>= 1;
71
name = default_name;
38
if (carry) {
72
}
39
- crc = ((crc ^ POLYNOMIAL) | carry);
73
40
+ crc = ((crc ^ POLYNOMIAL_BE) | carry);
74
- nc = qemu_new_net_client(&net_hub_port_info, NULL, "hub", name);
41
}
75
+ nc = qemu_new_net_client(&net_hub_port_info, hubpeer, "hub", name);
76
port = DO_UPCAST(NetHubPort, nc, nc);
77
port->id = id;
78
port->hub = hub;
79
@@ -XXX,XX +XXX,XX @@ static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
80
81
/**
82
* Create a port on a given hub
83
+ * @hub_id: Number of the hub
84
* @name: Net client name or NULL for default name.
85
+ * @hubpeer: Peer to use (if "netdev=id" has been specified)
86
*
87
* If there is no existing hub with the given id then a new hub is created.
88
*/
89
-NetClientState *net_hub_add_port(int hub_id, const char *name)
90
+NetClientState *net_hub_add_port(int hub_id, const char *name,
91
+ NetClientState *hubpeer)
92
{
93
NetHub *hub;
94
NetHubPort *port;
95
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_add_port(int hub_id, const char *name)
96
hub = net_hub_new(hub_id);
97
}
98
99
- port = net_hub_port_new(hub, name);
100
+ port = net_hub_port_new(hub, name, hubpeer);
101
return &port->nc;
102
}
103
104
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_port_find(int hub_id)
42
}
105
}
43
}
106
}
44
diff --git a/include/net/net.h b/include/net/net.h
107
45
index XXXXXXX..XXXXXXX 100644
108
- nc = net_hub_add_port(hub_id, NULL);
46
--- a/include/net/net.h
109
+ nc = net_hub_add_port(hub_id, NULL, NULL);
47
+++ b/include/net/net.h
110
return nc;
48
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_port_find(int hub_id);
111
}
49
112
50
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd);
113
@@ -XXX,XX +XXX,XX @@ int net_init_hubport(const Netdev *netdev, const char *name,
51
114
NetClientState *peer, Error **errp)
52
-#define POLYNOMIAL 0x04c11db6
115
{
53
+#define POLYNOMIAL_BE 0x04c11db6
116
const NetdevHubPortOptions *hubport;
54
+uint32_t net_crc32(const uint8_t *p, int len);
117
+ NetClientState *hubpeer = NULL;
55
unsigned compute_mcast_idx(const uint8_t *ep);
118
56
119
assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
57
#define vmstate_offset_macaddr(_state, _field) \
120
assert(!peer);
121
hubport = &netdev->u.hubport;
122
123
- net_hub_add_port(hubport->hubid, name);
124
+ if (hubport->has_netdev) {
125
+ hubpeer = qemu_find_netdev(hubport->netdev);
126
+ if (!hubpeer) {
127
+ error_setg(errp, "netdev '%s' not found", hubport->netdev);
128
+ return -1;
129
+ }
130
+ }
131
+
132
+ net_hub_add_port(hubport->hubid, name, hubpeer);
133
+
134
return 0;
135
}
136
137
diff --git a/net/hub.h b/net/hub.h
138
index XXXXXXX..XXXXXXX 100644
139
--- a/net/hub.h
140
+++ b/net/hub.h
141
@@ -XXX,XX +XXX,XX @@
142
143
#include "qemu-common.h"
144
145
-NetClientState *net_hub_add_port(int hub_id, const char *name);
146
+NetClientState *net_hub_add_port(int hub_id, const char *name,
147
+ NetClientState *hubpeer);
148
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
149
void net_hub_info(Monitor *mon);
150
void net_hub_check_clients(void);
58
diff --git a/net/net.c b/net/net.c
151
diff --git a/net/net.c b/net/net.c
59
index XXXXXXX..XXXXXXX 100644
152
index XXXXXXX..XXXXXXX 100644
60
--- a/net/net.c
153
--- a/net/net.c
61
+++ b/net/net.c
154
+++ b/net/net.c
62
@@ -XXX,XX +XXX,XX @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
155
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
63
156
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
64
/* From FreeBSD */
157
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
65
/* XXX: optimize */
158
!opts->u.nic.has_netdev) {
66
-unsigned compute_mcast_idx(const uint8_t *ep)
159
- peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
67
+uint32_t net_crc32(const uint8_t *p, int len)
160
+ peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL, NULL);
68
{
69
uint32_t crc;
70
int carry, i, j;
71
uint8_t b;
72
73
crc = 0xffffffff;
74
- for (i = 0; i < 6; i++) {
75
- b = *ep++;
76
+ for (i = 0; i < len; i++) {
77
+ b = *p++;
78
for (j = 0; j < 8; j++) {
79
carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
80
crc <<= 1;
81
b >>= 1;
82
if (carry) {
83
- crc = ((crc ^ POLYNOMIAL) | carry);
84
+ crc = ((crc ^ POLYNOMIAL_BE) | carry);
85
}
86
}
161
}
87
}
162
88
- return crc >> 26;
163
if (net->has_vlan && !vlan_warned) {
89
+
164
diff --git a/qapi/net.json b/qapi/net.json
90
+ return crc;
165
index XXXXXXX..XXXXXXX 100644
91
+}
166
--- a/qapi/net.json
92
+
167
+++ b/qapi/net.json
93
+unsigned compute_mcast_idx(const uint8_t *ep)
168
@@ -XXX,XX +XXX,XX @@
94
+{
169
# Connect two or more net clients through a software hub.
95
+ return net_crc32(ep, ETH_ALEN) >> 26;
170
#
96
}
171
# @hubid: hub identifier number
97
172
+# @netdev: used to connect hub to a netdev instead of a device (since 2.12)
98
QemuOptsList qemu_netdev_opts = {
173
#
174
# Since: 1.2
175
##
176
{ 'struct': 'NetdevHubPortOptions',
177
'data': {
178
- 'hubid': 'int32' } }
179
+ 'hubid': 'int32',
180
+ '*netdev': 'str' } }
181
182
##
183
# @NetdevNetmapOptions:
184
diff --git a/qemu-options.hx b/qemu-options.hx
185
index XXXXXXX..XXXXXXX 100644
186
--- a/qemu-options.hx
187
+++ b/qemu-options.hx
188
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
189
#endif
190
"-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n"
191
" configure a vhost-user network, backed by a chardev 'dev'\n"
192
- "-netdev hubport,id=str,hubid=n\n"
193
+ "-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
194
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
195
DEF("net", HAS_ARG, QEMU_OPTION_net,
196
"-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
197
@@ -XXX,XX +XXX,XX @@ vde_switch -F -sock /tmp/myswitch
198
qemu-system-i386 linux.img -net nic -net vde,sock=/tmp/myswitch
199
@end example
200
201
-@item -netdev hubport,id=@var{id},hubid=@var{hubid}
202
+@item -netdev hubport,id=@var{id},hubid=@var{hubid}[,netdev=@var{nd}]
203
204
Create a hub port on QEMU "vlan" @var{hubid}.
205
206
The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
207
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
208
-required hub automatically.
209
+required hub automatically. Alternatively, you can also connect the hubport
210
+to another netdev with ID @var{nd} by using the @option{netdev=@var{nd}}
211
+option.
212
213
@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
214
99
--
215
--
100
2.7.4
216
2.7.4
101
217
102
218
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
This provides a standard ethernet CRC32 little-endian implementation.
4
5
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
include/net/net.h | 2 ++
11
net/net.c | 22 ++++++++++++++++++++++
12
2 files changed, 24 insertions(+)
13
14
diff --git a/include/net/net.h b/include/net/net.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/net/net.h
17
+++ b/include/net/net.h
18
@@ -XXX,XX +XXX,XX @@ NetClientState *net_hub_port_find(int hub_id);
19
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd);
20
21
#define POLYNOMIAL_BE 0x04c11db6
22
+#define POLYNOMIAL_LE 0xedb88320
23
uint32_t net_crc32(const uint8_t *p, int len);
24
+uint32_t net_crc32_le(const uint8_t *p, int len);
25
unsigned compute_mcast_idx(const uint8_t *ep);
26
27
#define vmstate_offset_macaddr(_state, _field) \
28
diff --git a/net/net.c b/net/net.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/net/net.c
31
+++ b/net/net.c
32
@@ -XXX,XX +XXX,XX @@ uint32_t net_crc32(const uint8_t *p, int len)
33
return crc;
34
}
35
36
+uint32_t net_crc32_le(const uint8_t *p, int len)
37
+{
38
+ uint32_t crc;
39
+ int carry, i, j;
40
+ uint8_t b;
41
+
42
+ crc = 0xffffffff;
43
+ for (i = 0; i < len; i++) {
44
+ b = *p++;
45
+ for (j = 0; j < 8; j++) {
46
+ carry = (crc & 0x1) ^ (b & 0x01);
47
+ crc >>= 1;
48
+ b >>= 1;
49
+ if (carry) {
50
+ crc ^= POLYNOMIAL_LE;
51
+ }
52
+ }
53
+ }
54
+
55
+ return crc;
56
+}
57
+
58
unsigned compute_mcast_idx(const uint8_t *ep)
59
{
60
return net_crc32(ep, ETH_ALEN) >> 26;
61
--
62
2.7.4
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
Instead of lnc_mchash() using its own implementation, we can simply call
4
net_crc32_le() directly and apply the bit shift inline.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/pcnet.c | 22 ++--------------------
12
1 file changed, 2 insertions(+), 20 deletions(-)
13
14
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/pcnet.c
17
+++ b/hw/net/pcnet.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "qemu/osdep.h"
20
#include "hw/qdev.h"
21
#include "net/net.h"
22
+#include "net/eth.h"
23
#include "qemu/timer.h"
24
#include "qemu/sockets.h"
25
#include "sysemu/sysemu.h"
26
@@ -XXX,XX +XXX,XX @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
27
be16_to_cpu(hdr->ether_type)); \
28
} while (0)
29
30
-#define MULTICAST_FILTER_LEN 8
31
-
32
-static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
33
-{
34
-#define LNC_POLYNOMIAL 0xEDB88320UL
35
- uint32_t crc = 0xFFFFFFFF;
36
- int idx, bit;
37
- uint8_t data;
38
-
39
- for (idx = 0; idx < 6; idx++) {
40
- for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
41
- crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
42
- data >>= 1;
43
- }
44
- }
45
- return crc;
46
-#undef LNC_POLYNOMIAL
47
-}
48
-
49
#define CRC(crc, ch)     (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
50
51
/* generated using the AUTODIN II polynomial
52
@@ -XXX,XX +XXX,XX @@ static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
53
s->csr[10] & 0xff, s->csr[10] >> 8,
54
s->csr[11] & 0xff, s->csr[11] >> 8
55
};
56
- int index = lnc_mchash(hdr->ether_dhost) >> 26;
57
+ int index = net_crc32_le(hdr->ether_dhost, ETH_ALEN) >> 26;
58
return !!(ladr[index >> 3] & (1 << (index & 7)));
59
}
60
return 0;
61
--
62
2.7.4
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
Instead of e100_compute_mcast_idx() using its own implementation, we can
4
simply call net_crc32() directly and apply the bit shift inline.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Reviewed-by: Stefan Weil <sw@weilnetz.de>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/eepro100.c | 28 ++++------------------------
12
1 file changed, 4 insertions(+), 24 deletions(-)
13
14
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/eepro100.c
17
+++ b/hw/net/eepro100.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "hw/hw.h"
20
#include "hw/pci/pci.h"
21
#include "net/net.h"
22
+#include "net/eth.h"
23
#include "hw/nvram/eeprom93xx.h"
24
#include "sysemu/sysemu.h"
25
#include "sysemu/dma.h"
26
@@ -XXX,XX +XXX,XX @@ static const uint16_t eepro100_mdi_mask[] = {
27
28
static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
29
30
-/* From FreeBSD (locally modified). */
31
-static unsigned e100_compute_mcast_idx(const uint8_t *ep)
32
-{
33
- uint32_t crc;
34
- int carry, i, j;
35
- uint8_t b;
36
-
37
- crc = 0xffffffff;
38
- for (i = 0; i < 6; i++) {
39
- b = *ep++;
40
- for (j = 0; j < 8; j++) {
41
- carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
42
- crc <<= 1;
43
- b >>= 1;
44
- if (carry) {
45
- crc = ((crc ^ POLYNOMIAL_BE) | carry);
46
- }
47
- }
48
- }
49
- return (crc & BITS(7, 2)) >> 2;
50
-}
51
-
52
/* Read a 16 bit control/status (CSR) register. */
53
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
54
{
55
@@ -XXX,XX +XXX,XX @@ static void set_multicast_list(EEPRO100State *s)
56
uint8_t multicast_addr[6];
57
pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
58
TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
59
- unsigned mcast_idx = e100_compute_mcast_idx(multicast_addr);
60
+ unsigned mcast_idx = (net_crc32(multicast_addr, ETH_ALEN) &
61
+ BITS(7, 2)) >> 2;
62
assert(mcast_idx < 64);
63
s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
64
}
65
@@ -XXX,XX +XXX,XX @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
66
if (s->configuration[21] & BIT(3)) {
67
/* Multicast all bit is set, receive all multicast frames. */
68
} else {
69
- unsigned mcast_idx = e100_compute_mcast_idx(buf);
70
+ unsigned mcast_idx = (net_crc32(buf, ETH_ALEN) & BITS(7, 2)) >> 2;
71
assert(mcast_idx < 64);
72
if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
73
/* Multicast frame is allowed in hash table. */
74
--
75
2.7.4
76
77
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
Instead of sunhme_crc32_le() using its own implementation, we can simply call
4
net_crc32_le() directly and apply the bit shift inline.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/net/sunhme.c | 25 +------------------------
12
1 file changed, 1 insertion(+), 24 deletions(-)
13
14
diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/sunhme.c
17
+++ b/hw/net/sunhme.c
18
@@ -XXX,XX +XXX,XX @@ static inline void sunhme_set_rx_ring_nr(SunHMEState *s, int i)
19
s->erxregs[HME_ERXI_RING >> 2] = ring;
20
}
21
22
-#define POLYNOMIAL_LE 0xedb88320
23
-static uint32_t sunhme_crc32_le(const uint8_t *p, int len)
24
-{
25
- uint32_t crc;
26
- int carry, i, j;
27
- uint8_t b;
28
-
29
- crc = 0xffffffff;
30
- for (i = 0; i < len; i++) {
31
- b = *p++;
32
- for (j = 0; j < 8; j++) {
33
- carry = (crc & 0x1) ^ (b & 0x01);
34
- crc >>= 1;
35
- b >>= 1;
36
- if (carry) {
37
- crc = crc ^ POLYNOMIAL_LE;
38
- }
39
- }
40
- }
41
-
42
- return crc;
43
-}
44
-
45
#define MIN_BUF_SIZE 60
46
47
static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf,
48
@@ -XXX,XX +XXX,XX @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf,
49
trace_sunhme_rx_filter_bcast_match();
50
} else if (s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_HENABLE) {
51
/* Didn't match local address, check hash filter */
52
- int mcast_idx = sunhme_crc32_le(buf, 6) >> 26;
53
+ int mcast_idx = net_crc32_le(buf, ETH_ALEN) >> 26;
54
if (!(s->macregs[(HME_MACI_HASHTAB0 >> 2) - (mcast_idx >> 4)] &
55
(1 << (mcast_idx & 0xf)))) {
56
/* Didn't match hash filter */
57
--
58
2.7.4
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
This makes it much easier to compare the multicast CRC calculation endian and
4
bitshift against the Linux driver implementation.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/eepro100.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/eepro100.c
15
+++ b/hw/net/eepro100.c
16
@@ -XXX,XX +XXX,XX @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
17
rfd_status |= 0x0004;
18
} else if (s->configuration[20] & BIT(6)) {
19
/* Multiple IA bit set. */
20
- unsigned mcast_idx = compute_mcast_idx(buf);
21
+ unsigned mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
22
assert(mcast_idx < 64);
23
if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
24
TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s));
25
--
26
2.7.4
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
This makes it much easier to compare the multicast CRC calculation endian and
4
bitshift against the Linux driver implementation.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/opencores_eth.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
12
diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/opencores_eth.c
15
+++ b/hw/net/opencores_eth.c
16
@@ -XXX,XX +XXX,XX @@
17
#include "hw/net/mii.h"
18
#include "hw/sysbus.h"
19
#include "net/net.h"
20
+#include "net/eth.h"
21
#include "sysemu/sysemu.h"
22
#include "trace.h"
23
24
@@ -XXX,XX +XXX,XX @@ static ssize_t open_eth_receive(NetClientState *nc,
25
if (memcmp(buf, bcast_addr, sizeof(bcast_addr)) == 0) {
26
miss = GET_REGBIT(s, MODER, BRO);
27
} else if ((buf[0] & 0x1) || GET_REGBIT(s, MODER, IAM)) {
28
- unsigned mcast_idx = compute_mcast_idx(buf);
29
+ unsigned mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
30
miss = !(s->regs[HASH0 + mcast_idx / 32] &
31
(1 << (mcast_idx % 32)));
32
trace_open_eth_receive_mcast(
33
--
34
2.7.4
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
This makes it much easier to compare the multicast CRC calculation endian and
4
bitshift against the Linux driver implementation.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/lan9118.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
12
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/lan9118.c
15
+++ b/hw/net/lan9118.c
16
@@ -XXX,XX +XXX,XX @@
17
#include "qemu/osdep.h"
18
#include "hw/sysbus.h"
19
#include "net/net.h"
20
+#include "net/eth.h"
21
#include "hw/devices.h"
22
#include "sysemu/sysemu.h"
23
#include "hw/ptimer.h"
24
@@ -XXX,XX +XXX,XX @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr)
25
}
26
} else {
27
/* Hash matching */
28
- hash = compute_mcast_idx(addr);
29
+ hash = net_crc32(addr, ETH_ALEN) >> 26;
30
if (hash & 0x20) {
31
return (s->mac_hashh >> (hash & 0x1f)) & 1;
32
} else {
33
--
34
2.7.4
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
This makes it much easier to compare the multicast CRC calculation endian and
4
bitshift against the Linux driver implementation.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/ftgmac100.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/ftgmac100.c
15
+++ b/hw/net/ftgmac100.c
16
@@ -XXX,XX +XXX,XX @@ static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len)
17
}
18
19
/* TODO: this does not seem to work for ftgmac100 */
20
- mcast_idx = compute_mcast_idx(buf);
21
+ mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
22
if (!(s->math[mcast_idx / 32] & (1 << (mcast_idx % 32)))) {
23
return 0;
24
}
25
--
26
2.7.4
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
This makes it much easier to compare the multicast CRC calculation endian and
4
bitshift against the Linux driver implementation.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/ne2000.c | 4 +++-
10
1 file changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/ne2000.c
15
+++ b/hw/net/ne2000.c
16
@@ -XXX,XX +XXX,XX @@
17
*/
18
#include "qemu/osdep.h"
19
#include "hw/pci/pci.h"
20
+#include "net/net.h"
21
+#include "net/eth.h"
22
#include "ne2000.h"
23
#include "hw/loader.h"
24
#include "sysemu/sysemu.h"
25
@@ -XXX,XX +XXX,XX @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
26
/* multicast */
27
if (!(s->rxcr & 0x08))
28
return size;
29
- mcast_idx = compute_mcast_idx(buf);
30
+ mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
31
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
32
return size;
33
} else if (s->mem[0] == buf[0] &&
34
--
35
2.7.4
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
This makes it much easier to compare the multicast CRC calculation endian and
4
bitshift against the Linux driver implementation.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/net/rtl8139.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/rtl8139.c
15
+++ b/hw/net/rtl8139.c
16
@@ -XXX,XX +XXX,XX @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
17
return size;
18
}
19
20
- int mcast_idx = compute_mcast_idx(buf);
21
+ int mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
22
23
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
24
{
25
--
26
2.7.4
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2
1
3
Now that all of the callers have been converted to compute the multicast index
4
inline using new net CRC functions, this function can now be dropped.
5
6
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
net/net.c | 5 -----
10
1 file changed, 5 deletions(-)
11
12
diff --git a/net/net.c b/net/net.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/net/net.c
15
+++ b/net/net.c
16
@@ -XXX,XX +XXX,XX @@ uint32_t net_crc32_le(const uint8_t *p, int len)
17
return crc;
18
}
19
20
-unsigned compute_mcast_idx(const uint8_t *ep)
21
-{
22
- return net_crc32(ep, ETH_ALEN) >> 26;
23
-}
24
-
25
QemuOptsList qemu_netdev_opts = {
26
.name = "netdev",
27
.implied_opt_name = "type",
28
--
29
2.7.4
30
31
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
It has never been documented, so hardly anybody knows about this
3
It does not make much sense to limit these commands to the legacy 'vlan'
4
parameter, and it is marked as deprecated since QEMU v2.6.
4
concept only, they should work with the modern netdevs, too. So now
5
Time to let it go now.
5
it is possible to use this command with one, two or three parameters.
6
6
7
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
7
With one parameter, the command installs a hostfwd rule on the default
8
"user" network:
9
hostfwd_add tcp:...
10
11
With two parameters, the command installs a hostfwd rule on a netdev
12
(that's the new way of using this command):
13
hostfwd_add netdev_id tcp:...
14
15
With three parameters, the command installs a rule on a 'vlan' (aka hub):
16
hostfwd_add hub_id name tcp:...
17
18
Same applies to the hostfwd_remove command now.
19
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
20
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
21
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
22
---
11
include/net/slirp.h | 2 --
23
hmp-commands.hx | 4 ++--
12
net/net.c | 7 -------
24
net/slirp.c | 33 +++++++++++++++++++++++----------
13
net/slirp.c | 34 ----------------------------------
25
2 files changed, 25 insertions(+), 12 deletions(-)
14
qemu-doc.texi | 5 -----
15
4 files changed, 48 deletions(-)
16
26
17
diff --git a/include/net/slirp.h b/include/net/slirp.h
27
diff --git a/hmp-commands.hx b/hmp-commands.hx
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/include/net/slirp.h
29
--- a/hmp-commands.hx
20
+++ b/include/net/slirp.h
30
+++ b/hmp-commands.hx
21
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict);
31
@@ -XXX,XX +XXX,XX @@ ETEXI
22
32
{
23
int net_slirp_redir(const char *redir_str);
33
.name = "hostfwd_add",
24
34
.args_type = "arg1:s,arg2:s?,arg3:s?",
25
-int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret);
35
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
26
-
36
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
27
int net_slirp_smb(const char *exported_dir);
37
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
28
38
.cmd = hmp_hostfwd_add,
29
void hmp_info_usernet(Monitor *mon, const QDict *qdict);
39
},
30
diff --git a/net/net.c b/net/net.c
40
@@ -XXX,XX +XXX,XX @@ ETEXI
31
index XXXXXXX..XXXXXXX 100644
41
{
32
--- a/net/net.c
42
.name = "hostfwd_remove",
33
+++ b/net/net.c
43
.args_type = "arg1:s,arg2:s?,arg3:s?",
34
@@ -XXX,XX +XXX,XX @@ int net_init_clients(void)
44
- .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
35
45
+ .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport",
36
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
46
.help = "remove host-to-guest TCP or UDP redirection",
37
{
47
.cmd = hmp_hostfwd_remove,
38
-#if defined(CONFIG_SLIRP)
48
},
39
- int ret;
40
- if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
41
- return ret;
42
- }
43
-#endif
44
-
45
if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
46
return -1;
47
}
48
diff --git a/net/slirp.c b/net/slirp.c
49
diff --git a/net/slirp.c b/net/slirp.c
49
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
50
--- a/net/slirp.c
51
--- a/net/slirp.c
51
+++ b/net/slirp.c
52
+++ b/net/slirp.c
52
@@ -XXX,XX +XXX,XX @@ int net_init_slirp(const Netdev *netdev, const char *name,
53
@@ -XXX,XX +XXX,XX @@ error:
53
54
return -1;
54
return ret;
55
}
55
}
56
57
-static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
58
- const char *stack)
59
+static SlirpState *slirp_lookup(Monitor *mon, const char *hub_id,
60
+ const char *name)
61
{
56
-
62
-
57
-int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret)
63
- if (vlan) {
58
-{
64
+ if (name) {
59
- if (strcmp(opts_list->name, "net") != 0 ||
65
NetClientState *nc;
60
- strncmp(optarg, "channel,", strlen("channel,")) != 0) {
66
- nc = net_hub_find_client_by_name(strtol(vlan, NULL, 0), stack);
61
- return 0;
67
- if (!nc) {
62
- }
68
- monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
63
-
69
- return NULL;
64
- error_report("The '-net channel' option is deprecated. "
70
+ if (hub_id) {
65
- "Please use '-netdev user,guestfwd=...' instead.");
71
+ nc = net_hub_find_client_by_name(strtol(hub_id, NULL, 0), name);
66
-
72
+ if (!nc) {
67
- /* handle legacy -net channel,port:chr */
73
+ monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
68
- optarg += strlen("channel,");
74
+ return NULL;
69
-
75
+ }
70
- if (QTAILQ_EMPTY(&slirp_stacks)) {
76
+ } else {
71
- struct slirp_config_str *config;
77
+ nc = qemu_find_netdev(name);
72
-
78
+ if (!nc) {
73
- config = g_malloc(sizeof(*config));
79
+ monitor_printf(mon, "unrecognized netdev id '%s'\n", name);
74
- pstrcpy(config->str, sizeof(config->str), optarg);
80
+ return NULL;
75
- config->flags = SLIRP_CFG_LEGACY;
81
+ }
76
- config->next = slirp_configs;
82
}
77
- slirp_configs = config;
83
if (strcmp(nc->model, "user")) {
78
- *ret = 0;
84
monitor_printf(mon, "invalid device specified\n");
79
- } else {
85
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
80
- Error *err = NULL;
86
const char *arg2 = qdict_get_try_str(qdict, "arg2");
81
- *ret = slirp_guestfwd(QTAILQ_FIRST(&slirp_stacks), optarg, 1, &err);
87
const char *arg3 = qdict_get_try_str(qdict, "arg3");
82
- if (*ret < 0) {
88
83
- error_report_err(err);
89
- if (arg2) {
84
- }
90
+ if (arg3) {
85
- }
91
s = slirp_lookup(mon, arg1, arg2);
86
-
92
src_str = arg3;
87
- return 1;
93
+ } else if (arg2) {
88
-}
94
+ s = slirp_lookup(mon, NULL, arg1);
89
-
95
+ src_str = arg2;
90
diff --git a/qemu-doc.texi b/qemu-doc.texi
96
} else {
91
index XXXXXXX..XXXXXXX 100644
97
s = slirp_lookup(mon, NULL, NULL);
92
--- a/qemu-doc.texi
98
src_str = arg1;
93
+++ b/qemu-doc.texi
99
@@ -XXX,XX +XXX,XX @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
94
@@ -XXX,XX +XXX,XX @@ The ``-smb /some/dir'' argument is now a synonym for setting
100
const char *arg2 = qdict_get_try_str(qdict, "arg2");
95
the ``-netdev user,smb=/some/dir'' argument instead. The new
101
const char *arg3 = qdict_get_try_str(qdict, "arg3");
96
syntax allows different settings to be provided per NIC.
102
97
103
- if (arg2) {
98
-@subsection -net channel (since 2.6.0)
104
+ if (arg3) {
99
-
105
s = slirp_lookup(mon, arg1, arg2);
100
-The ``--net channel,ARGS'' argument is now a synonym for setting
106
redir_str = arg3;
101
-the ``-netdev user,guestfwd=ARGS'' argument instead.
107
+ } else if (arg2) {
102
-
108
+ s = slirp_lookup(mon, NULL, arg1);
103
@subsection -net vlan (since 2.9.0)
109
+ redir_str = arg2;
104
110
} else {
105
The ``-net vlan=NN'' argument is partially replaced with the
111
s = slirp_lookup(mon, NULL, NULL);
112
redir_str = arg1;
106
--
113
--
107
2.7.4
114
2.7.4
108
115
109
116
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Looks like we missed to document that it is also possible to specify
3
The vlan concept is marked as deprecated, so we should not use
4
a netdev with "-net nic" - which is very useful if you want to
4
this for examples in the documentation anymore.
5
configure your on-board NIC to use a backend that has been specified
6
with "-netdev".
7
5
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
8
---
11
qemu-options.hx | 14 ++++++++------
9
qemu-options.hx | 4 ++--
12
1 file changed, 8 insertions(+), 6 deletions(-)
10
1 file changed, 2 insertions(+), 2 deletions(-)
13
11
14
diff --git a/qemu-options.hx b/qemu-options.hx
12
diff --git a/qemu-options.hx b/qemu-options.hx
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-options.hx
14
--- a/qemu-options.hx
17
+++ b/qemu-options.hx
15
+++ b/qemu-options.hx
18
@@ -XXX,XX +XXX,XX @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
16
@@ -XXX,XX +XXX,XX @@ qemu-system-i386 linux.img -net nic -net tap
19
"-netdev hubport,id=str,hubid=n\n"
17
#launch a QEMU instance with two NICs, each one connected
20
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
18
#to a TAP device
21
DEF("net", HAS_ARG, QEMU_OPTION_net,
19
qemu-system-i386 linux.img \
22
- "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
20
- -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
23
- " old way to create a new NIC and connect it to VLAN 'n'\n"
21
- -net nic,vlan=1 -net tap,vlan=1,ifname=tap1
24
- " (use the '-device devtype,netdev=str' option if possible instead)\n"
22
+ -netdev tap,id=nd0,ifname=tap0 -device e1000,netdev=nd0 \
25
+ "-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
23
+ -netdev tap,id=nd1,ifname=tap1 -device rtl8139,netdev=nd1
26
+ " configure or create an on-board (or machine default) NIC and\n"
24
@end example
27
+ " connect it either to VLAN 'n' or the netdev 'nd' (for pluggable\n"
25
28
+ " NICs please use '-device devtype,netdev=nd' instead)\n"
26
@example
29
"-net dump[,vlan=n][,file=f][,len=n]\n"
30
" dump traffic on vlan 'n' to file 'f' (max n bytes per packet)\n"
31
"-net none use it alone to have zero network devices. If no -net option\n"
32
@@ -XXX,XX +XXX,XX @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
33
" old way to initialize a host network interface\n"
34
" (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
35
STEXI
36
-@item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
37
+@item -net nic[,vlan=@var{n}][,netdev=@var{nd}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
38
@findex -net
39
-Create a new Network Interface Card and connect it to VLAN @var{n} (@var{n}
40
-= 0 is the default). The NIC is an e1000 by default on the PC
41
+Configure or create an on-board (or machine default) Network Interface Card
42
+(NIC) and connect it either to VLAN @var{n} (@var{n} = 0 is the default), or
43
+to the netdev @var{nd}. The NIC is an e1000 by default on the PC
44
target. Optionally, the MAC address can be changed to @var{mac}, the
45
device address set to @var{addr} (PCI cards only),
46
and a @var{name} can be assigned for use in monitor commands.
47
--
27
--
48
2.7.4
28
2.7.4
49
29
50
30
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
The information how to update the deprecated parameters was too scarce,
3
gently asked by his automatic reply :)
4
so that some people did not update to the new syntax yet. Provide some
5
more information to make sure that it is clear how to update from the
6
old syntax to the new one.
7
4
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
7
---
11
qemu-doc.texi | 33 +++++++++++++++++++++------------
8
MAINTAINERS | 8 ++++----
12
1 file changed, 21 insertions(+), 12 deletions(-)
9
1 file changed, 4 insertions(+), 4 deletions(-)
13
10
14
diff --git a/qemu-doc.texi b/qemu-doc.texi
11
diff --git a/MAINTAINERS b/MAINTAINERS
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-doc.texi
13
--- a/MAINTAINERS
17
+++ b/qemu-doc.texi
14
+++ b/MAINTAINERS
18
@@ -XXX,XX +XXX,XX @@ combined with ``-vnc tls-creds=tls0'
15
@@ -XXX,XX +XXX,XX @@ F: hw/scsi/mfi.h
19
16
F: tests/megasas-test.c
20
@subsection -tftp (since 2.6.0)
17
21
18
Network packet abstractions
22
-The ``-tftp /some/dir'' argument is now a synonym for setting
19
-M: Dmitry Fleytman <dmitry@daynix.com>
23
-the ``-netdev user,tftp=/some/dir' argument. The new syntax
20
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
24
-allows different settings to be provided per NIC.
21
S: Maintained
25
+The ``-tftp /some/dir'' argument is replaced by
22
F: include/net/eth.h
26
+``-netdev user,id=x,tftp=/some/dir'', either accompanied with
23
F: net/eth.c
27
+``-device ...,netdev=x'' (for pluggable NICs) or ``-net nic,netdev=x''
24
@@ -XXX,XX +XXX,XX @@ F: hw/net/net_rx_pkt*
28
+(for embedded NICs). The new syntax allows different settings to be
25
F: hw/net/net_tx_pkt*
29
+provided per NIC.
26
30
27
Vmware
31
@subsection -bootp (since 2.6.0)
28
-M: Dmitry Fleytman <dmitry@daynix.com>
32
29
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
33
-The ``-bootp /some/file'' argument is now a synonym for setting
30
S: Maintained
34
-the ``-netdev user,bootp=/some/file' argument. The new syntax
31
F: hw/net/vmxnet*
35
-allows different settings to be provided per NIC.
32
F: hw/scsi/vmw_pvscsi*
36
+The ``-bootp /some/file'' argument is replaced by
33
@@ -XXX,XX +XXX,XX @@ F: hw/mem/nvdimm.c
37
+``-netdev user,id=x,bootp=/some/file'', either accompanied with
34
F: include/hw/mem/nvdimm.h
38
+``-device ...,netdev=x'' (for pluggable NICs) or ``-net nic,netdev=x''
35
39
+(for embedded NICs). The new syntax allows different settings to be
36
e1000x
40
+provided per NIC.
37
-M: Dmitry Fleytman <dmitry@daynix.com>
41
38
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
42
@subsection -redir (since 2.6.0)
39
S: Maintained
43
40
F: hw/net/e1000x*
44
-The ``-redir ARGS'' argument is now a synonym for setting
41
45
-the ``-netdev user,hostfwd=ARGS'' argument instead. The new
42
e1000e
46
-syntax allows different settings to be provided per NIC.
43
-M: Dmitry Fleytman <dmitry@daynix.com>
47
+The ``-redir [tcp|udp]:hostport:[guestaddr]:guestport'' argument is
44
+M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
48
+replaced by ``-netdev
45
S: Maintained
49
+user,id=x,hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport'',
46
F: hw/net/e1000e*
50
+either accompanied with ``-device ...,netdev=x'' (for pluggable NICs) or
51
+``-net nic,netdev=x'' (for embedded NICs). The new syntax allows different
52
+settings to be provided per NIC.
53
54
@subsection -smb (since 2.6.0)
55
56
-The ``-smb /some/dir'' argument is now a synonym for setting
57
-the ``-netdev user,smb=/some/dir'' argument instead. The new
58
-syntax allows different settings to be provided per NIC.
59
+The ``-smb /some/dir'' argument is replaced by
60
+``-netdev user,id=x,smb=/some/dir'', either accompanied with
61
+``-device ...,netdev=x'' (for pluggable NICs) or ``-net nic,netdev=x''
62
+(for embedded NICs). The new syntax allows different settings to be
63
+provided per NIC.
64
65
@subsection -net vlan (since 2.9.0)
66
47
67
--
48
--
68
2.7.4
49
2.7.4
69
50
70
51
diff view generated by jsdifflib