1 | The following changes since commit 6632f6ff96f0537fc34cdc00c760656fc62e23c5: | 1 | The following changes since commit 2a95551e8b1456aa53ce54fac573df18809340a6: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/famz/tags/block-and-testing-pull-request' into staging (2017-07-17 11:46:36 +0100) | 3 | Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20200330' into staging (2020-03-31 11:20:21 +0100) |
4 | 4 | ||
5 | are available in the git repository at: | 5 | are available in the git repository at: |
6 | 6 | ||
7 | https://github.com/jasowang/qemu.git tags/net-pull-request | 7 | https://github.com/jasowang/qemu.git tags/net-pull-request |
8 | 8 | ||
9 | for you to fetch changes up to 189ae6bb5ce1f5a322f8691d00fe942ba43dd601: | 9 | for you to fetch changes up to 1153cf9f5b67fad41ca6f8571e9a26e2c7c70759: |
10 | 10 | ||
11 | virtio-net: fix offload ctrl endian (2017-07-17 20:13:56 +0800) | 11 | qtest: add tulip test case (2020-03-31 21:14:35 +0800) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | 14 | ||
15 | - fix virtio-net ctrl offload endian | 15 | Changes from V1: |
16 | - vnet header support for variou COLO netfilters and compare thread | 16 | |
17 | - fix the compiling error | ||
18 | - include qtest for tulip OOB | ||
17 | 19 | ||
18 | ---------------------------------------------------------------- | 20 | ---------------------------------------------------------------- |
19 | Jason Wang (1): | 21 | Andrew Melnychenko (1): |
20 | virtio-net: fix offload ctrl endian | 22 | Fixed integer overflow in e1000e |
21 | 23 | ||
22 | Michal Privoznik (1): | 24 | Li Qiang (1): |
23 | virtion-net: Prefer is_power_of_2() | 25 | qtest: add tulip test case |
24 | 26 | ||
25 | Zhang Chen (12): | 27 | Peter Maydell (2): |
26 | net: Add vnet_hdr_len arguments in NetClientState | 28 | hw/net/i82596.c: Avoid reading off end of buffer in i82596_receive() |
27 | net/net.c: Add vnet_hdr support in SocketReadState | 29 | hw/net/allwinner-sun8i-emac.c: Fix REG_ADDR_HIGH/LOW reads |
28 | net/filter-mirror.c: Introduce parameter for filter_send() | ||
29 | net/filter-mirror.c: Make filter mirror support vnet support. | ||
30 | net/filter-mirror.c: Add new option to enable vnet support for filter-redirector | ||
31 | net/colo.c: Make vnet_hdr_len as packet property | ||
32 | net/colo-compare.c: Introduce parameter for compare_chr_send() | ||
33 | net/colo-compare.c: Make colo-compare support vnet_hdr_len | ||
34 | net/colo.c: Add vnet packet parse feature in colo-proxy | ||
35 | net/colo-compare.c: Add vnet packet's tcp/udp/icmp compare | ||
36 | net/filter-rewriter.c: Make filter-rewriter support vnet_hdr_len | ||
37 | docs/colo-proxy.txt: Update colo-proxy usage of net driver with vnet_header | ||
38 | 30 | ||
39 | docs/colo-proxy.txt | 26 ++++++++++++++++ | 31 | Philippe Mathieu-Daudé (7): |
40 | hw/net/virtio-net.c | 4 ++- | 32 | hw/net/i82596: Correct command bitmask (CID 1419392) |
41 | include/net/net.h | 10 ++++-- | 33 | hw/net/e1000e_core: Let e1000e_can_receive() return a boolean |
42 | net/colo-compare.c | 84 ++++++++++++++++++++++++++++++++++++++++++--------- | 34 | hw/net/smc91c111: Let smc91c111_can_receive() return a boolean |
43 | net/colo.c | 9 +++--- | 35 | hw/net/rtl8139: Simplify if/else statement |
44 | net/colo.h | 4 ++- | 36 | hw/net/rtl8139: Update coding style to make checkpatch.pl happy |
45 | net/filter-mirror.c | 75 +++++++++++++++++++++++++++++++++++++++++---- | 37 | hw/net: Make NetCanReceive() return a boolean |
46 | net/filter-rewriter.c | 37 ++++++++++++++++++++++- | 38 | hw/net/can: Make CanBusClientInfo::can_receive() return a boolean |
47 | net/net.c | 37 ++++++++++++++++++++--- | 39 | |
48 | net/socket.c | 8 ++--- | 40 | Prasad J Pandit (1): |
49 | qemu-options.hx | 19 ++++++------ | 41 | net: tulip: check frame size and r/w data length |
50 | 11 files changed, 265 insertions(+), 48 deletions(-) | 42 | |
43 | Zhang Chen (2): | ||
44 | net/colo-compare.c: Expose "compare_timeout" to users | ||
45 | net/colo-compare.c: Expose "expired_scan_cycle" to users | ||
46 | |||
47 | hw/net/allwinner-sun8i-emac.c | 14 +++---- | ||
48 | hw/net/allwinner_emac.c | 2 +- | ||
49 | hw/net/cadence_gem.c | 8 ++-- | ||
50 | hw/net/can/can_sja1000.c | 8 ++-- | ||
51 | hw/net/can/can_sja1000.h | 2 +- | ||
52 | hw/net/dp8393x.c | 8 ++-- | ||
53 | hw/net/e1000.c | 2 +- | ||
54 | hw/net/e1000e.c | 4 +- | ||
55 | hw/net/e1000e_core.c | 2 +- | ||
56 | hw/net/e1000e_core.h | 2 +- | ||
57 | hw/net/ftgmac100.c | 6 +-- | ||
58 | hw/net/i82596.c | 66 ++++++++++++++++++++---------- | ||
59 | hw/net/i82596.h | 2 +- | ||
60 | hw/net/imx_fec.c | 2 +- | ||
61 | hw/net/opencores_eth.c | 5 +-- | ||
62 | hw/net/rtl8139.c | 22 +++++----- | ||
63 | hw/net/smc91c111.c | 10 ++--- | ||
64 | hw/net/spapr_llan.c | 4 +- | ||
65 | hw/net/sungem.c | 6 +-- | ||
66 | hw/net/sunhme.c | 4 +- | ||
67 | hw/net/tulip.c | 36 ++++++++++++---- | ||
68 | hw/net/virtio-net.c | 10 ++--- | ||
69 | hw/net/xilinx_ethlite.c | 2 +- | ||
70 | include/net/can_emu.h | 2 +- | ||
71 | include/net/net.h | 2 +- | ||
72 | net/can/can_socketcan.c | 4 +- | ||
73 | net/colo-compare.c | 95 ++++++++++++++++++++++++++++++++++++++++--- | ||
74 | net/filter-buffer.c | 2 +- | ||
75 | net/hub.c | 6 +-- | ||
76 | qemu-options.hx | 10 +++-- | ||
77 | tests/qtest/Makefile.include | 1 + | ||
78 | tests/qtest/tulip-test.c | 91 +++++++++++++++++++++++++++++++++++++++++ | ||
79 | 32 files changed, 328 insertions(+), 112 deletions(-) | ||
80 | create mode 100644 tests/qtest/tulip-test.c | ||
51 | 81 | ||
52 | 82 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> |
---|---|---|---|
2 | 2 | ||
3 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 3 | The command is 32-bit, but we are loading the 16 upper bits with |
4 | the 'get_uint16(s->scb + 2)' call. | ||
5 | |||
6 | Once shifted by 16, the command bits match the status bits: | ||
7 | |||
8 | - Command | ||
9 | Bit 31 ACK-CX Acknowledges that the CU completed an Action Command. | ||
10 | Bit 30 ACK-FR Acknowledges that the RU received a frame. | ||
11 | Bit 29 ACK-CNA Acknowledges that the Command Unit became not active. | ||
12 | Bit 28 ACK-RNR Acknowledges that the Receive Unit became not ready. | ||
13 | |||
14 | - Status | ||
15 | Bit 15 CX The CU finished executing a command with its I(interrupt) bit set. | ||
16 | Bit 14 FR The RU finished receiving a frame. | ||
17 | Bit 13 CNA The Command Unit left the Active state. | ||
18 | Bit 12 RNR The Receive Unit left the Ready state. | ||
19 | |||
20 | Add the SCB_COMMAND_ACK_MASK definition to simplify the code. | ||
21 | |||
22 | This fixes Coverity 1419392 (CONSTANT_EXPRESSION_RESULT): | ||
23 | |||
24 | /hw/net/i82596.c: 352 in examine_scb() | ||
25 | 346 cuc = (command >> 8) & 0x7; | ||
26 | 347 ruc = (command >> 4) & 0x7; | ||
27 | 348 DBG(printf("MAIN COMMAND %04x cuc %02x ruc %02x\n", command, cuc, ruc)); | ||
28 | 349 /* and clear the scb command word */ | ||
29 | 350 set_uint16(s->scb + 2, 0); | ||
30 | 351 | ||
31 | >>> CID 1419392: (CONSTANT_EXPRESSION_RESULT) | ||
32 | >>> "command & (2147483648UL /* 1UL << 31 */)" is always 0 regardless of the values of its operands. This occurs as the logical operand of "if". | ||
33 | 352 if (command & BIT(31)) /* ACK-CX */ | ||
34 | 353 s->scb_status &= ~SCB_STATUS_CX; | ||
35 | >>> CID 1419392: (CONSTANT_EXPRESSION_RESULT) | ||
36 | >>> "command & (1073741824UL /* 1UL << 30 */)" is always 0 regardless of the values of its operands. This occurs as the logical operand of "if". | ||
37 | 354 if (command & BIT(30)) /*ACK-FR */ | ||
38 | 355 s->scb_status &= ~SCB_STATUS_FR; | ||
39 | >>> CID 1419392: (CONSTANT_EXPRESSION_RESULT) | ||
40 | >>> "command & (536870912UL /* 1UL << 29 */)" is always 0 regardless of the values of its operands. This occurs as the logical operand of "if". | ||
41 | 356 if (command & BIT(29)) /*ACK-CNA */ | ||
42 | 357 s->scb_status &= ~SCB_STATUS_CNA; | ||
43 | >>> CID 1419392: (CONSTANT_EXPRESSION_RESULT) | ||
44 | >>> "command & (268435456UL /* 1UL << 28 */)" is always 0 regardless of the values of its operands. This occurs as the logical operand of "if". | ||
45 | 358 if (command & BIT(28)) /*ACK-RNR */ | ||
46 | 359 s->scb_status &= ~SCB_STATUS_RNR; | ||
47 | |||
48 | Fixes: Covertiy CID 1419392 (commit 376b851909) | ||
49 | Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
50 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
4 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 51 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
5 | --- | 52 | --- |
6 | docs/colo-proxy.txt | 26 ++++++++++++++++++++++++++ | 53 | hw/net/i82596.c | 12 ++++-------- |
7 | 1 file changed, 26 insertions(+) | 54 | 1 file changed, 4 insertions(+), 8 deletions(-) |
8 | 55 | ||
9 | diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt | 56 | diff --git a/hw/net/i82596.c b/hw/net/i82596.c |
10 | index XXXXXXX..XXXXXXX 100644 | 57 | index XXXXXXX..XXXXXXX 100644 |
11 | --- a/docs/colo-proxy.txt | 58 | --- a/hw/net/i82596.c |
12 | +++ b/docs/colo-proxy.txt | 59 | +++ b/hw/net/i82596.c |
13 | @@ -XXX,XX +XXX,XX @@ Secondary(ip:3.3.3.8): | 60 | @@ -XXX,XX +XXX,XX @@ |
14 | -chardev socket,id=red1,host=3.3.3.3,port=9004 | 61 | #define SCB_STATUS_CNA 0x2000 /* CU left active state */ |
15 | -object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0 | 62 | #define SCB_STATUS_RNR 0x1000 /* RU left active state */ |
16 | -object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1 | 63 | |
17 | +-object filter-rewriter,id=f3,netdev=hn0,queue=all | 64 | +#define SCB_COMMAND_ACK_MASK \ |
65 | + (SCB_STATUS_CX | SCB_STATUS_FR | SCB_STATUS_CNA | SCB_STATUS_RNR) | ||
18 | + | 66 | + |
19 | +If you want to use virtio-net-pci or other driver with vnet_header: | 67 | #define CU_IDLE 0 |
20 | + | 68 | #define CU_SUSPENDED 1 |
21 | +Primary(ip:3.3.3.3): | 69 | #define CU_ACTIVE 2 |
22 | +-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown | 70 | @@ -XXX,XX +XXX,XX @@ static void examine_scb(I82596State *s) |
23 | +-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66 | 71 | /* and clear the scb command word */ |
24 | +-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait | 72 | set_uint16(s->scb + 2, 0); |
25 | +-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait | 73 | |
26 | +-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait | 74 | - if (command & BIT(31)) /* ACK-CX */ |
27 | +-chardev socket,id=compare0-0,host=3.3.3.3,port=9001 | 75 | - s->scb_status &= ~SCB_STATUS_CX; |
28 | +-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait | 76 | - if (command & BIT(30)) /*ACK-FR */ |
29 | +-chardev socket,id=compare_out0,host=3.3.3.3,port=9005 | 77 | - s->scb_status &= ~SCB_STATUS_FR; |
30 | +-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support | 78 | - if (command & BIT(29)) /*ACK-CNA */ |
31 | +-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out,vnet_hdr_support | 79 | - s->scb_status &= ~SCB_STATUS_CNA; |
32 | +-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0,vnet_hdr_support | 80 | - if (command & BIT(28)) /*ACK-RNR */ |
33 | +-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support | 81 | - s->scb_status &= ~SCB_STATUS_RNR; |
34 | + | 82 | + s->scb_status &= ~(command & SCB_COMMAND_ACK_MASK); |
35 | +Secondary(ip:3.3.3.8): | 83 | |
36 | +-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown | 84 | switch (cuc) { |
37 | +-device e1000,netdev=hn0,mac=52:a4:00:12:78:66 | 85 | case 0: /* no change */ |
38 | +-chardev socket,id=red0,host=3.3.3.3,port=9003 | ||
39 | +-chardev socket,id=red1,host=3.3.3.3,port=9004 | ||
40 | +-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0,vnet_hdr_support | ||
41 | +-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1,vnet_hdr_support | ||
42 | +-object filter-rewriter,id=f3,netdev=hn0,queue=all,vnet_hdr_support | ||
43 | |||
44 | Note: | ||
45 | a.COLO-proxy must work with COLO-frame and Block-replication. | ||
46 | -- | 86 | -- |
47 | 2.7.4 | 87 | 2.5.0 |
48 | 88 | ||
49 | 89 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Peter Maydell <peter.maydell@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | COLO-Proxy just focus on packet payload, so we skip vnet header. | 3 | The i82596_receive() function attempts to pass the guest a buffer |
4 | which is effectively the concatenation of the data it is passed and a | ||
5 | 4 byte CRC value. However, rather than implementing this as "write | ||
6 | the data; then write the CRC" it instead bumps the length value of | ||
7 | the data by 4, and writes 4 extra bytes from beyond the end of the | ||
8 | buffer, which it then overwrites with the CRC. It also assumed that | ||
9 | we could always fit all four bytes of the CRC into the final receive | ||
10 | buffer, which might not be true if the CRC needs to be split over two | ||
11 | receive buffers. | ||
4 | 12 | ||
5 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 13 | Calculate separately how many bytes we need to transfer into the |
14 | guest's receive buffer from the source buffer, and how many we need | ||
15 | to transfer from the CRC work. | ||
16 | |||
17 | We add a count 'bufsz' of the number of bytes left in the source | ||
18 | buffer, which we use purely to assert() that we don't overrun. | ||
19 | |||
20 | Spotted by Coverity (CID 1419396) for the specific case when we end | ||
21 | up using a local array as the source buffer. | ||
22 | |||
23 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 24 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
7 | --- | 25 | --- |
8 | net/colo-compare.c | 8 ++++++-- | 26 | hw/net/i82596.c | 44 +++++++++++++++++++++++++++++++++++--------- |
9 | 1 file changed, 6 insertions(+), 2 deletions(-) | 27 | 1 file changed, 35 insertions(+), 9 deletions(-) |
10 | 28 | ||
11 | diff --git a/net/colo-compare.c b/net/colo-compare.c | 29 | diff --git a/hw/net/i82596.c b/hw/net/i82596.c |
12 | index XXXXXXX..XXXXXXX 100644 | 30 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/net/colo-compare.c | 31 | --- a/hw/net/i82596.c |
14 | +++ b/net/colo-compare.c | 32 | +++ b/hw/net/i82596.c |
15 | @@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset) | 33 | @@ -XXX,XX +XXX,XX @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) |
16 | sec_ip_src, sec_ip_dst); | 34 | uint32_t rfd_p; |
35 | uint32_t rbd; | ||
36 | uint16_t is_broadcast = 0; | ||
37 | - size_t len = sz; | ||
38 | + size_t len = sz; /* length of data for guest (including CRC) */ | ||
39 | + size_t bufsz = sz; /* length of data in buf */ | ||
40 | uint32_t crc; | ||
41 | uint8_t *crc_ptr; | ||
42 | uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN]; | ||
43 | @@ -XXX,XX +XXX,XX @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) | ||
44 | if (len < MIN_BUF_SIZE) { | ||
45 | len = MIN_BUF_SIZE; | ||
46 | } | ||
47 | + bufsz = len; | ||
17 | } | 48 | } |
18 | 49 | ||
19 | + offset = ppkt->vnet_hdr_len + offset; | 50 | /* Calculate the ethernet checksum (4 bytes) */ |
51 | @@ -XXX,XX +XXX,XX @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) | ||
52 | while (len) { | ||
53 | uint16_t buffer_size, num; | ||
54 | uint32_t rba; | ||
55 | + size_t bufcount, crccount; | ||
56 | |||
57 | /* printf("Receive: rbd is %08x\n", rbd); */ | ||
58 | buffer_size = get_uint16(rbd + 12); | ||
59 | @@ -XXX,XX +XXX,XX @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) | ||
60 | } | ||
61 | rba = get_uint32(rbd + 8); | ||
62 | /* printf("rba is 0x%x\n", rba); */ | ||
63 | - address_space_write(&address_space_memory, rba, | ||
64 | - MEMTXATTRS_UNSPECIFIED, buf, num); | ||
65 | - rba += num; | ||
66 | - buf += num; | ||
67 | - len -= num; | ||
68 | - if (len == 0) { /* copy crc */ | ||
69 | - address_space_write(&address_space_memory, rba - 4, | ||
70 | - MEMTXATTRS_UNSPECIFIED, crc_ptr, 4); | ||
71 | + /* | ||
72 | + * Calculate how many bytes we want from buf[] and how many | ||
73 | + * from the CRC. | ||
74 | + */ | ||
75 | + if ((len - num) >= 4) { | ||
76 | + /* The whole guest buffer, we haven't hit the CRC yet */ | ||
77 | + bufcount = num; | ||
78 | + } else { | ||
79 | + /* All that's left of buf[] */ | ||
80 | + bufcount = len - 4; | ||
81 | + } | ||
82 | + crccount = num - bufcount; | ||
20 | + | 83 | + |
21 | if (ppkt->size == spkt->size) { | 84 | + if (bufcount > 0) { |
22 | - return memcmp(ppkt->data + offset, spkt->data + offset, | 85 | + /* Still some of the actual data buffer to transfer */ |
23 | + return memcmp(ppkt->data + offset, | 86 | + assert(bufsz >= bufcount); |
24 | + spkt->data + offset, | 87 | + bufsz -= bufcount; |
25 | spkt->size - offset); | 88 | + address_space_write(&address_space_memory, rba, |
26 | } else { | 89 | + MEMTXATTRS_UNSPECIFIED, buf, bufcount); |
27 | trace_colo_compare_main("Net packet size are not the same"); | 90 | + rba += bufcount; |
28 | @@ -XXX,XX +XXX,XX @@ static int colo_packet_compare_tcp(Packet *spkt, Packet *ppkt) | 91 | + buf += bufcount; |
29 | */ | 92 | + len -= bufcount; |
30 | if (ptcp->th_off > 5) { | 93 | + } |
31 | ptrdiff_t tcp_offset; | ||
32 | + | 94 | + |
33 | tcp_offset = ppkt->transport_header - (uint8_t *)ppkt->data | 95 | + /* Write as much of the CRC as fits */ |
34 | - + (ptcp->th_off * 4); | 96 | + if (crccount > 0) { |
35 | + + (ptcp->th_off * 4) - ppkt->vnet_hdr_len; | 97 | + address_space_write(&address_space_memory, rba, |
36 | res = colo_packet_compare_common(ppkt, spkt, tcp_offset); | 98 | + MEMTXATTRS_UNSPECIFIED, crc_ptr, crccount); |
37 | } else if (ptcp->th_sum == stcp->th_sum) { | 99 | + rba += crccount; |
38 | res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN); | 100 | + crc_ptr += crccount; |
101 | + len -= crccount; | ||
102 | } | ||
103 | |||
104 | num |= 0x4000; /* set F BIT */ | ||
39 | -- | 105 | -- |
40 | 2.7.4 | 106 | 2.5.0 |
41 | 107 | ||
42 | 108 | diff view generated by jsdifflib |
1 | From: Michal Privoznik <mprivozn@redhat.com> | 1 | From: Andrew Melnychenko <andrew@daynix.com> |
---|---|---|---|
2 | 2 | ||
3 | We have a function that checks if given number is power of two. | 3 | Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1737400 |
4 | We should prefer it instead of expanding the check on our own. | 4 | Fixed setting max_queue_num if there are no peers in |
5 | NICConf. qemu_new_nic() creates NICState with 1 NetClientState(index | ||
6 | 0) without peers, set max_queue_num to 0 - It prevents undefined | ||
7 | behavior and possible crashes, especially during pcie hotplug. | ||
5 | 8 | ||
6 | Signed-off-by: Michal Privoznik <mprivozn@redhat.com> | 9 | Fixes: 6f3fbe4ed06 ("net: Introduce e1000e device emulation") |
10 | Signed-off-by: Andrew Melnychenko <andrew@daynix.com> | ||
11 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
12 | Reviewed-by: Dmitry Fleytman <dmitry.fleytman@gmail.com> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 13 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
8 | --- | 14 | --- |
9 | hw/net/virtio-net.c | 2 +- | 15 | hw/net/e1000e.c | 2 +- |
10 | 1 file changed, 1 insertion(+), 1 deletion(-) | 16 | 1 file changed, 1 insertion(+), 1 deletion(-) |
11 | 17 | ||
12 | diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c | 18 | diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c |
13 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/hw/net/virtio-net.c | 20 | --- a/hw/net/e1000e.c |
15 | +++ b/hw/net/virtio-net.c | 21 | +++ b/hw/net/e1000e.c |
16 | @@ -XXX,XX +XXX,XX @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) | 22 | @@ -XXX,XX +XXX,XX @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr) |
17 | */ | 23 | s->nic = qemu_new_nic(&net_e1000e_info, &s->conf, |
18 | if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE || | 24 | object_get_typename(OBJECT(s)), dev->id, s); |
19 | n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE || | 25 | |
20 | - (n->net_conf.rx_queue_size & (n->net_conf.rx_queue_size - 1))) { | 26 | - s->core.max_queue_num = s->conf.peers.queues - 1; |
21 | + !is_power_of_2(n->net_conf.rx_queue_size)) { | 27 | + s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; |
22 | error_setg(errp, "Invalid rx_queue_size (= %" PRIu16 "), " | 28 | |
23 | "must be a power of 2 between %d and %d.", | 29 | trace_e1000e_mac_set_permanent(MAC_ARG(macaddr)); |
24 | n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE, | 30 | memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac)); |
25 | -- | 31 | -- |
26 | 2.7.4 | 32 | 2.5.0 |
27 | 33 | ||
28 | 34 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | This patch change the compare_chr_send() parameter from CharBackend to CompareState, | 3 | The e1000e_can_receive() function simply returns a boolean value. |
4 | we can get more information like vnet_hdr(We use it to support packet with vnet_header). | ||
5 | 4 | ||
6 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 5 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
6 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
7 | Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 8 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
8 | --- | 9 | --- |
9 | net/colo-compare.c | 14 +++++++------- | 10 | hw/net/e1000e_core.c | 2 +- |
10 | 1 file changed, 7 insertions(+), 7 deletions(-) | 11 | hw/net/e1000e_core.h | 2 +- |
12 | 2 files changed, 2 insertions(+), 2 deletions(-) | ||
11 | 13 | ||
12 | diff --git a/net/colo-compare.c b/net/colo-compare.c | 14 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c |
13 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/net/colo-compare.c | 16 | --- a/hw/net/e1000e_core.c |
15 | +++ b/net/colo-compare.c | 17 | +++ b/hw/net/e1000e_core.c |
16 | @@ -XXX,XX +XXX,XX @@ enum { | 18 | @@ -XXX,XX +XXX,XX @@ e1000e_start_recv(E1000ECore *core) |
17 | SECONDARY_IN, | ||
18 | }; | ||
19 | |||
20 | -static int compare_chr_send(CharBackend *out, | ||
21 | +static int compare_chr_send(CompareState *s, | ||
22 | const uint8_t *buf, | ||
23 | uint32_t size); | ||
24 | |||
25 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data) | ||
26 | } | ||
27 | |||
28 | if (result) { | ||
29 | - ret = compare_chr_send(&s->chr_out, pkt->data, pkt->size); | ||
30 | + ret = compare_chr_send(s, pkt->data, pkt->size); | ||
31 | if (ret < 0) { | ||
32 | error_report("colo_send_primary_packet failed"); | ||
33 | } | ||
34 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data) | ||
35 | } | 19 | } |
36 | } | 20 | } |
37 | 21 | ||
38 | -static int compare_chr_send(CharBackend *out, | 22 | -int |
39 | +static int compare_chr_send(CompareState *s, | 23 | +bool |
40 | const uint8_t *buf, | 24 | e1000e_can_receive(E1000ECore *core) |
41 | uint32_t size) | ||
42 | { | 25 | { |
43 | @@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CharBackend *out, | 26 | int i; |
44 | return 0; | 27 | diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h |
45 | } | 28 | index XXXXXXX..XXXXXXX 100644 |
46 | 29 | --- a/hw/net/e1000e_core.h | |
47 | - ret = qemu_chr_fe_write_all(out, (uint8_t *)&len, sizeof(len)); | 30 | +++ b/hw/net/e1000e_core.h |
48 | + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); | 31 | @@ -XXX,XX +XXX,XX @@ e1000e_core_set_link_status(E1000ECore *core); |
49 | if (ret != sizeof(len)) { | 32 | void |
50 | goto err; | 33 | e1000e_core_pci_uninit(E1000ECore *core); |
51 | } | 34 | |
52 | 35 | -int | |
53 | - ret = qemu_chr_fe_write_all(out, (uint8_t *)buf, size); | 36 | +bool |
54 | + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size); | 37 | e1000e_can_receive(E1000ECore *core); |
55 | if (ret != size) { | 38 | |
56 | goto err; | 39 | ssize_t |
57 | } | ||
58 | @@ -XXX,XX +XXX,XX @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs) | ||
59 | |||
60 | if (packet_enqueue(s, PRIMARY_IN)) { | ||
61 | trace_colo_compare_main("primary: unsupported packet in"); | ||
62 | - compare_chr_send(&s->chr_out, pri_rs->buf, pri_rs->packet_len); | ||
63 | + compare_chr_send(s, pri_rs->buf, pri_rs->packet_len); | ||
64 | } else { | ||
65 | /* compare connection */ | ||
66 | g_queue_foreach(&s->conn_list, colo_compare_connection, s); | ||
67 | @@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data) | ||
68 | |||
69 | while (!g_queue_is_empty(&conn->primary_list)) { | ||
70 | pkt = g_queue_pop_head(&conn->primary_list); | ||
71 | - compare_chr_send(&s->chr_out, pkt->data, pkt->size); | ||
72 | + compare_chr_send(s, pkt->data, pkt->size); | ||
73 | packet_destroy(pkt, NULL); | ||
74 | } | ||
75 | while (!g_queue_is_empty(&conn->secondary_list)) { | ||
76 | -- | 40 | -- |
77 | 2.7.4 | 41 | 2.5.0 |
78 | 42 | ||
79 | 43 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | We can use this property flush and send packet with vnet_hdr_len. | 3 | The smc91c111_can_receive() function simply returns a boolean value. |
4 | 4 | ||
5 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 5 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
6 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
7 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | ||
6 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 8 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
7 | --- | 9 | --- |
8 | net/colo-compare.c | 8 ++++++-- | 10 | hw/net/smc91c111.c | 8 ++++---- |
9 | net/colo.c | 3 ++- | 11 | 1 file changed, 4 insertions(+), 4 deletions(-) |
10 | net/colo.h | 4 +++- | ||
11 | net/filter-rewriter.c | 2 +- | ||
12 | 4 files changed, 12 insertions(+), 5 deletions(-) | ||
13 | 12 | ||
14 | diff --git a/net/colo-compare.c b/net/colo-compare.c | 13 | diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c |
15 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/net/colo-compare.c | 15 | --- a/hw/net/smc91c111.c |
17 | +++ b/net/colo-compare.c | 16 | +++ b/hw/net/smc91c111.c |
18 | @@ -XXX,XX +XXX,XX @@ static int packet_enqueue(CompareState *s, int mode) | 17 | @@ -XXX,XX +XXX,XX @@ static void smc91c111_update(smc91c111_state *s) |
19 | Connection *conn; | 18 | qemu_set_irq(s->irq, level); |
20 | 19 | } | |
21 | if (mode == PRIMARY_IN) { | 20 | |
22 | - pkt = packet_new(s->pri_rs.buf, s->pri_rs.packet_len); | 21 | -static int smc91c111_can_receive(smc91c111_state *s) |
23 | + pkt = packet_new(s->pri_rs.buf, | 22 | +static bool smc91c111_can_receive(smc91c111_state *s) |
24 | + s->pri_rs.packet_len, | 23 | { |
25 | + s->pri_rs.vnet_hdr_len); | 24 | if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) { |
26 | } else { | 25 | - return 1; |
27 | - pkt = packet_new(s->sec_rs.buf, s->sec_rs.packet_len); | 26 | + return true; |
28 | + pkt = packet_new(s->sec_rs.buf, | ||
29 | + s->sec_rs.packet_len, | ||
30 | + s->sec_rs.vnet_hdr_len); | ||
31 | } | 27 | } |
32 | 28 | if (s->allocated == (1 << NUM_PACKETS) - 1 || | |
33 | if (parse_packet_early(pkt)) { | 29 | s->rx_fifo_len == NUM_PACKETS) { |
34 | diff --git a/net/colo.c b/net/colo.c | 30 | - return 0; |
35 | index XXXXXXX..XXXXXXX 100644 | 31 | + return false; |
36 | --- a/net/colo.c | 32 | } |
37 | +++ b/net/colo.c | 33 | - return 1; |
38 | @@ -XXX,XX +XXX,XX @@ void connection_destroy(void *opaque) | 34 | + return true; |
39 | g_slice_free(Connection, conn); | ||
40 | } | 35 | } |
41 | 36 | ||
42 | -Packet *packet_new(const void *data, int size) | 37 | static inline void smc91c111_flush_queued_packets(smc91c111_state *s) |
43 | +Packet *packet_new(const void *data, int size, int vnet_hdr_len) | ||
44 | { | ||
45 | Packet *pkt = g_slice_new(Packet); | ||
46 | |||
47 | pkt->data = g_memdup(data, size); | ||
48 | pkt->size = size; | ||
49 | pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST); | ||
50 | + pkt->vnet_hdr_len = vnet_hdr_len; | ||
51 | |||
52 | return pkt; | ||
53 | } | ||
54 | diff --git a/net/colo.h b/net/colo.h | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/net/colo.h | ||
57 | +++ b/net/colo.h | ||
58 | @@ -XXX,XX +XXX,XX @@ typedef struct Packet { | ||
59 | int size; | ||
60 | /* Time of packet creation, in wall clock ms */ | ||
61 | int64_t creation_ms; | ||
62 | + /* Get vnet_hdr_len from filter */ | ||
63 | + uint32_t vnet_hdr_len; | ||
64 | } Packet; | ||
65 | |||
66 | typedef struct ConnectionKey { | ||
67 | @@ -XXX,XX +XXX,XX @@ Connection *connection_get(GHashTable *connection_track_table, | ||
68 | ConnectionKey *key, | ||
69 | GQueue *conn_list); | ||
70 | void connection_hashtable_reset(GHashTable *connection_track_table); | ||
71 | -Packet *packet_new(const void *data, int size); | ||
72 | +Packet *packet_new(const void *data, int size, int vnet_hdr_len); | ||
73 | void packet_destroy(void *opaque, void *user_data); | ||
74 | |||
75 | #endif /* QEMU_COLO_PROXY_H */ | ||
76 | diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c | ||
77 | index XXXXXXX..XXXXXXX 100644 | ||
78 | --- a/net/filter-rewriter.c | ||
79 | +++ b/net/filter-rewriter.c | ||
80 | @@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf, | ||
81 | char *buf = g_malloc0(size); | ||
82 | |||
83 | iov_to_buf(iov, iovcnt, 0, buf, size); | ||
84 | - pkt = packet_new(buf, size); | ||
85 | + pkt = packet_new(buf, size, 0); | ||
86 | g_free(buf); | ||
87 | |||
88 | /* | ||
89 | -- | 38 | -- |
90 | 2.7.4 | 39 | 2.5.0 |
91 | 40 | ||
92 | 41 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Add vnet_hdr_len arguments in NetClientState | 3 | Rewrite: |
4 | that make other module get real vnet_hdr_len easily. | ||
5 | 4 | ||
6 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 5 | if (E) { |
6 | return A; | ||
7 | } else { | ||
8 | return B; | ||
9 | } | ||
10 | /* EOF */ | ||
11 | } | ||
12 | |||
13 | as: | ||
14 | |||
15 | if (E) { | ||
16 | return A; | ||
17 | } | ||
18 | return B; | ||
19 | } | ||
20 | |||
21 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
22 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
23 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 24 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
8 | --- | 25 | --- |
9 | include/net/net.h | 1 + | 26 | hw/net/rtl8139.c | 8 ++++---- |
10 | net/net.c | 1 + | 27 | 1 file changed, 4 insertions(+), 4 deletions(-) |
11 | 2 files changed, 2 insertions(+) | ||
12 | 28 | ||
13 | diff --git a/include/net/net.h b/include/net/net.h | 29 | diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c |
14 | index XXXXXXX..XXXXXXX 100644 | 30 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/include/net/net.h | 31 | --- a/hw/net/rtl8139.c |
16 | +++ b/include/net/net.h | 32 | +++ b/hw/net/rtl8139.c |
17 | @@ -XXX,XX +XXX,XX @@ struct NetClientState { | 33 | @@ -XXX,XX +XXX,XX @@ static int rtl8139_can_receive(NetClientState *nc) |
18 | unsigned int queue_index; | 34 | /* ??? Flow control not implemented in c+ mode. |
19 | unsigned rxfilter_notify_enabled:1; | 35 | This is a hack to work around slirp deficiencies anyway. */ |
20 | int vring_enable; | 36 | return 1; |
21 | + int vnet_hdr_len; | 37 | - } else { |
22 | QTAILQ_HEAD(NetFilterHead, NetFilterState) filters; | 38 | - avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, |
23 | }; | 39 | - s->RxBufferSize); |
24 | 40 | - return (avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow)); | |
25 | diff --git a/net/net.c b/net/net.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/net/net.c | ||
28 | +++ b/net/net.c | ||
29 | @@ -XXX,XX +XXX,XX @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len) | ||
30 | return; | ||
31 | } | 41 | } |
32 | 42 | + | |
33 | + nc->vnet_hdr_len = len; | 43 | + avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, |
34 | nc->info->set_vnet_hdr_len(nc, len); | 44 | + s->RxBufferSize); |
45 | + return avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow); | ||
35 | } | 46 | } |
36 | 47 | ||
48 | static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt) | ||
37 | -- | 49 | -- |
38 | 2.7.4 | 50 | 2.5.0 |
39 | 51 | ||
40 | 52 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Make colo-compare and filter-rewriter can parse vnet packet. | 3 | We will modify this code in the next commit. Clean it up |
4 | first to avoid checkpatch.pl errors. | ||
4 | 5 | ||
5 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 6 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
7 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
8 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | ||
6 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 9 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
7 | --- | 10 | --- |
8 | net/colo.c | 6 +++--- | 11 | hw/net/rtl8139.c | 10 ++++++---- |
9 | 1 file changed, 3 insertions(+), 3 deletions(-) | 12 | 1 file changed, 6 insertions(+), 4 deletions(-) |
10 | 13 | ||
11 | diff --git a/net/colo.c b/net/colo.c | 14 | diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c |
12 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/net/colo.c | 16 | --- a/hw/net/rtl8139.c |
14 | +++ b/net/colo.c | 17 | +++ b/hw/net/rtl8139.c |
15 | @@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt) | 18 | @@ -XXX,XX +XXX,XX @@ static int rtl8139_can_receive(NetClientState *nc) |
16 | { | 19 | int avail; |
17 | int network_length; | 20 | |
18 | static const uint8_t vlan[] = {0x81, 0x00}; | 21 | /* Receive (drop) packets if card is disabled. */ |
19 | - uint8_t *data = pkt->data; | 22 | - if (!s->clock_enabled) |
20 | + uint8_t *data = pkt->data + pkt->vnet_hdr_len; | 23 | - return 1; |
21 | uint16_t l3_proto; | 24 | - if (!rtl8139_receiver_enabled(s)) |
22 | ssize_t l2hdr_len = eth_get_l2_hdr_length(data); | 25 | - return 1; |
23 | 26 | + if (!s->clock_enabled) { | |
24 | - if (pkt->size < ETH_HLEN) { | 27 | + return 1; |
25 | + if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) { | 28 | + } |
26 | trace_colo_proxy_main("pkt->size < ETH_HLEN"); | 29 | + if (!rtl8139_receiver_enabled(s)) { |
27 | return 1; | 30 | + return 1; |
28 | } | 31 | + } |
29 | @@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt) | 32 | |
30 | } | 33 | if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) { |
31 | 34 | /* ??? Flow control not implemented in c+ mode. | |
32 | network_length = pkt->ip->ip_hl * 4; | ||
33 | - if (pkt->size < l2hdr_len + network_length) { | ||
34 | + if (pkt->size < l2hdr_len + network_length + pkt->vnet_hdr_len) { | ||
35 | trace_colo_proxy_main("pkt->size < network_header + network_length"); | ||
36 | return 1; | ||
37 | } | ||
38 | -- | 35 | -- |
39 | 2.7.4 | 36 | 2.5.0 |
40 | 37 | ||
41 | 38 | diff view generated by jsdifflib |
1 | Spec said offloads should be le64, so use virtio_ldq_p() to guarantee | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | valid endian. | ||
3 | 2 | ||
4 | Fixes: 644c98587d4c ("virtio-net: dynamic network offloads configuration") | 3 | The NetCanReceive handler return whether the device can or |
5 | Cc: qemu-stable@nongnu.org | 4 | can not receive new packets. Make it obvious by returning |
6 | Cc: Dmitry Fleytman <dfleytma@redhat.com> | 5 | a boolean type. |
6 | |||
7 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
8 | Acked-by: David Gibson <david@gibson.dropbear.id.au> | ||
9 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 11 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
8 | --- | 12 | --- |
9 | hw/net/virtio-net.c | 2 ++ | 13 | hw/net/allwinner_emac.c | 2 +- |
10 | 1 file changed, 2 insertions(+) | 14 | hw/net/cadence_gem.c | 8 ++++---- |
15 | hw/net/dp8393x.c | 8 +++----- | ||
16 | hw/net/e1000.c | 2 +- | ||
17 | hw/net/e1000e.c | 2 +- | ||
18 | hw/net/ftgmac100.c | 6 +++--- | ||
19 | hw/net/i82596.c | 10 +++++----- | ||
20 | hw/net/i82596.h | 2 +- | ||
21 | hw/net/imx_fec.c | 2 +- | ||
22 | hw/net/opencores_eth.c | 5 ++--- | ||
23 | hw/net/rtl8139.c | 8 ++++---- | ||
24 | hw/net/smc91c111.c | 2 +- | ||
25 | hw/net/spapr_llan.c | 4 ++-- | ||
26 | hw/net/sungem.c | 6 +++--- | ||
27 | hw/net/sunhme.c | 4 ++-- | ||
28 | hw/net/virtio-net.c | 10 +++++----- | ||
29 | hw/net/xilinx_ethlite.c | 2 +- | ||
30 | include/net/net.h | 2 +- | ||
31 | net/filter-buffer.c | 2 +- | ||
32 | net/hub.c | 6 +++--- | ||
33 | 20 files changed, 45 insertions(+), 48 deletions(-) | ||
11 | 34 | ||
35 | diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c | ||
36 | index XXXXXXX..XXXXXXX 100644 | ||
37 | --- a/hw/net/allwinner_emac.c | ||
38 | +++ b/hw/net/allwinner_emac.c | ||
39 | @@ -XXX,XX +XXX,XX @@ static uint32_t fifo8_pop_word(Fifo8 *fifo) | ||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | -static int aw_emac_can_receive(NetClientState *nc) | ||
44 | +static bool aw_emac_can_receive(NetClientState *nc) | ||
45 | { | ||
46 | AwEmacState *s = qemu_get_nic_opaque(nc); | ||
47 | |||
48 | diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c | ||
49 | index XXXXXXX..XXXXXXX 100644 | ||
50 | --- a/hw/net/cadence_gem.c | ||
51 | +++ b/hw/net/cadence_gem.c | ||
52 | @@ -XXX,XX +XXX,XX @@ static void phy_update_link(CadenceGEMState *s) | ||
53 | } | ||
54 | } | ||
55 | |||
56 | -static int gem_can_receive(NetClientState *nc) | ||
57 | +static bool gem_can_receive(NetClientState *nc) | ||
58 | { | ||
59 | CadenceGEMState *s; | ||
60 | int i; | ||
61 | @@ -XXX,XX +XXX,XX @@ static int gem_can_receive(NetClientState *nc) | ||
62 | s->can_rx_state = 1; | ||
63 | DB_PRINT("can't receive - no enable\n"); | ||
64 | } | ||
65 | - return 0; | ||
66 | + return false; | ||
67 | } | ||
68 | |||
69 | for (i = 0; i < s->num_priority_queues; i++) { | ||
70 | @@ -XXX,XX +XXX,XX @@ static int gem_can_receive(NetClientState *nc) | ||
71 | s->can_rx_state = 2; | ||
72 | DB_PRINT("can't receive - all the buffer descriptors are busy\n"); | ||
73 | } | ||
74 | - return 0; | ||
75 | + return false; | ||
76 | } | ||
77 | |||
78 | if (s->can_rx_state != 0) { | ||
79 | s->can_rx_state = 0; | ||
80 | DB_PRINT("can receive\n"); | ||
81 | } | ||
82 | - return 1; | ||
83 | + return true; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c | ||
88 | index XXXXXXX..XXXXXXX 100644 | ||
89 | --- a/hw/net/dp8393x.c | ||
90 | +++ b/hw/net/dp8393x.c | ||
91 | @@ -XXX,XX +XXX,XX @@ static void dp8393x_do_stop_timer(dp8393xState *s) | ||
92 | dp8393x_update_wt_regs(s); | ||
93 | } | ||
94 | |||
95 | -static int dp8393x_can_receive(NetClientState *nc); | ||
96 | +static bool dp8393x_can_receive(NetClientState *nc); | ||
97 | |||
98 | static void dp8393x_do_receiver_enable(dp8393xState *s) | ||
99 | { | ||
100 | @@ -XXX,XX +XXX,XX @@ static void dp8393x_watchdog(void *opaque) | ||
101 | dp8393x_update_irq(s); | ||
102 | } | ||
103 | |||
104 | -static int dp8393x_can_receive(NetClientState *nc) | ||
105 | +static bool dp8393x_can_receive(NetClientState *nc) | ||
106 | { | ||
107 | dp8393xState *s = qemu_get_nic_opaque(nc); | ||
108 | |||
109 | - if (!(s->regs[SONIC_CR] & SONIC_CR_RXEN)) | ||
110 | - return 0; | ||
111 | - return 1; | ||
112 | + return !!(s->regs[SONIC_CR] & SONIC_CR_RXEN); | ||
113 | } | ||
114 | |||
115 | static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf, | ||
116 | diff --git a/hw/net/e1000.c b/hw/net/e1000.c | ||
117 | index XXXXXXX..XXXXXXX 100644 | ||
118 | --- a/hw/net/e1000.c | ||
119 | +++ b/hw/net/e1000.c | ||
120 | @@ -XXX,XX +XXX,XX @@ static bool e1000_has_rxbufs(E1000State *s, size_t total_size) | ||
121 | return total_size <= bufs * s->rxbuf_size; | ||
122 | } | ||
123 | |||
124 | -static int | ||
125 | +static bool | ||
126 | e1000_can_receive(NetClientState *nc) | ||
127 | { | ||
128 | E1000State *s = qemu_get_nic_opaque(nc); | ||
129 | diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c | ||
130 | index XXXXXXX..XXXXXXX 100644 | ||
131 | --- a/hw/net/e1000e.c | ||
132 | +++ b/hw/net/e1000e.c | ||
133 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps io_ops = { | ||
134 | }, | ||
135 | }; | ||
136 | |||
137 | -static int | ||
138 | +static bool | ||
139 | e1000e_nc_can_receive(NetClientState *nc) | ||
140 | { | ||
141 | E1000EState *s = qemu_get_nic_opaque(nc); | ||
142 | diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c | ||
143 | index XXXXXXX..XXXXXXX 100644 | ||
144 | --- a/hw/net/ftgmac100.c | ||
145 | +++ b/hw/net/ftgmac100.c | ||
146 | @@ -XXX,XX +XXX,XX @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, | ||
147 | ftgmac100_update_irq(s); | ||
148 | } | ||
149 | |||
150 | -static int ftgmac100_can_receive(NetClientState *nc) | ||
151 | +static bool ftgmac100_can_receive(NetClientState *nc) | ||
152 | { | ||
153 | FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc)); | ||
154 | FTGMAC100Desc bd; | ||
155 | |||
156 | if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) | ||
157 | != (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) { | ||
158 | - return 0; | ||
159 | + return false; | ||
160 | } | ||
161 | |||
162 | if (ftgmac100_read_bd(&bd, s->rx_descriptor)) { | ||
163 | - return 0; | ||
164 | + return false; | ||
165 | } | ||
166 | return !(bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY); | ||
167 | } | ||
168 | diff --git a/hw/net/i82596.c b/hw/net/i82596.c | ||
169 | index XXXXXXX..XXXXXXX 100644 | ||
170 | --- a/hw/net/i82596.c | ||
171 | +++ b/hw/net/i82596.c | ||
172 | @@ -XXX,XX +XXX,XX @@ void i82596_h_reset(void *opaque) | ||
173 | i82596_s_reset(s); | ||
174 | } | ||
175 | |||
176 | -int i82596_can_receive(NetClientState *nc) | ||
177 | +bool i82596_can_receive(NetClientState *nc) | ||
178 | { | ||
179 | I82596State *s = qemu_get_nic_opaque(nc); | ||
180 | |||
181 | if (s->rx_status == RX_SUSPENDED) { | ||
182 | - return 0; | ||
183 | + return false; | ||
184 | } | ||
185 | |||
186 | if (!s->lnkst) { | ||
187 | - return 0; | ||
188 | + return false; | ||
189 | } | ||
190 | |||
191 | if (USE_TIMER && !timer_pending(s->flush_queue_timer)) { | ||
192 | - return 1; | ||
193 | + return true; | ||
194 | } | ||
195 | |||
196 | - return 1; | ||
197 | + return true; | ||
198 | } | ||
199 | |||
200 | #define MIN_BUF_SIZE 60 | ||
201 | diff --git a/hw/net/i82596.h b/hw/net/i82596.h | ||
202 | index XXXXXXX..XXXXXXX 100644 | ||
203 | --- a/hw/net/i82596.h | ||
204 | +++ b/hw/net/i82596.h | ||
205 | @@ -XXX,XX +XXX,XX @@ void i82596_ioport_writel(void *opaque, uint32_t addr, uint32_t val); | ||
206 | uint32_t i82596_ioport_readl(void *opaque, uint32_t addr); | ||
207 | uint32_t i82596_bcr_readw(I82596State *s, uint32_t rap); | ||
208 | ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t size_); | ||
209 | -int i82596_can_receive(NetClientState *nc); | ||
210 | +bool i82596_can_receive(NetClientState *nc); | ||
211 | void i82596_set_link_status(NetClientState *nc); | ||
212 | void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info); | ||
213 | extern const VMStateDescription vmstate_i82596; | ||
214 | diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c | ||
215 | index XXXXXXX..XXXXXXX 100644 | ||
216 | --- a/hw/net/imx_fec.c | ||
217 | +++ b/hw/net/imx_fec.c | ||
218 | @@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, | ||
219 | imx_eth_update(s); | ||
220 | } | ||
221 | |||
222 | -static int imx_eth_can_receive(NetClientState *nc) | ||
223 | +static bool imx_eth_can_receive(NetClientState *nc) | ||
224 | { | ||
225 | IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc)); | ||
226 | |||
227 | diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c | ||
228 | index XXXXXXX..XXXXXXX 100644 | ||
229 | --- a/hw/net/opencores_eth.c | ||
230 | +++ b/hw/net/opencores_eth.c | ||
231 | @@ -XXX,XX +XXX,XX @@ static void open_eth_reset(void *opaque) | ||
232 | open_eth_set_link_status(qemu_get_queue(s->nic)); | ||
233 | } | ||
234 | |||
235 | -static int open_eth_can_receive(NetClientState *nc) | ||
236 | +static bool open_eth_can_receive(NetClientState *nc) | ||
237 | { | ||
238 | OpenEthState *s = qemu_get_nic_opaque(nc); | ||
239 | |||
240 | - return GET_REGBIT(s, MODER, RXEN) && | ||
241 | - (s->regs[TX_BD_NUM] < 0x80); | ||
242 | + return GET_REGBIT(s, MODER, RXEN) && (s->regs[TX_BD_NUM] < 0x80); | ||
243 | } | ||
244 | |||
245 | static ssize_t open_eth_receive(NetClientState *nc, | ||
246 | diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c | ||
247 | index XXXXXXX..XXXXXXX 100644 | ||
248 | --- a/hw/net/rtl8139.c | ||
249 | +++ b/hw/net/rtl8139.c | ||
250 | @@ -XXX,XX +XXX,XX @@ static bool rtl8139_cp_rx_valid(RTL8139State *s) | ||
251 | return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0); | ||
252 | } | ||
253 | |||
254 | -static int rtl8139_can_receive(NetClientState *nc) | ||
255 | +static bool rtl8139_can_receive(NetClientState *nc) | ||
256 | { | ||
257 | RTL8139State *s = qemu_get_nic_opaque(nc); | ||
258 | int avail; | ||
259 | |||
260 | /* Receive (drop) packets if card is disabled. */ | ||
261 | if (!s->clock_enabled) { | ||
262 | - return 1; | ||
263 | + return true; | ||
264 | } | ||
265 | if (!rtl8139_receiver_enabled(s)) { | ||
266 | - return 1; | ||
267 | + return true; | ||
268 | } | ||
269 | |||
270 | if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) { | ||
271 | /* ??? Flow control not implemented in c+ mode. | ||
272 | This is a hack to work around slirp deficiencies anyway. */ | ||
273 | - return 1; | ||
274 | + return true; | ||
275 | } | ||
276 | |||
277 | avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, | ||
278 | diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c | ||
279 | index XXXXXXX..XXXXXXX 100644 | ||
280 | --- a/hw/net/smc91c111.c | ||
281 | +++ b/hw/net/smc91c111.c | ||
282 | @@ -XXX,XX +XXX,XX @@ static void smc91c111_writefn(void *opaque, hwaddr addr, | ||
283 | } | ||
284 | } | ||
285 | |||
286 | -static int smc91c111_can_receive_nc(NetClientState *nc) | ||
287 | +static bool smc91c111_can_receive_nc(NetClientState *nc) | ||
288 | { | ||
289 | smc91c111_state *s = qemu_get_nic_opaque(nc); | ||
290 | |||
291 | diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c | ||
292 | index XXXXXXX..XXXXXXX 100644 | ||
293 | --- a/hw/net/spapr_llan.c | ||
294 | +++ b/hw/net/spapr_llan.c | ||
295 | @@ -XXX,XX +XXX,XX @@ typedef struct SpaprVioVlan { | ||
296 | RxBufPool *rx_pool[RX_MAX_POOLS]; /* Receive buffer descriptor pools */ | ||
297 | } SpaprVioVlan; | ||
298 | |||
299 | -static int spapr_vlan_can_receive(NetClientState *nc) | ||
300 | +static bool spapr_vlan_can_receive(NetClientState *nc) | ||
301 | { | ||
302 | SpaprVioVlan *dev = qemu_get_nic_opaque(nc); | ||
303 | |||
304 | - return (dev->isopen && dev->rx_bufs > 0); | ||
305 | + return dev->isopen && dev->rx_bufs > 0; | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | diff --git a/hw/net/sungem.c b/hw/net/sungem.c | ||
310 | index XXXXXXX..XXXXXXX 100644 | ||
311 | --- a/hw/net/sungem.c | ||
312 | +++ b/hw/net/sungem.c | ||
313 | @@ -XXX,XX +XXX,XX @@ static bool sungem_rx_full(SunGEMState *s, uint32_t kick, uint32_t done) | ||
314 | return kick == ((done + 1) & s->rx_mask); | ||
315 | } | ||
316 | |||
317 | -static int sungem_can_receive(NetClientState *nc) | ||
318 | +static bool sungem_can_receive(NetClientState *nc) | ||
319 | { | ||
320 | SunGEMState *s = qemu_get_nic_opaque(nc); | ||
321 | uint32_t kick, done, rxdma_cfg, rxmac_cfg; | ||
322 | @@ -XXX,XX +XXX,XX @@ static int sungem_can_receive(NetClientState *nc) | ||
323 | /* If MAC disabled, can't receive */ | ||
324 | if ((rxmac_cfg & MAC_RXCFG_ENAB) == 0) { | ||
325 | trace_sungem_rx_mac_disabled(); | ||
326 | - return 0; | ||
327 | + return false; | ||
328 | } | ||
329 | if ((rxdma_cfg & RXDMA_CFG_ENABLE) == 0) { | ||
330 | trace_sungem_rx_txdma_disabled(); | ||
331 | - return 0; | ||
332 | + return false; | ||
333 | } | ||
334 | |||
335 | /* Check RX availability */ | ||
336 | diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c | ||
337 | index XXXXXXX..XXXXXXX 100644 | ||
338 | --- a/hw/net/sunhme.c | ||
339 | +++ b/hw/net/sunhme.c | ||
340 | @@ -XXX,XX +XXX,XX @@ static void sunhme_transmit(SunHMEState *s) | ||
341 | sunhme_update_irq(s); | ||
342 | } | ||
343 | |||
344 | -static int sunhme_can_receive(NetClientState *nc) | ||
345 | +static bool sunhme_can_receive(NetClientState *nc) | ||
346 | { | ||
347 | SunHMEState *s = qemu_get_nic_opaque(nc); | ||
348 | |||
349 | - return s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE; | ||
350 | + return !!(s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE); | ||
351 | } | ||
352 | |||
353 | static void sunhme_link_status_changed(NetClientState *nc) | ||
12 | diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c | 354 | diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c |
13 | index XXXXXXX..XXXXXXX 100644 | 355 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/hw/net/virtio-net.c | 356 | --- a/hw/net/virtio-net.c |
15 | +++ b/hw/net/virtio-net.c | 357 | +++ b/hw/net/virtio-net.c |
16 | @@ -XXX,XX +XXX,XX @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd, | 358 | @@ -XXX,XX +XXX,XX @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) |
17 | if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) { | 359 | qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index)); |
18 | uint64_t supported_offloads; | 360 | } |
19 | 361 | ||
20 | + offloads = virtio_ldq_p(vdev, &offloads); | 362 | -static int virtio_net_can_receive(NetClientState *nc) |
21 | + | 363 | +static bool virtio_net_can_receive(NetClientState *nc) |
22 | if (!n->has_vnet_hdr) { | 364 | { |
23 | return VIRTIO_NET_ERR; | 365 | VirtIONet *n = qemu_get_nic_opaque(nc); |
366 | VirtIODevice *vdev = VIRTIO_DEVICE(n); | ||
367 | VirtIONetQueue *q = virtio_net_get_subqueue(nc); | ||
368 | |||
369 | if (!vdev->vm_running) { | ||
370 | - return 0; | ||
371 | + return false; | ||
372 | } | ||
373 | |||
374 | if (nc->queue_index >= n->curr_queues) { | ||
375 | - return 0; | ||
376 | + return false; | ||
377 | } | ||
378 | |||
379 | if (!virtio_queue_ready(q->rx_vq) || | ||
380 | !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { | ||
381 | - return 0; | ||
382 | + return false; | ||
383 | } | ||
384 | |||
385 | - return 1; | ||
386 | + return true; | ||
387 | } | ||
388 | |||
389 | static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize) | ||
390 | diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c | ||
391 | index XXXXXXX..XXXXXXX 100644 | ||
392 | --- a/hw/net/xilinx_ethlite.c | ||
393 | +++ b/hw/net/xilinx_ethlite.c | ||
394 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps eth_ops = { | ||
395 | } | ||
396 | }; | ||
397 | |||
398 | -static int eth_can_rx(NetClientState *nc) | ||
399 | +static bool eth_can_rx(NetClientState *nc) | ||
400 | { | ||
401 | struct xlx_ethlite *s = qemu_get_nic_opaque(nc); | ||
402 | unsigned int rxbase = s->rxbuf * (0x800 / 4); | ||
403 | diff --git a/include/net/net.h b/include/net/net.h | ||
404 | index XXXXXXX..XXXXXXX 100644 | ||
405 | --- a/include/net/net.h | ||
406 | +++ b/include/net/net.h | ||
407 | @@ -XXX,XX +XXX,XX @@ typedef struct NICConf { | ||
408 | /* Net clients */ | ||
409 | |||
410 | typedef void (NetPoll)(NetClientState *, bool enable); | ||
411 | -typedef int (NetCanReceive)(NetClientState *); | ||
412 | +typedef bool (NetCanReceive)(NetClientState *); | ||
413 | typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); | ||
414 | typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); | ||
415 | typedef void (NetCleanup) (NetClientState *); | ||
416 | diff --git a/net/filter-buffer.c b/net/filter-buffer.c | ||
417 | index XXXXXXX..XXXXXXX 100644 | ||
418 | --- a/net/filter-buffer.c | ||
419 | +++ b/net/filter-buffer.c | ||
420 | @@ -XXX,XX +XXX,XX @@ static ssize_t filter_buffer_receive_iov(NetFilterState *nf, | ||
421 | * the filter can still accept packets until its internal queue is full. | ||
422 | * For example: | ||
423 | * For some reason, receiver could not receive more packets | ||
424 | - * (.can_receive() returns zero). Without a filter, at most one packet | ||
425 | + * (.can_receive() returns false). Without a filter, at most one packet | ||
426 | * will be queued in incoming queue and sender's poll will be disabled | ||
427 | * unit its sent_cb() was called. With a filter, it will keep receiving | ||
428 | * the packets without caring about the receiver. This is suboptimal. | ||
429 | diff --git a/net/hub.c b/net/hub.c | ||
430 | index XXXXXXX..XXXXXXX 100644 | ||
431 | --- a/net/hub.c | ||
432 | +++ b/net/hub.c | ||
433 | @@ -XXX,XX +XXX,XX @@ static NetHub *net_hub_new(int id) | ||
434 | return hub; | ||
435 | } | ||
436 | |||
437 | -static int net_hub_port_can_receive(NetClientState *nc) | ||
438 | +static bool net_hub_port_can_receive(NetClientState *nc) | ||
439 | { | ||
440 | NetHubPort *port; | ||
441 | NetHubPort *src_port = DO_UPCAST(NetHubPort, nc, nc); | ||
442 | @@ -XXX,XX +XXX,XX @@ static int net_hub_port_can_receive(NetClientState *nc) | ||
24 | } | 443 | } |
444 | |||
445 | if (qemu_can_send_packet(&port->nc)) { | ||
446 | - return 1; | ||
447 | + return true; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | - return 0; | ||
452 | + return false; | ||
453 | } | ||
454 | |||
455 | static ssize_t net_hub_port_receive(NetClientState *nc, | ||
25 | -- | 456 | -- |
26 | 2.7.4 | 457 | 2.5.0 |
27 | 458 | ||
28 | 459 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | We add the vnet_hdr_support option for filter-mirror, default is disabled. | 3 | The CanBusClientInfo::can_receive handler return whether the |
4 | If you use virtio-net-pci or other driver needs vnet_hdr, please enable it. | 4 | device can or can not receive new frames. Make it obvious by |
5 | You can use it for example: | 5 | returning a boolean type. |
6 | -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support | ||
7 | 6 | ||
8 | If it has vnet_hdr_support flag, we will change the sending packet format from | 7 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
9 | struct {int size; const uint8_t buf[];} to {int size; int vnet_hdr_len; const uint8_t buf[];}. | 8 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> |
10 | make other module(like colo-compare) know how to parse net packet correctly. | 9 | Reviewed-by: Cédric Le Goater <clg@kaod.org> |
11 | |||
12 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | ||
13 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 10 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
14 | --- | 11 | --- |
15 | net/filter-mirror.c | 42 +++++++++++++++++++++++++++++++++++++++++- | 12 | hw/net/allwinner-sun8i-emac.c | 2 +- |
16 | qemu-options.hx | 5 ++--- | 13 | hw/net/can/can_sja1000.c | 8 ++++---- |
17 | 2 files changed, 43 insertions(+), 4 deletions(-) | 14 | hw/net/can/can_sja1000.h | 2 +- |
15 | include/net/can_emu.h | 2 +- | ||
16 | net/can/can_socketcan.c | 4 ++-- | ||
17 | 5 files changed, 9 insertions(+), 9 deletions(-) | ||
18 | 18 | ||
19 | diff --git a/net/filter-mirror.c b/net/filter-mirror.c | 19 | diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c |
20 | index XXXXXXX..XXXXXXX 100644 | 20 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/net/filter-mirror.c | 21 | --- a/hw/net/allwinner-sun8i-emac.c |
22 | +++ b/net/filter-mirror.c | 22 | +++ b/hw/net/allwinner-sun8i-emac.c |
23 | @@ -XXX,XX +XXX,XX @@ typedef struct MirrorState { | 23 | @@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_flush_desc(FrameDescriptor *desc, |
24 | CharBackend chr_in; | 24 | cpu_physical_memory_write(phys_addr, desc, sizeof(*desc)); |
25 | CharBackend chr_out; | 25 | } |
26 | SocketReadState rs; | 26 | |
27 | + bool vnet_hdr; | 27 | -static int allwinner_sun8i_emac_can_receive(NetClientState *nc) |
28 | } MirrorState; | 28 | +static bool allwinner_sun8i_emac_can_receive(NetClientState *nc) |
29 | |||
30 | static int filter_send(MirrorState *s, | ||
31 | const struct iovec *iov, | ||
32 | int iovcnt) | ||
33 | { | 29 | { |
34 | + NetFilterState *nf = NETFILTER(s); | 30 | AwSun8iEmacState *s = qemu_get_nic_opaque(nc); |
35 | int ret = 0; | 31 | FrameDescriptor desc; |
36 | ssize_t size = 0; | 32 | diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c |
37 | uint32_t len = 0; | 33 | index XXXXXXX..XXXXXXX 100644 |
38 | @@ -XXX,XX +XXX,XX @@ static int filter_send(MirrorState *s, | 34 | --- a/hw/net/can/can_sja1000.c |
39 | goto err; | 35 | +++ b/hw/net/can/can_sja1000.c |
40 | } | 36 | @@ -XXX,XX +XXX,XX @@ uint64_t can_sja_mem_read(CanSJA1000State *s, hwaddr addr, unsigned size) |
41 | 37 | return temp; | |
42 | + if (s->vnet_hdr) { | 38 | } |
43 | + /* | 39 | |
44 | + * If vnet_hdr = on, we send vnet header len to make other | 40 | -int can_sja_can_receive(CanBusClientState *client) |
45 | + * module(like colo-compare) know how to parse net | 41 | +bool can_sja_can_receive(CanBusClientState *client) |
46 | + * packet correctly. | 42 | { |
47 | + */ | 43 | CanSJA1000State *s = container_of(client, CanSJA1000State, bus_client); |
48 | + ssize_t vnet_hdr_len; | 44 | |
49 | + | 45 | if (s->clock & 0x80) { /* PeliCAN Mode */ |
50 | + vnet_hdr_len = nf->netdev->vnet_hdr_len; | 46 | if (s->mode & 0x01) { /* reset mode. */ |
51 | + | 47 | - return 0; |
52 | + len = htonl(vnet_hdr_len); | 48 | + return false; |
53 | + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); | 49 | } |
54 | + if (ret != sizeof(len)) { | 50 | } else { /* BasicCAN mode */ |
55 | + goto err; | 51 | if (s->control & 0x01) { |
56 | + } | 52 | - return 0; |
57 | + } | 53 | + return false; |
58 | + | ||
59 | buf = g_malloc(size); | ||
60 | iov_to_buf(iov, iovcnt, 0, buf, size); | ||
61 | ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size); | ||
62 | @@ -XXX,XX +XXX,XX @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp) | ||
63 | } | 54 | } |
64 | } | 55 | } |
65 | 56 | ||
66 | - net_socket_rs_init(&s->rs, redirector_rs_finalize, false); | 57 | - return 1; /* always return 1, when operation mode */ |
67 | + net_socket_rs_init(&s->rs, redirector_rs_finalize, s->vnet_hdr); | 58 | + return true; /* always return true, when operation mode */ |
68 | 59 | } | |
69 | if (s->indev) { | 60 | |
70 | chr = qemu_chr_find(s->indev); | 61 | ssize_t can_sja_receive(CanBusClientState *client, const qemu_can_frame *frames, |
71 | @@ -XXX,XX +XXX,XX @@ static void filter_mirror_set_outdev(Object *obj, | 62 | diff --git a/hw/net/can/can_sja1000.h b/hw/net/can/can_sja1000.h |
63 | index XXXXXXX..XXXXXXX 100644 | ||
64 | --- a/hw/net/can/can_sja1000.h | ||
65 | +++ b/hw/net/can/can_sja1000.h | ||
66 | @@ -XXX,XX +XXX,XX @@ void can_sja_disconnect(CanSJA1000State *s); | ||
67 | |||
68 | int can_sja_init(CanSJA1000State *s, qemu_irq irq); | ||
69 | |||
70 | -int can_sja_can_receive(CanBusClientState *client); | ||
71 | +bool can_sja_can_receive(CanBusClientState *client); | ||
72 | |||
73 | ssize_t can_sja_receive(CanBusClientState *client, | ||
74 | const qemu_can_frame *frames, size_t frames_cnt); | ||
75 | diff --git a/include/net/can_emu.h b/include/net/can_emu.h | ||
76 | index XXXXXXX..XXXXXXX 100644 | ||
77 | --- a/include/net/can_emu.h | ||
78 | +++ b/include/net/can_emu.h | ||
79 | @@ -XXX,XX +XXX,XX @@ typedef struct CanBusClientState CanBusClientState; | ||
80 | typedef struct CanBusState CanBusState; | ||
81 | |||
82 | typedef struct CanBusClientInfo { | ||
83 | - int (*can_receive)(CanBusClientState *); | ||
84 | + bool (*can_receive)(CanBusClientState *); | ||
85 | ssize_t (*receive)(CanBusClientState *, | ||
86 | const struct qemu_can_frame *frames, size_t frames_cnt); | ||
87 | } CanBusClientInfo; | ||
88 | diff --git a/net/can/can_socketcan.c b/net/can/can_socketcan.c | ||
89 | index XXXXXXX..XXXXXXX 100644 | ||
90 | --- a/net/can/can_socketcan.c | ||
91 | +++ b/net/can/can_socketcan.c | ||
92 | @@ -XXX,XX +XXX,XX @@ static void can_host_socketcan_read(void *opaque) | ||
72 | } | 93 | } |
73 | } | 94 | } |
74 | 95 | ||
75 | +static bool filter_mirror_get_vnet_hdr(Object *obj, Error **errp) | 96 | -static int can_host_socketcan_can_receive(CanBusClientState *client) |
76 | +{ | 97 | +static bool can_host_socketcan_can_receive(CanBusClientState *client) |
77 | + MirrorState *s = FILTER_MIRROR(obj); | ||
78 | + | ||
79 | + return s->vnet_hdr; | ||
80 | +} | ||
81 | + | ||
82 | +static void filter_mirror_set_vnet_hdr(Object *obj, bool value, Error **errp) | ||
83 | +{ | ||
84 | + MirrorState *s = FILTER_MIRROR(obj); | ||
85 | + | ||
86 | + s->vnet_hdr = value; | ||
87 | +} | ||
88 | + | ||
89 | static char *filter_redirector_get_outdev(Object *obj, Error **errp) | ||
90 | { | 98 | { |
91 | MirrorState *s = FILTER_REDIRECTOR(obj); | 99 | - return 1; |
92 | @@ -XXX,XX +XXX,XX @@ static void filter_redirector_set_outdev(Object *obj, | 100 | + return true; |
93 | |||
94 | static void filter_mirror_init(Object *obj) | ||
95 | { | ||
96 | + MirrorState *s = FILTER_MIRROR(obj); | ||
97 | + | ||
98 | object_property_add_str(obj, "outdev", filter_mirror_get_outdev, | ||
99 | filter_mirror_set_outdev, NULL); | ||
100 | + | ||
101 | + s->vnet_hdr = false; | ||
102 | + object_property_add_bool(obj, "vnet_hdr_support", | ||
103 | + filter_mirror_get_vnet_hdr, | ||
104 | + filter_mirror_set_vnet_hdr, NULL); | ||
105 | } | 101 | } |
106 | 102 | ||
107 | static void filter_redirector_init(Object *obj) | 103 | static ssize_t can_host_socketcan_receive(CanBusClientState *client, |
108 | diff --git a/qemu-options.hx b/qemu-options.hx | ||
109 | index XXXXXXX..XXXXXXX 100644 | ||
110 | --- a/qemu-options.hx | ||
111 | +++ b/qemu-options.hx | ||
112 | @@ -XXX,XX +XXX,XX @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter. | ||
113 | @option{tx}: the filter is attached to the transmit queue of the netdev, | ||
114 | where it will receive packets sent by the netdev. | ||
115 | |||
116 | -@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid}[,queue=@var{all|rx|tx}] | ||
117 | +@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support] | ||
118 | |||
119 | -filter-mirror on netdev @var{netdevid},mirror net packet to chardev | ||
120 | -@var{chardevid} | ||
121 | +filter-mirror on netdev @var{netdevid},mirror net packet to chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror will mirror packet with vnet_hdr_len. | ||
122 | |||
123 | @item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid}, | ||
124 | outdev=@var{chardevid}[,queue=@var{all|rx|tx}] | ||
125 | -- | 104 | -- |
126 | 2.7.4 | 105 | 2.5.0 |
127 | 106 | ||
128 | 107 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Zhang Chen <chen.zhang@intel.com> |
---|---|---|---|
2 | 2 | ||
3 | We add the vnet_hdr_support option for colo-compare, default is disabled. | 3 | The "compare_timeout" determines the maximum time to hold the primary net packet. |
4 | If you use virtio-net-pci or other driver needs vnet_hdr, please enable it. | 4 | This patch expose the "compare_timeout", make user have ability to |
5 | You can use it for example: | 5 | adjest the value according to application scenarios. |
6 | -object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,vnet_hdr_support | ||
7 | 6 | ||
8 | COLO-compare can get vnet header length from filter, | 7 | QMP command demo: |
9 | Add vnet_hdr_len to struct packet and output packet with | 8 | { "execute": "qom-get", |
10 | the vnet_hdr_len. | 9 | "arguments": { "path": "/objects/comp0", |
10 | "property": "compare_timeout" } } | ||
11 | 11 | ||
12 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 12 | { "execute": "qom-set", |
13 | "arguments": { "path": "/objects/comp0", | ||
14 | "property": "compare_timeout", | ||
15 | "value": 5000} } | ||
16 | |||
17 | Signed-off-by: Zhang Chen <chen.zhang@intel.com> | ||
13 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 18 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
14 | --- | 19 | --- |
15 | net/colo-compare.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++------- | 20 | net/colo-compare.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- |
16 | qemu-options.hx | 4 ++-- | 21 | qemu-options.hx | 8 +++++--- |
17 | 2 files changed, 55 insertions(+), 9 deletions(-) | 22 | 2 files changed, 50 insertions(+), 5 deletions(-) |
18 | 23 | ||
19 | diff --git a/net/colo-compare.c b/net/colo-compare.c | 24 | diff --git a/net/colo-compare.c b/net/colo-compare.c |
20 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/net/colo-compare.c | 26 | --- a/net/colo-compare.c |
22 | +++ b/net/colo-compare.c | 27 | +++ b/net/colo-compare.c |
28 | @@ -XXX,XX +XXX,XX @@ static NotifierList colo_compare_notifiers = | ||
29 | |||
30 | /* TODO: Should be configurable */ | ||
31 | #define REGULAR_PACKET_CHECK_MS 3000 | ||
32 | +#define DEFAULT_TIME_OUT_MS 3000 | ||
33 | |||
34 | static QemuMutex event_mtx; | ||
35 | static QemuCond event_complete_cond; | ||
23 | @@ -XXX,XX +XXX,XX @@ typedef struct CompareState { | 36 | @@ -XXX,XX +XXX,XX @@ typedef struct CompareState { |
24 | CharBackend chr_out; | ||
25 | SocketReadState pri_rs; | ||
26 | SocketReadState sec_rs; | 37 | SocketReadState sec_rs; |
27 | + bool vnet_hdr; | 38 | SocketReadState notify_rs; |
28 | 39 | bool vnet_hdr; | |
29 | /* connection list: the connections belonged to this NIC could be found | 40 | + uint32_t compare_timeout; |
30 | * in this list. | 41 | |
31 | @@ -XXX,XX +XXX,XX @@ enum { | 42 | /* |
32 | 43 | * Record the connection that through the NIC | |
33 | static int compare_chr_send(CompareState *s, | 44 | @@ -XXX,XX +XXX,XX @@ static int colo_old_packet_check_one_conn(Connection *conn, |
34 | const uint8_t *buf, | 45 | CompareState *s) |
35 | - uint32_t size); | ||
36 | + uint32_t size, | ||
37 | + uint32_t vnet_hdr_len); | ||
38 | |||
39 | static gint seq_sorter(Packet *a, Packet *b, gpointer data) | ||
40 | { | 46 | { |
41 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data) | 47 | GList *result = NULL; |
42 | } | 48 | - int64_t check_time = REGULAR_PACKET_CHECK_MS; |
43 | 49 | ||
44 | if (result) { | 50 | result = g_queue_find_custom(&conn->primary_list, |
45 | - ret = compare_chr_send(s, pkt->data, pkt->size); | 51 | - &check_time, |
46 | + ret = compare_chr_send(s, | 52 | + &s->compare_timeout, |
47 | + pkt->data, | 53 | (GCompareFunc)colo_old_packet_check_one); |
48 | + pkt->size, | 54 | |
49 | + pkt->vnet_hdr_len); | 55 | if (result) { |
50 | if (ret < 0) { | 56 | @@ -XXX,XX +XXX,XX @@ static void compare_set_notify_dev(Object *obj, const char *value, Error **errp) |
51 | error_report("colo_send_primary_packet failed"); | 57 | s->notify_dev = g_strdup(value); |
52 | } | ||
53 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_connection(void *opaque, void *user_data) | ||
54 | |||
55 | static int compare_chr_send(CompareState *s, | ||
56 | const uint8_t *buf, | ||
57 | - uint32_t size) | ||
58 | + uint32_t size, | ||
59 | + uint32_t vnet_hdr_len) | ||
60 | { | ||
61 | int ret = 0; | ||
62 | uint32_t len = htonl(size); | ||
63 | @@ -XXX,XX +XXX,XX @@ static int compare_chr_send(CompareState *s, | ||
64 | goto err; | ||
65 | } | ||
66 | |||
67 | + if (s->vnet_hdr) { | ||
68 | + /* | ||
69 | + * We send vnet header len make other module(like filter-redirector) | ||
70 | + * know how to parse net packet correctly. | ||
71 | + */ | ||
72 | + len = htonl(vnet_hdr_len); | ||
73 | + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); | ||
74 | + if (ret != sizeof(len)) { | ||
75 | + goto err; | ||
76 | + } | ||
77 | + } | ||
78 | + | ||
79 | ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size); | ||
80 | if (ret != size) { | ||
81 | goto err; | ||
82 | @@ -XXX,XX +XXX,XX @@ static void compare_set_outdev(Object *obj, const char *value, Error **errp) | ||
83 | s->outdev = g_strdup(value); | ||
84 | } | 58 | } |
85 | 59 | ||
86 | +static bool compare_get_vnet_hdr(Object *obj, Error **errp) | 60 | +static void compare_get_timeout(Object *obj, Visitor *v, |
61 | + const char *name, void *opaque, | ||
62 | + Error **errp) | ||
87 | +{ | 63 | +{ |
88 | + CompareState *s = COLO_COMPARE(obj); | 64 | + CompareState *s = COLO_COMPARE(obj); |
65 | + uint32_t value = s->compare_timeout; | ||
89 | + | 66 | + |
90 | + return s->vnet_hdr; | 67 | + visit_type_uint32(v, name, &value, errp); |
91 | +} | 68 | +} |
92 | + | 69 | + |
93 | +static void compare_set_vnet_hdr(Object *obj, | 70 | +static void compare_set_timeout(Object *obj, Visitor *v, |
94 | + bool value, | 71 | + const char *name, void *opaque, |
95 | + Error **errp) | 72 | + Error **errp) |
96 | +{ | 73 | +{ |
97 | + CompareState *s = COLO_COMPARE(obj); | 74 | + CompareState *s = COLO_COMPARE(obj); |
75 | + Error *local_err = NULL; | ||
76 | + uint32_t value; | ||
98 | + | 77 | + |
99 | + s->vnet_hdr = value; | 78 | + visit_type_uint32(v, name, &value, &local_err); |
79 | + if (local_err) { | ||
80 | + goto out; | ||
81 | + } | ||
82 | + if (!value) { | ||
83 | + error_setg(&local_err, "Property '%s.%s' requires a positive value", | ||
84 | + object_get_typename(obj), name); | ||
85 | + goto out; | ||
86 | + } | ||
87 | + s->compare_timeout = value; | ||
88 | + | ||
89 | +out: | ||
90 | + error_propagate(errp, local_err); | ||
100 | +} | 91 | +} |
101 | + | 92 | + |
102 | static void compare_pri_rs_finalize(SocketReadState *pri_rs) | 93 | static void compare_pri_rs_finalize(SocketReadState *pri_rs) |
103 | { | 94 | { |
104 | CompareState *s = container_of(pri_rs, CompareState, pri_rs); | 95 | CompareState *s = container_of(pri_rs, CompareState, pri_rs); |
105 | |||
106 | if (packet_enqueue(s, PRIMARY_IN)) { | ||
107 | trace_colo_compare_main("primary: unsupported packet in"); | ||
108 | - compare_chr_send(s, pri_rs->buf, pri_rs->packet_len); | ||
109 | + compare_chr_send(s, | ||
110 | + pri_rs->buf, | ||
111 | + pri_rs->packet_len, | ||
112 | + pri_rs->vnet_hdr_len); | ||
113 | } else { | ||
114 | /* compare connection */ | ||
115 | g_queue_foreach(&s->conn_list, colo_compare_connection, s); | ||
116 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) | 96 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) |
117 | return; | 97 | return; |
118 | } | 98 | } |
119 | 99 | ||
120 | - net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, false); | 100 | + if (!s->compare_timeout) { |
121 | - net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, false); | 101 | + /* Set default value to 3000 MS */ |
122 | + net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr); | 102 | + s->compare_timeout = DEFAULT_TIME_OUT_MS; |
123 | + net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr); | 103 | + } |
124 | |||
125 | g_queue_init(&s->conn_list); | ||
126 | |||
127 | @@ -XXX,XX +XXX,XX @@ static void colo_flush_packets(void *opaque, void *user_data) | ||
128 | |||
129 | while (!g_queue_is_empty(&conn->primary_list)) { | ||
130 | pkt = g_queue_pop_head(&conn->primary_list); | ||
131 | - compare_chr_send(s, pkt->data, pkt->size); | ||
132 | + compare_chr_send(s, | ||
133 | + pkt->data, | ||
134 | + pkt->size, | ||
135 | + pkt->vnet_hdr_len); | ||
136 | packet_destroy(pkt, NULL); | ||
137 | } | ||
138 | while (!g_queue_is_empty(&conn->secondary_list)) { | ||
139 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_class_init(ObjectClass *oc, void *data) | ||
140 | |||
141 | static void colo_compare_init(Object *obj) | ||
142 | { | ||
143 | + CompareState *s = COLO_COMPARE(obj); | ||
144 | + | 104 | + |
145 | object_property_add_str(obj, "primary_in", | 105 | if (find_and_check_chardev(&chr, s->pri_indev, errp) || |
146 | compare_get_pri_indev, compare_set_pri_indev, | 106 | !qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) { |
107 | return; | ||
108 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj) | ||
109 | compare_get_notify_dev, compare_set_notify_dev, | ||
147 | NULL); | 110 | NULL); |
148 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj) | 111 | |
149 | object_property_add_str(obj, "outdev", | 112 | + object_property_add(obj, "compare_timeout", "uint32", |
150 | compare_get_outdev, compare_set_outdev, | 113 | + compare_get_timeout, |
151 | NULL); | 114 | + compare_set_timeout, NULL, NULL, NULL); |
152 | + | 115 | + |
153 | + s->vnet_hdr = false; | 116 | s->vnet_hdr = false; |
154 | + object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr, | 117 | object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr, |
155 | + compare_set_vnet_hdr, NULL); | 118 | compare_set_vnet_hdr, NULL); |
156 | } | ||
157 | |||
158 | static void colo_compare_finalize(Object *obj) | ||
159 | diff --git a/qemu-options.hx b/qemu-options.hx | 119 | diff --git a/qemu-options.hx b/qemu-options.hx |
160 | index XXXXXXX..XXXXXXX 100644 | 120 | index XXXXXXX..XXXXXXX 100644 |
161 | --- a/qemu-options.hx | 121 | --- a/qemu-options.hx |
162 | +++ b/qemu-options.hx | 122 | +++ b/qemu-options.hx |
163 | @@ -XXX,XX +XXX,XX @@ Dump the network traffic on netdev @var{dev} to the file specified by | 123 | @@ -XXX,XX +XXX,XX @@ SRST |
164 | The file format is libpcap, so it can be analyzed with tools such as tcpdump | 124 | stored. The file format is libpcap, so it can be analyzed with |
165 | or Wireshark. | 125 | tools such as tcpdump or Wireshark. |
166 | 126 | ||
167 | -@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid}, | 127 | - ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id]`` |
168 | -outdev=@var{chardevid} | 128 | + ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}]`` |
169 | +@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid}[,vnet_hdr_support] | 129 | Colo-compare gets packet from primary\_inchardevid and |
170 | 130 | secondary\_inchardevid, than compare primary packet with | |
171 | Colo-compare gets packet from primary_in@var{chardevid} and secondary_in@var{chardevid}, than compare primary packet with | 131 | secondary packet. If the packets are same, we will output |
172 | secondary packet. If the packets are same, we will output primary | 132 | @@ -XXX,XX +XXX,XX @@ SRST |
173 | packet to outdev@var{chardevid}, else we will notify colo-frame | 133 | outdevchardevid. In order to improve efficiency, we need to put |
174 | do checkpoint and send primary packet to outdev@var{chardevid}. | 134 | the task of comparison in another thread. If it has the |
175 | +if it has the vnet_hdr_support flag, colo compare will send/recv packet with vnet_hdr_len. | 135 | vnet\_hdr\_support flag, colo compare will send/recv packet with |
176 | 136 | - vnet\_hdr\_len. If you want to use Xen COLO, will need the | |
177 | we must use it with the help of filter-mirror and filter-redirector. | 137 | - notify\_dev to notify Xen colo-frame to do checkpoint. |
178 | 138 | + vnet\_hdr\_len. Then compare\_timeout=@var{ms} determines the | |
139 | + maximum delay colo-compare wait for the packet. | ||
140 | + If you want to use Xen COLO, will need the notify\_dev to | ||
141 | + notify Xen colo-frame to do checkpoint. | ||
142 | |||
143 | we must use it with the help of filter-mirror and | ||
144 | filter-redirector. | ||
179 | -- | 145 | -- |
180 | 2.7.4 | 146 | 2.5.0 |
181 | 147 | ||
182 | 148 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Zhang Chen <chen.zhang@intel.com> |
---|---|---|---|
2 | 2 | ||
3 | We add the vnet_hdr_support option for filter-redirector, default is disabled. | 3 | The "expired_scan_cycle" determines period of scanning expired |
4 | If you use virtio-net-pci net driver or other driver needs vnet_hdr, please enable it. | 4 | primary node net packets. |
5 | Because colo-compare or other modules needs the vnet_hdr_len to parse | ||
6 | packet, we add this new option send the len to others. | ||
7 | You can use it for example: | ||
8 | -object filter-redirector,id=r0,netdev=hn0,queue=tx,outdev=red0,vnet_hdr_support | ||
9 | 5 | ||
10 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 6 | Signed-off-by: Zhang Chen <chen.zhang@intel.com> |
11 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 7 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
12 | --- | 8 | --- |
13 | net/filter-mirror.c | 23 +++++++++++++++++++++++ | 9 | net/colo-compare.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- |
14 | qemu-options.hx | 6 +++--- | 10 | qemu-options.hx | 4 +++- |
15 | 2 files changed, 26 insertions(+), 3 deletions(-) | 11 | 2 files changed, 48 insertions(+), 4 deletions(-) |
16 | 12 | ||
17 | diff --git a/net/filter-mirror.c b/net/filter-mirror.c | 13 | diff --git a/net/colo-compare.c b/net/colo-compare.c |
18 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/net/filter-mirror.c | 15 | --- a/net/colo-compare.c |
20 | +++ b/net/filter-mirror.c | 16 | +++ b/net/colo-compare.c |
21 | @@ -XXX,XX +XXX,XX @@ static void filter_redirector_set_outdev(Object *obj, | 17 | @@ -XXX,XX +XXX,XX @@ static NotifierList colo_compare_notifiers = |
22 | s->outdev = g_strdup(value); | 18 | #define COLO_COMPARE_FREE_PRIMARY 0x01 |
19 | #define COLO_COMPARE_FREE_SECONDARY 0x02 | ||
20 | |||
21 | -/* TODO: Should be configurable */ | ||
22 | #define REGULAR_PACKET_CHECK_MS 3000 | ||
23 | #define DEFAULT_TIME_OUT_MS 3000 | ||
24 | |||
25 | @@ -XXX,XX +XXX,XX @@ typedef struct CompareState { | ||
26 | SocketReadState notify_rs; | ||
27 | bool vnet_hdr; | ||
28 | uint32_t compare_timeout; | ||
29 | + uint32_t expired_scan_cycle; | ||
30 | |||
31 | /* | ||
32 | * Record the connection that through the NIC | ||
33 | @@ -XXX,XX +XXX,XX @@ static void check_old_packet_regular(void *opaque) | ||
34 | /* if have old packet we will notify checkpoint */ | ||
35 | colo_old_packet_check(s); | ||
36 | timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + | ||
37 | - REGULAR_PACKET_CHECK_MS); | ||
38 | + s->expired_scan_cycle); | ||
23 | } | 39 | } |
24 | 40 | ||
25 | +static bool filter_redirector_get_vnet_hdr(Object *obj, Error **errp) | 41 | /* Public API, Used for COLO frame to notify compare event */ |
42 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_timer_init(CompareState *s) | ||
43 | SCALE_MS, check_old_packet_regular, | ||
44 | s); | ||
45 | timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + | ||
46 | - REGULAR_PACKET_CHECK_MS); | ||
47 | + s->expired_scan_cycle); | ||
48 | } | ||
49 | |||
50 | static void colo_compare_timer_del(CompareState *s) | ||
51 | @@ -XXX,XX +XXX,XX @@ out: | ||
52 | error_propagate(errp, local_err); | ||
53 | } | ||
54 | |||
55 | +static void compare_get_expired_scan_cycle(Object *obj, Visitor *v, | ||
56 | + const char *name, void *opaque, | ||
57 | + Error **errp) | ||
26 | +{ | 58 | +{ |
27 | + MirrorState *s = FILTER_REDIRECTOR(obj); | 59 | + CompareState *s = COLO_COMPARE(obj); |
60 | + uint32_t value = s->expired_scan_cycle; | ||
28 | + | 61 | + |
29 | + return s->vnet_hdr; | 62 | + visit_type_uint32(v, name, &value, errp); |
30 | +} | 63 | +} |
31 | + | 64 | + |
32 | +static void filter_redirector_set_vnet_hdr(Object *obj, | 65 | +static void compare_set_expired_scan_cycle(Object *obj, Visitor *v, |
33 | + bool value, | 66 | + const char *name, void *opaque, |
34 | + Error **errp) | 67 | + Error **errp) |
35 | +{ | 68 | +{ |
36 | + MirrorState *s = FILTER_REDIRECTOR(obj); | 69 | + CompareState *s = COLO_COMPARE(obj); |
70 | + Error *local_err = NULL; | ||
71 | + uint32_t value; | ||
37 | + | 72 | + |
38 | + s->vnet_hdr = value; | 73 | + visit_type_uint32(v, name, &value, &local_err); |
74 | + if (local_err) { | ||
75 | + goto out; | ||
76 | + } | ||
77 | + if (!value) { | ||
78 | + error_setg(&local_err, "Property '%s.%s' requires a positive value", | ||
79 | + object_get_typename(obj), name); | ||
80 | + goto out; | ||
81 | + } | ||
82 | + s->expired_scan_cycle = value; | ||
83 | + | ||
84 | +out: | ||
85 | + error_propagate(errp, local_err); | ||
39 | +} | 86 | +} |
40 | + | 87 | + |
41 | static void filter_mirror_init(Object *obj) | 88 | static void compare_pri_rs_finalize(SocketReadState *pri_rs) |
42 | { | 89 | { |
43 | MirrorState *s = FILTER_MIRROR(obj); | 90 | CompareState *s = container_of(pri_rs, CompareState, pri_rs); |
44 | @@ -XXX,XX +XXX,XX @@ static void filter_mirror_init(Object *obj) | 91 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) |
45 | 92 | s->compare_timeout = DEFAULT_TIME_OUT_MS; | |
46 | static void filter_redirector_init(Object *obj) | 93 | } |
47 | { | 94 | |
48 | + MirrorState *s = FILTER_REDIRECTOR(obj); | 95 | + if (!s->expired_scan_cycle) { |
96 | + /* Set default value to 3000 MS */ | ||
97 | + s->expired_scan_cycle = REGULAR_PACKET_CHECK_MS; | ||
98 | + } | ||
49 | + | 99 | + |
50 | object_property_add_str(obj, "indev", filter_redirector_get_indev, | 100 | if (find_and_check_chardev(&chr, s->pri_indev, errp) || |
51 | filter_redirector_set_indev, NULL); | 101 | !qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) { |
52 | object_property_add_str(obj, "outdev", filter_redirector_get_outdev, | 102 | return; |
53 | filter_redirector_set_outdev, NULL); | 103 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_init(Object *obj) |
104 | compare_get_timeout, | ||
105 | compare_set_timeout, NULL, NULL, NULL); | ||
106 | |||
107 | + object_property_add(obj, "expired_scan_cycle", "uint32", | ||
108 | + compare_get_expired_scan_cycle, | ||
109 | + compare_set_expired_scan_cycle, NULL, NULL, NULL); | ||
54 | + | 110 | + |
55 | + s->vnet_hdr = false; | 111 | s->vnet_hdr = false; |
56 | + object_property_add_bool(obj, "vnet_hdr_support", | 112 | object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr, |
57 | + filter_redirector_get_vnet_hdr, | 113 | compare_set_vnet_hdr, NULL); |
58 | + filter_redirector_set_vnet_hdr, NULL); | ||
59 | } | ||
60 | |||
61 | static void filter_mirror_fini(Object *obj) | ||
62 | diff --git a/qemu-options.hx b/qemu-options.hx | 114 | diff --git a/qemu-options.hx b/qemu-options.hx |
63 | index XXXXXXX..XXXXXXX 100644 | 115 | index XXXXXXX..XXXXXXX 100644 |
64 | --- a/qemu-options.hx | 116 | --- a/qemu-options.hx |
65 | +++ b/qemu-options.hx | 117 | +++ b/qemu-options.hx |
66 | @@ -XXX,XX +XXX,XX @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter. | 118 | @@ -XXX,XX +XXX,XX @@ SRST |
67 | 119 | stored. The file format is libpcap, so it can be analyzed with | |
68 | filter-mirror on netdev @var{netdevid},mirror net packet to chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror will mirror packet with vnet_hdr_len. | 120 | tools such as tcpdump or Wireshark. |
69 | 121 | ||
70 | -@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid}, | 122 | - ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}]`` |
71 | -outdev=@var{chardevid}[,queue=@var{all|rx|tx}] | 123 | + ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}][,expired_scan_cycle=@var{ms}`` |
72 | +@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support] | 124 | Colo-compare gets packet from primary\_inchardevid and |
73 | 125 | secondary\_inchardevid, than compare primary packet with | |
74 | filter-redirector on netdev @var{netdevid},redirect filter's net packet to chardev | 126 | secondary packet. If the packets are same, we will output |
75 | -@var{chardevid},and redirect indev's packet to filter. | 127 | @@ -XXX,XX +XXX,XX @@ SRST |
76 | +@var{chardevid},and redirect indev's packet to filter.if it has the vnet_hdr_support flag, | 128 | vnet\_hdr\_support flag, colo compare will send/recv packet with |
77 | +filter-redirector will redirect packet with vnet_hdr_len. | 129 | vnet\_hdr\_len. Then compare\_timeout=@var{ms} determines the |
78 | Create a filter-redirector we need to differ outdev id from indev id, id can not | 130 | maximum delay colo-compare wait for the packet. |
79 | be the same. we can just use indev or outdev, but at least one of indev or outdev | 131 | + The expired\_scan\_cycle=@var{ms} to set the period of scanning |
80 | need to be specified. | 132 | + expired primary node network packets. |
133 | If you want to use Xen COLO, will need the notify\_dev to | ||
134 | notify Xen colo-frame to do checkpoint. | ||
135 | |||
81 | -- | 136 | -- |
82 | 2.7.4 | 137 | 2.5.0 |
83 | 138 | ||
84 | 139 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Prasad J Pandit <pjp@fedoraproject.org> |
---|---|---|---|
2 | 2 | ||
3 | We add a flag to decide whether net_fill_rstate() need read | 3 | Tulip network driver while copying tx/rx buffers does not check |
4 | the vnet_hdr_len or not. | 4 | frame size against r/w data length. This may lead to OOB buffer |
5 | access. Add check to avoid it. | ||
5 | 6 | ||
6 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 7 | Limit iterations over descriptors to avoid potential infinite |
7 | Suggested-by: Jason Wang <jasowang@redhat.com> | 8 | loop issue in tulip_xmit_list_update. |
9 | |||
10 | Reported-by: Li Qiang <pangpei.lq@antfin.com> | ||
11 | Reported-by: Ziming Zhang <ezrakiez@gmail.com> | ||
12 | Reported-by: Jason Wang <jasowang@redhat.com> | ||
13 | Tested-by: Li Qiang <liq3ea@gmail.com> | ||
14 | Reviewed-by: Li Qiang <liq3ea@gmail.com> | ||
15 | Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> | ||
8 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 16 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
9 | --- | 17 | --- |
10 | include/net/net.h | 9 +++++++-- | 18 | hw/net/tulip.c | 36 +++++++++++++++++++++++++++--------- |
11 | net/colo-compare.c | 4 ++-- | 19 | 1 file changed, 27 insertions(+), 9 deletions(-) |
12 | net/filter-mirror.c | 2 +- | ||
13 | net/net.c | 36 ++++++++++++++++++++++++++++++++---- | ||
14 | net/socket.c | 8 ++++---- | ||
15 | 5 files changed, 46 insertions(+), 13 deletions(-) | ||
16 | 20 | ||
17 | diff --git a/include/net/net.h b/include/net/net.h | 21 | diff --git a/hw/net/tulip.c b/hw/net/tulip.c |
18 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/include/net/net.h | 23 | --- a/hw/net/tulip.c |
20 | +++ b/include/net/net.h | 24 | +++ b/hw/net/tulip.c |
21 | @@ -XXX,XX +XXX,XX @@ typedef struct NICState { | 25 | @@ -XXX,XX +XXX,XX @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) |
22 | } NICState; | 26 | } else { |
23 | 27 | len = s->rx_frame_len; | |
24 | struct SocketReadState { | 28 | } |
25 | - int state; /* 0 = getting length, 1 = getting data */ | 29 | + |
26 | + /* 0 = getting length, 1 = getting vnet header length, 2 = getting data */ | 30 | + if (s->rx_frame_len + len > sizeof(s->rx_frame)) { |
27 | + int state; | 31 | + return; |
28 | + /* This flag decide whether to read the vnet_hdr_len field */ | 32 | + } |
29 | + bool vnet_hdr; | 33 | pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame + |
30 | uint32_t index; | 34 | (s->rx_frame_size - s->rx_frame_len), len); |
31 | uint32_t packet_len; | 35 | s->rx_frame_len -= len; |
32 | + uint32_t vnet_hdr_len; | 36 | @@ -XXX,XX +XXX,XX @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) |
33 | uint8_t buf[NET_BUFSIZE]; | 37 | } else { |
34 | SocketReadStateFinalize *finalize; | 38 | len = s->rx_frame_len; |
35 | }; | 39 | } |
36 | @@ -XXX,XX +XXX,XX @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender, | 40 | + |
37 | void print_net_client(Monitor *mon, NetClientState *nc); | 41 | + if (s->rx_frame_len + len > sizeof(s->rx_frame)) { |
38 | void hmp_info_network(Monitor *mon, const QDict *qdict); | 42 | + return; |
39 | void net_socket_rs_init(SocketReadState *rs, | 43 | + } |
40 | - SocketReadStateFinalize *finalize); | 44 | pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame + |
41 | + SocketReadStateFinalize *finalize, | 45 | (s->rx_frame_size - s->rx_frame_len), len); |
42 | + bool vnet_hdr); | 46 | s->rx_frame_len -= len; |
43 | 47 | @@ -XXX,XX +XXX,XX @@ static ssize_t tulip_receive(TULIPState *s, const uint8_t *buf, size_t size) | |
44 | /* NIC info */ | 48 | |
45 | 49 | trace_tulip_receive(buf, size); | |
46 | diff --git a/net/colo-compare.c b/net/colo-compare.c | 50 | |
47 | index XXXXXXX..XXXXXXX 100644 | 51 | - if (size < 14 || size > 2048 || s->rx_frame_len || tulip_rx_stopped(s)) { |
48 | --- a/net/colo-compare.c | 52 | + if (size < 14 || size > sizeof(s->rx_frame) - 4 |
49 | +++ b/net/colo-compare.c | 53 | + || s->rx_frame_len || tulip_rx_stopped(s)) { |
50 | @@ -XXX,XX +XXX,XX @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) | 54 | return 0; |
55 | } | ||
56 | |||
57 | @@ -XXX,XX +XXX,XX @@ static ssize_t tulip_receive_nc(NetClientState *nc, | ||
58 | return tulip_receive(qemu_get_nic_opaque(nc), buf, size); | ||
59 | } | ||
60 | |||
61 | - | ||
62 | static NetClientInfo net_tulip_info = { | ||
63 | .type = NET_CLIENT_DRIVER_NIC, | ||
64 | .size = sizeof(NICState), | ||
65 | @@ -XXX,XX +XXX,XX @@ static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc) | ||
66 | if ((s->csr[6] >> CSR6_OM_SHIFT) & CSR6_OM_MASK) { | ||
67 | /* Internal or external Loopback */ | ||
68 | tulip_receive(s, s->tx_frame, s->tx_frame_len); | ||
69 | - } else { | ||
70 | + } else if (s->tx_frame_len <= sizeof(s->tx_frame)) { | ||
71 | qemu_send_packet(qemu_get_queue(s->nic), | ||
72 | s->tx_frame, s->tx_frame_len); | ||
73 | } | ||
74 | @@ -XXX,XX +XXX,XX @@ static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc) | ||
75 | } | ||
76 | } | ||
77 | |||
78 | -static void tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) | ||
79 | +static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) | ||
80 | { | ||
81 | int len1 = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; | ||
82 | int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK; | ||
83 | |||
84 | + if (s->tx_frame_len + len1 > sizeof(s->tx_frame)) { | ||
85 | + return -1; | ||
86 | + } | ||
87 | if (len1) { | ||
88 | pci_dma_read(&s->dev, desc->buf_addr1, | ||
89 | s->tx_frame + s->tx_frame_len, len1); | ||
90 | s->tx_frame_len += len1; | ||
91 | } | ||
92 | |||
93 | + if (s->tx_frame_len + len2 > sizeof(s->tx_frame)) { | ||
94 | + return -1; | ||
95 | + } | ||
96 | if (len2) { | ||
97 | pci_dma_read(&s->dev, desc->buf_addr2, | ||
98 | s->tx_frame + s->tx_frame_len, len2); | ||
99 | s->tx_frame_len += len2; | ||
100 | } | ||
101 | desc->status = (len1 + len2) ? 0 : 0x7fffffff; | ||
102 | + | ||
103 | + return 0; | ||
104 | } | ||
105 | |||
106 | static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n) | ||
107 | @@ -XXX,XX +XXX,XX @@ static uint32_t tulip_ts(TULIPState *s) | ||
108 | |||
109 | static void tulip_xmit_list_update(TULIPState *s) | ||
110 | { | ||
111 | +#define TULIP_DESC_MAX 128 | ||
112 | + uint8_t i = 0; | ||
113 | struct tulip_descriptor desc; | ||
114 | |||
115 | if (tulip_ts(s) != CSR5_TS_SUSPENDED) { | ||
51 | return; | 116 | return; |
52 | } | 117 | } |
53 | 118 | ||
54 | - net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize); | 119 | - for (;;) { |
55 | - net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize); | 120 | + for (i = 0; i < TULIP_DESC_MAX; i++) { |
56 | + net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, false); | 121 | tulip_desc_read(s, s->current_tx_desc, &desc); |
57 | + net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, false); | 122 | tulip_dump_tx_descriptor(s, &desc); |
58 | 123 | ||
59 | g_queue_init(&s->conn_list); | 124 | @@ -XXX,XX +XXX,XX @@ static void tulip_xmit_list_update(TULIPState *s) |
60 | 125 | s->tx_frame_len = 0; | |
61 | diff --git a/net/filter-mirror.c b/net/filter-mirror.c | 126 | } |
62 | index XXXXXXX..XXXXXXX 100644 | 127 | |
63 | --- a/net/filter-mirror.c | 128 | - tulip_copy_tx_buffers(s, &desc); |
64 | +++ b/net/filter-mirror.c | 129 | - |
65 | @@ -XXX,XX +XXX,XX @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp) | 130 | - if (desc.control & TDES1_LS) { |
66 | } | 131 | - tulip_tx(s, &desc); |
67 | } | 132 | + if (!tulip_copy_tx_buffers(s, &desc)) { |
68 | 133 | + if (desc.control & TDES1_LS) { | |
69 | - net_socket_rs_init(&s->rs, redirector_rs_finalize); | 134 | + tulip_tx(s, &desc); |
70 | + net_socket_rs_init(&s->rs, redirector_rs_finalize, false); | ||
71 | |||
72 | if (s->indev) { | ||
73 | chr = qemu_chr_find(s->indev); | ||
74 | diff --git a/net/net.c b/net/net.c | ||
75 | index XXXXXXX..XXXXXXX 100644 | ||
76 | --- a/net/net.c | ||
77 | +++ b/net/net.c | ||
78 | @@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_net_opts = { | ||
79 | }; | ||
80 | |||
81 | void net_socket_rs_init(SocketReadState *rs, | ||
82 | - SocketReadStateFinalize *finalize) | ||
83 | + SocketReadStateFinalize *finalize, | ||
84 | + bool vnet_hdr) | ||
85 | { | ||
86 | rs->state = 0; | ||
87 | + rs->vnet_hdr = vnet_hdr; | ||
88 | rs->index = 0; | ||
89 | rs->packet_len = 0; | ||
90 | + rs->vnet_hdr_len = 0; | ||
91 | memset(rs->buf, 0, sizeof(rs->buf)); | ||
92 | rs->finalize = finalize; | ||
93 | } | ||
94 | @@ -XXX,XX +XXX,XX @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size) | ||
95 | unsigned int l; | ||
96 | |||
97 | while (size > 0) { | ||
98 | - /* reassemble a packet from the network */ | ||
99 | - switch (rs->state) { /* 0 = getting length, 1 = getting data */ | ||
100 | + /* Reassemble a packet from the network. | ||
101 | + * 0 = getting length. | ||
102 | + * 1 = getting vnet header length. | ||
103 | + * 2 = getting data. | ||
104 | + */ | ||
105 | + switch (rs->state) { | ||
106 | case 0: | ||
107 | l = 4 - rs->index; | ||
108 | if (l > size) { | ||
109 | @@ -XXX,XX +XXX,XX @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size) | ||
110 | /* got length */ | ||
111 | rs->packet_len = ntohl(*(uint32_t *)rs->buf); | ||
112 | rs->index = 0; | ||
113 | - rs->state = 1; | ||
114 | + if (rs->vnet_hdr) { | ||
115 | + rs->state = 1; | ||
116 | + } else { | ||
117 | + rs->state = 2; | ||
118 | + rs->vnet_hdr_len = 0; | ||
119 | + } | 135 | + } |
120 | } | 136 | } |
121 | break; | 137 | } |
122 | case 1: | 138 | tulip_desc_write(s, s->current_tx_desc, &desc); |
123 | + l = 4 - rs->index; | ||
124 | + if (l > size) { | ||
125 | + l = size; | ||
126 | + } | ||
127 | + memcpy(rs->buf + rs->index, buf, l); | ||
128 | + buf += l; | ||
129 | + size -= l; | ||
130 | + rs->index += l; | ||
131 | + if (rs->index == 4) { | ||
132 | + /* got vnet header length */ | ||
133 | + rs->vnet_hdr_len = ntohl(*(uint32_t *)rs->buf); | ||
134 | + rs->index = 0; | ||
135 | + rs->state = 2; | ||
136 | + } | ||
137 | + break; | ||
138 | + case 2: | ||
139 | l = rs->packet_len - rs->index; | ||
140 | if (l > size) { | ||
141 | l = size; | ||
142 | diff --git a/net/socket.c b/net/socket.c | ||
143 | index XXXXXXX..XXXXXXX 100644 | ||
144 | --- a/net/socket.c | ||
145 | +++ b/net/socket.c | ||
146 | @@ -XXX,XX +XXX,XX @@ static void net_socket_send(void *opaque) | ||
147 | closesocket(s->fd); | ||
148 | |||
149 | s->fd = -1; | ||
150 | - net_socket_rs_init(&s->rs, net_socket_rs_finalize); | ||
151 | + net_socket_rs_init(&s->rs, net_socket_rs_finalize, false); | ||
152 | s->nc.link_down = true; | ||
153 | memset(s->nc.info_str, 0, sizeof(s->nc.info_str)); | ||
154 | |||
155 | @@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, | ||
156 | s->fd = fd; | ||
157 | s->listen_fd = -1; | ||
158 | s->send_fn = net_socket_send_dgram; | ||
159 | - net_socket_rs_init(&s->rs, net_socket_rs_finalize); | ||
160 | + net_socket_rs_init(&s->rs, net_socket_rs_finalize, false); | ||
161 | net_socket_read_poll(s, true); | ||
162 | |||
163 | /* mcast: save bound address as dst */ | ||
164 | @@ -XXX,XX +XXX,XX @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, | ||
165 | |||
166 | s->fd = fd; | ||
167 | s->listen_fd = -1; | ||
168 | - net_socket_rs_init(&s->rs, net_socket_rs_finalize); | ||
169 | + net_socket_rs_init(&s->rs, net_socket_rs_finalize, false); | ||
170 | |||
171 | /* Disable Nagle algorithm on TCP sockets to reduce latency */ | ||
172 | socket_set_nodelay(fd); | ||
173 | @@ -XXX,XX +XXX,XX @@ static int net_socket_listen_init(NetClientState *peer, | ||
174 | s->fd = -1; | ||
175 | s->listen_fd = fd; | ||
176 | s->nc.link_down = true; | ||
177 | - net_socket_rs_init(&s->rs, net_socket_rs_finalize); | ||
178 | + net_socket_rs_init(&s->rs, net_socket_rs_finalize, false); | ||
179 | |||
180 | qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); | ||
181 | return 0; | ||
182 | -- | 139 | -- |
183 | 2.7.4 | 140 | 2.5.0 |
184 | 141 | ||
185 | 142 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Peter Maydell <peter.maydell@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | This patch change the filter_send() parameter from CharBackend to MirrorState, | 3 | Coverity points out (CID 1421926) that the read code for |
4 | we can get more information like vnet_hdr(We use it to support packet with vnet_header). | 4 | REG_ADDR_HIGH reads off the end of the buffer, because it does a |
5 | 32-bit read from byte 4 of a 6-byte buffer. | ||
5 | 6 | ||
6 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 7 | The code also has an endianness issue for both REG_ADDR_HIGH and |
8 | REG_ADDR_LOW, because it will do the wrong thing on a big-endian | ||
9 | host. | ||
10 | |||
11 | Rewrite the read code to use ldl_le_p() and lduw_le_p() to fix this; | ||
12 | the write code is not incorrect, but for consistency we make it use | ||
13 | stl_le_p() and stw_le_p(). | ||
14 | |||
15 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
16 | Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com> | ||
17 | Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com> | ||
18 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 19 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
8 | --- | 20 | --- |
9 | net/filter-mirror.c | 10 +++++----- | 21 | hw/net/allwinner-sun8i-emac.c | 12 ++++-------- |
10 | 1 file changed, 5 insertions(+), 5 deletions(-) | 22 | 1 file changed, 4 insertions(+), 8 deletions(-) |
11 | 23 | ||
12 | diff --git a/net/filter-mirror.c b/net/filter-mirror.c | 24 | diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c |
13 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/net/filter-mirror.c | 26 | --- a/hw/net/allwinner-sun8i-emac.c |
15 | +++ b/net/filter-mirror.c | 27 | +++ b/hw/net/allwinner-sun8i-emac.c |
16 | @@ -XXX,XX +XXX,XX @@ typedef struct MirrorState { | 28 | @@ -XXX,XX +XXX,XX @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset, |
17 | SocketReadState rs; | 29 | value = s->mii_data; |
18 | } MirrorState; | 30 | break; |
19 | 31 | case REG_ADDR_HIGH: /* MAC Address High */ | |
20 | -static int filter_send(CharBackend *chr_out, | 32 | - value = *(((uint32_t *) (s->conf.macaddr.a)) + 1); |
21 | +static int filter_send(MirrorState *s, | 33 | + value = lduw_le_p(s->conf.macaddr.a + 4); |
22 | const struct iovec *iov, | 34 | break; |
23 | int iovcnt) | 35 | case REG_ADDR_LOW: /* MAC Address Low */ |
24 | { | 36 | - value = *(uint32_t *) (s->conf.macaddr.a); |
25 | @@ -XXX,XX +XXX,XX @@ static int filter_send(CharBackend *chr_out, | 37 | + value = ldl_le_p(s->conf.macaddr.a); |
26 | } | 38 | break; |
27 | 39 | case REG_TX_DMA_STA: /* Transmit DMA Status */ | |
28 | len = htonl(size); | 40 | break; |
29 | - ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)&len, sizeof(len)); | 41 | @@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_write(void *opaque, hwaddr offset, |
30 | + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); | 42 | s->mii_data = value; |
31 | if (ret != sizeof(len)) { | 43 | break; |
32 | goto err; | 44 | case REG_ADDR_HIGH: /* MAC Address High */ |
33 | } | 45 | - s->conf.macaddr.a[4] = (value & 0xff); |
34 | 46 | - s->conf.macaddr.a[5] = (value & 0xff00) >> 8; | |
35 | buf = g_malloc(size); | 47 | + stw_le_p(s->conf.macaddr.a + 4, value); |
36 | iov_to_buf(iov, iovcnt, 0, buf, size); | 48 | break; |
37 | - ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)buf, size); | 49 | case REG_ADDR_LOW: /* MAC Address Low */ |
38 | + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size); | 50 | - s->conf.macaddr.a[0] = (value & 0xff); |
39 | g_free(buf); | 51 | - s->conf.macaddr.a[1] = (value & 0xff00) >> 8; |
40 | if (ret != size) { | 52 | - s->conf.macaddr.a[2] = (value & 0xff0000) >> 16; |
41 | goto err; | 53 | - s->conf.macaddr.a[3] = (value & 0xff000000) >> 24; |
42 | @@ -XXX,XX +XXX,XX @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf, | 54 | + stl_le_p(s->conf.macaddr.a, value); |
43 | MirrorState *s = FILTER_MIRROR(nf); | 55 | break; |
44 | int ret; | 56 | case REG_TX_DMA_STA: /* Transmit DMA Status */ |
45 | 57 | case REG_TX_CUR_DESC: /* Transmit Current Descriptor */ | |
46 | - ret = filter_send(&s->chr_out, iov, iovcnt); | ||
47 | + ret = filter_send(s, iov, iovcnt); | ||
48 | if (ret) { | ||
49 | error_report("filter mirror send failed(%s)", strerror(-ret)); | ||
50 | } | ||
51 | @@ -XXX,XX +XXX,XX @@ static ssize_t filter_redirector_receive_iov(NetFilterState *nf, | ||
52 | int ret; | ||
53 | |||
54 | if (qemu_chr_fe_backend_connected(&s->chr_out)) { | ||
55 | - ret = filter_send(&s->chr_out, iov, iovcnt); | ||
56 | + ret = filter_send(s, iov, iovcnt); | ||
57 | if (ret) { | ||
58 | error_report("filter redirector send failed(%s)", strerror(-ret)); | ||
59 | } | ||
60 | -- | 58 | -- |
61 | 2.7.4 | 59 | 2.5.0 |
62 | 60 | ||
63 | 61 | diff view generated by jsdifflib |
1 | From: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 1 | From: Li Qiang <liq3ea@163.com> |
---|---|---|---|
2 | 2 | ||
3 | We add the vnet_hdr_support option for filter-rewriter, default is disabled. | 3 | The tulip networking card emulation has an OOB issue in |
4 | If you use virtio-net-pci or other driver needs vnet_hdr, please enable it. | 4 | 'tulip_copy_tx_buffers' when the guest provide malformed descriptor. |
5 | You can use it for example: | 5 | This test will trigger a ASAN heap overflow crash. To trigger this |
6 | -object filter-rewriter,id=rew0,netdev=hn0,queue=all,vnet_hdr_support | 6 | issue we can construct the data as following: |
7 | 7 | ||
8 | We get the vnet_hdr_len from NetClientState that make us | 8 | 1. construct a 'tulip_descriptor'. Its control is set to |
9 | parse net packet correctly. | 9 | '0x7ff | 0x7ff << 11', this will make the 'tulip_copy_tx_buffers's |
10 | 'len1' and 'len2' to 0x7ff(2047). So 'len1+len2' will overflow | ||
11 | 'TULIPState's 'tx_frame' field. This descriptor's 'buf_addr1' and | ||
12 | 'buf_addr2' should set to a guest address. | ||
10 | 13 | ||
11 | Signed-off-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> | 14 | 2. write this descriptor to tulip device's CSR4 register. This will |
15 | set the 'TULIPState's 'current_tx_desc' field. | ||
16 | |||
17 | 3. write 'CSR6_ST' to tulip device's CSR6 register. This will trigger | ||
18 | 'tulip_xmit_list_update' and finally calls 'tulip_copy_tx_buffers'. | ||
19 | |||
20 | Following shows the backtrack of crash: | ||
21 | |||
22 | ==31781==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x628000007cd0 at pc 0x7fe03c5a077a bp 0x7fff05b46770 sp 0x7fff05b45f18 | ||
23 | WRITE of size 2047 at 0x628000007cd0 thread T0 | ||
24 | #0 0x7fe03c5a0779 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x79779) | ||
25 | #1 0x5575fb6daa6a in flatview_read_continue /home/test/qemu/exec.c:3194 | ||
26 | #2 0x5575fb6daccb in flatview_read /home/test/qemu/exec.c:3227 | ||
27 | #3 0x5575fb6dae66 in address_space_read_full /home/test/qemu/exec.c:3240 | ||
28 | #4 0x5575fb6db0cb in address_space_rw /home/test/qemu/exec.c:3268 | ||
29 | #5 0x5575fbdfd460 in dma_memory_rw_relaxed /home/test/qemu/include/sysemu/dma.h:87 | ||
30 | #6 0x5575fbdfd4b5 in dma_memory_rw /home/test/qemu/include/sysemu/dma.h:110 | ||
31 | #7 0x5575fbdfd866 in pci_dma_rw /home/test/qemu/include/hw/pci/pci.h:787 | ||
32 | #8 0x5575fbdfd8a3 in pci_dma_read /home/test/qemu/include/hw/pci/pci.h:794 | ||
33 | #9 0x5575fbe02761 in tulip_copy_tx_buffers hw/net/tulip.c:585 | ||
34 | #10 0x5575fbe0366b in tulip_xmit_list_update hw/net/tulip.c:678 | ||
35 | #11 0x5575fbe04073 in tulip_write hw/net/tulip.c:783 | ||
36 | |||
37 | Signed-off-by: Li Qiang <liq3ea@163.com> | ||
12 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 38 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
13 | --- | 39 | --- |
14 | net/filter-rewriter.c | 37 ++++++++++++++++++++++++++++++++++++- | 40 | tests/qtest/Makefile.include | 1 + |
15 | qemu-options.hx | 4 ++-- | 41 | tests/qtest/tulip-test.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ |
16 | 2 files changed, 38 insertions(+), 3 deletions(-) | 42 | 2 files changed, 92 insertions(+) |
43 | create mode 100644 tests/qtest/tulip-test.c | ||
17 | 44 | ||
18 | diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c | 45 | diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include |
19 | index XXXXXXX..XXXXXXX 100644 | 46 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/net/filter-rewriter.c | 47 | --- a/tests/qtest/Makefile.include |
21 | +++ b/net/filter-rewriter.c | 48 | +++ b/tests/qtest/Makefile.include |
49 | @@ -XXX,XX +XXX,XX @@ qos-test-obj-y += tests/qtest/es1370-test.o | ||
50 | qos-test-obj-y += tests/qtest/ipoctal232-test.o | ||
51 | qos-test-obj-y += tests/qtest/megasas-test.o | ||
52 | qos-test-obj-y += tests/qtest/ne2000-test.o | ||
53 | +qos-test-obj-y += tests/qtest/tulip-test.o | ||
54 | qos-test-obj-y += tests/qtest/nvme-test.o | ||
55 | qos-test-obj-y += tests/qtest/pca9552-test.o | ||
56 | qos-test-obj-y += tests/qtest/pci-test.o | ||
57 | diff --git a/tests/qtest/tulip-test.c b/tests/qtest/tulip-test.c | ||
58 | new file mode 100644 | ||
59 | index XXXXXXX..XXXXXXX | ||
60 | --- /dev/null | ||
61 | +++ b/tests/qtest/tulip-test.c | ||
22 | @@ -XXX,XX +XXX,XX @@ | 62 | @@ -XXX,XX +XXX,XX @@ |
23 | #include "qemu-common.h" | 63 | +/* |
24 | #include "qapi/error.h" | 64 | + * QTest testcase for DEC/Intel Tulip 21143 |
25 | #include "qapi/qmp/qerror.h" | 65 | + * |
26 | +#include "qemu/error-report.h" | 66 | + * Copyright (c) 2020 Li Qiang <liq3ea@gmail.com> |
27 | #include "qapi-visit.h" | 67 | + * |
28 | #include "qom/object.h" | 68 | + * This work is licensed under the terms of the GNU GPL, version 2 or later. |
29 | #include "qemu/main-loop.h" | 69 | + * See the COPYING file in the top-level directory. |
30 | @@ -XXX,XX +XXX,XX @@ typedef struct RewriterState { | 70 | + */ |
31 | NetQueue *incoming_queue; | ||
32 | /* hashtable to save connection */ | ||
33 | GHashTable *connection_track_table; | ||
34 | + bool vnet_hdr; | ||
35 | } RewriterState; | ||
36 | |||
37 | static void filter_rewriter_flush(NetFilterState *nf) | ||
38 | @@ -XXX,XX +XXX,XX @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf, | ||
39 | ConnectionKey key; | ||
40 | Packet *pkt; | ||
41 | ssize_t size = iov_size(iov, iovcnt); | ||
42 | + ssize_t vnet_hdr_len = 0; | ||
43 | char *buf = g_malloc0(size); | ||
44 | |||
45 | iov_to_buf(iov, iovcnt, 0, buf, size); | ||
46 | - pkt = packet_new(buf, size, 0); | ||
47 | + | 71 | + |
48 | + if (s->vnet_hdr) { | 72 | +#include "qemu/osdep.h" |
49 | + vnet_hdr_len = nf->netdev->vnet_hdr_len; | 73 | +#include "libqtest.h" |
74 | +#include "qemu/module.h" | ||
75 | +#include "libqos/qgraph.h" | ||
76 | +#include "libqos/pci.h" | ||
77 | +#include "qemu/bitops.h" | ||
78 | +#include "hw/net/tulip.h" | ||
79 | + | ||
80 | +typedef struct QTulip_pci QTulip_pci; | ||
81 | + | ||
82 | +struct QTulip_pci { | ||
83 | + QOSGraphObject obj; | ||
84 | + QPCIDevice dev; | ||
85 | +}; | ||
86 | + | ||
87 | +static void *tulip_pci_get_driver(void *obj, const char *interface) | ||
88 | +{ | ||
89 | + QTulip_pci *tulip_pci = obj; | ||
90 | + | ||
91 | + if (!g_strcmp0(interface, "pci-device")) { | ||
92 | + return &tulip_pci->dev; | ||
50 | + } | 93 | + } |
51 | + | 94 | + |
52 | + pkt = packet_new(buf, size, vnet_hdr_len); | 95 | + fprintf(stderr, "%s not present in tulip_pci\n", interface); |
53 | g_free(buf); | 96 | + g_assert_not_reached(); |
54 | |||
55 | /* | ||
56 | @@ -XXX,XX +XXX,XX @@ static void colo_rewriter_setup(NetFilterState *nf, Error **errp) | ||
57 | s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf); | ||
58 | } | ||
59 | |||
60 | +static bool filter_rewriter_get_vnet_hdr(Object *obj, Error **errp) | ||
61 | +{ | ||
62 | + RewriterState *s = FILTER_COLO_REWRITER(obj); | ||
63 | + | ||
64 | + return s->vnet_hdr; | ||
65 | +} | 97 | +} |
66 | + | 98 | + |
67 | +static void filter_rewriter_set_vnet_hdr(Object *obj, | 99 | +static void *tulip_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr) |
68 | + bool value, | ||
69 | + Error **errp) | ||
70 | +{ | 100 | +{ |
71 | + RewriterState *s = FILTER_COLO_REWRITER(obj); | 101 | + QTulip_pci *tulip_pci = g_new0(QTulip_pci, 1); |
102 | + QPCIBus *bus = pci_bus; | ||
72 | + | 103 | + |
73 | + s->vnet_hdr = value; | 104 | + qpci_device_init(&tulip_pci->dev, bus, addr); |
105 | + tulip_pci->obj.get_driver = tulip_pci_get_driver; | ||
106 | + | ||
107 | + return &tulip_pci->obj; | ||
74 | +} | 108 | +} |
75 | + | 109 | + |
76 | +static void filter_rewriter_init(Object *obj) | 110 | +static void tulip_large_tx(void *obj, void *data, QGuestAllocator *alloc) |
77 | +{ | 111 | +{ |
78 | + RewriterState *s = FILTER_COLO_REWRITER(obj); | 112 | + QTulip_pci *tulip_pci = obj; |
113 | + QPCIDevice *dev = &tulip_pci->dev; | ||
114 | + QPCIBar bar; | ||
115 | + struct tulip_descriptor context; | ||
116 | + char guest_data[4096]; | ||
117 | + uint64_t context_pa; | ||
118 | + uint64_t guest_pa; | ||
79 | + | 119 | + |
80 | + s->vnet_hdr = false; | 120 | + qpci_device_enable(dev); |
81 | + object_property_add_bool(obj, "vnet_hdr_support", | 121 | + bar = qpci_iomap(dev, 0, NULL); |
82 | + filter_rewriter_get_vnet_hdr, | 122 | + context_pa = guest_alloc(alloc, sizeof(context)); |
83 | + filter_rewriter_set_vnet_hdr, NULL); | 123 | + guest_pa = guest_alloc(alloc, 4096); |
124 | + memset(guest_data, 'A', sizeof(guest_data)); | ||
125 | + context.status = TDES0_OWN; | ||
126 | + context.control = TDES1_BUF2_SIZE_MASK << TDES1_BUF2_SIZE_SHIFT | | ||
127 | + TDES1_BUF1_SIZE_MASK << TDES1_BUF1_SIZE_SHIFT; | ||
128 | + context.buf_addr2 = guest_pa; | ||
129 | + context.buf_addr1 = guest_pa; | ||
130 | + | ||
131 | + qtest_memwrite(dev->bus->qts, context_pa, &context, sizeof(context)); | ||
132 | + qtest_memwrite(dev->bus->qts, guest_pa, guest_data, sizeof(guest_data)); | ||
133 | + qpci_io_writel(dev, bar, 0x20, context_pa); | ||
134 | + qpci_io_writel(dev, bar, 0x30, CSR6_ST); | ||
135 | + guest_free(alloc, context_pa); | ||
136 | + guest_free(alloc, guest_pa); | ||
84 | +} | 137 | +} |
85 | + | 138 | + |
86 | static void colo_rewriter_class_init(ObjectClass *oc, void *data) | 139 | +static void tulip_register_nodes(void) |
87 | { | 140 | +{ |
88 | NetFilterClass *nfc = NETFILTER_CLASS(oc); | 141 | + QOSGraphEdgeOptions opts = { |
89 | @@ -XXX,XX +XXX,XX @@ static const TypeInfo colo_rewriter_info = { | 142 | + .extra_device_opts = "addr=04.0", |
90 | .name = TYPE_FILTER_REWRITER, | 143 | + }; |
91 | .parent = TYPE_NETFILTER, | 144 | + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); |
92 | .class_init = colo_rewriter_class_init, | 145 | + |
93 | + .instance_init = filter_rewriter_init, | 146 | + qos_node_create_driver("tulip", tulip_pci_create); |
94 | .instance_size = sizeof(RewriterState), | 147 | + qos_node_consumes("tulip", "pci-bus", &opts); |
95 | }; | 148 | + qos_node_produces("tulip", "pci-device"); |
96 | 149 | + | |
97 | diff --git a/qemu-options.hx b/qemu-options.hx | 150 | + qos_add_test("tulip_large_tx", "tulip", tulip_large_tx, NULL); |
98 | index XXXXXXX..XXXXXXX 100644 | 151 | +} |
99 | --- a/qemu-options.hx | 152 | + |
100 | +++ b/qemu-options.hx | 153 | +libqos_init(tulip_register_nodes); |
101 | @@ -XXX,XX +XXX,XX @@ Create a filter-redirector we need to differ outdev id from indev id, id can not | ||
102 | be the same. we can just use indev or outdev, but at least one of indev or outdev | ||
103 | need to be specified. | ||
104 | |||
105 | -@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid}[,queue=@var{all|rx|tx}] | ||
106 | +@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx},[vnet_hdr_support] | ||
107 | |||
108 | Filter-rewriter is a part of COLO project.It will rewrite tcp packet to | ||
109 | secondary from primary to keep secondary tcp connection,and rewrite | ||
110 | tcp packet to primary from secondary make tcp packet can be handled by | ||
111 | -client. | ||
112 | +client.if it has the vnet_hdr_support flag, we can parse packet with vnet header. | ||
113 | |||
114 | usage: | ||
115 | colo secondary: | ||
116 | -- | 154 | -- |
117 | 2.7.4 | 155 | 2.5.0 |
118 | 156 | ||
119 | 157 | diff view generated by jsdifflib |