1 | The following changes since commit 23895cbd82be95428e90168b12e925d0d3ca2f06: | 1 | The following changes since commit 886c0453cbf10eebd42a9ccf89c3e46eb389c357: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20201123.0' into staging (2020-11-23 18:51:13 +0000) | 3 | Merge tag 'pull-qapi-2023-05-17-v2' of https://repo.or.cz/qemu/armbru into staging (2023-05-22 15:54:21 -0700) |
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 9925990d01a92564af55f6f69d0f5f59b47609b1: | 9 | for you to fetch changes up to 792676c165159c11412346870fd58fd243ab2166: |
10 | 10 | ||
11 | net: Use correct default-path macro for downscript (2020-11-24 10:40:17 +0800) | 11 | rtl8139: fix large_send_mss divide-by-zero (2023-05-23 15:20:15 +0800) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | 14 | ||
15 | ---------------------------------------------------------------- | 15 | ---------------------------------------------------------------- |
16 | Keqian Zhu (1): | 16 | Akihiko Odaki (48): |
17 | net: Use correct default-path macro for downscript | 17 | hw/net/net_tx_pkt: Decouple implementation from PCI |
18 | hw/net/net_tx_pkt: Decouple interface from PCI | ||
19 | e1000x: Fix BPRC and MPRC | ||
20 | igb: Fix Rx packet type encoding | ||
21 | igb: Do not require CTRL.VME for tx VLAN tagging | ||
22 | igb: Clear IMS bits when committing ICR access | ||
23 | net/net_rx_pkt: Use iovec for net_rx_pkt_set_protocols() | ||
24 | e1000e: Always copy ethernet header | ||
25 | igb: Always copy ethernet header | ||
26 | Fix references to igb Avocado test | ||
27 | tests/avocado: Remove unused imports | ||
28 | tests/avocado: Remove test_igb_nomsi_kvm | ||
29 | hw/net/net_tx_pkt: Remove net_rx_pkt_get_l4_info | ||
30 | net/eth: Rename eth_setup_vlan_headers_ex | ||
31 | e1000x: Share more Rx filtering logic | ||
32 | e1000x: Take CRC into consideration for size check | ||
33 | e1000x: Rename TcpIpv6 into TcpIpv6Ex | ||
34 | e1000e: Always log status after building rx metadata | ||
35 | igb: Always log status after building rx metadata | ||
36 | igb: Remove goto | ||
37 | igb: Read DCMD.VLE of the first Tx descriptor | ||
38 | e1000e: Reset packet state after emptying Tx queue | ||
39 | vmxnet3: Reset packet state after emptying Tx queue | ||
40 | igb: Add more definitions for Tx descriptor | ||
41 | igb: Share common VF constants | ||
42 | igb: Fix igb_mac_reg_init coding style alignment | ||
43 | igb: Clear EICR bits for delayed MSI-X interrupts | ||
44 | e1000e: Rename a variable in e1000e_receive_internal() | ||
45 | igb: Rename a variable in igb_receive_internal() | ||
46 | net/eth: Use void pointers | ||
47 | net/eth: Always add VLAN tag | ||
48 | hw/net/net_rx_pkt: Enforce alignment for eth_header | ||
49 | tests/qtest/libqos/igb: Set GPIE.Multiple_MSIX | ||
50 | igb: Implement MSI-X single vector mode | ||
51 | igb: Use UDP for RSS hash | ||
52 | igb: Implement Rx SCTP CSO | ||
53 | igb: Implement Tx SCTP CSO | ||
54 | igb: Strip the second VLAN tag for extended VLAN | ||
55 | igb: Filter with the second VLAN tag for extended VLAN | ||
56 | igb: Implement igb-specific oversize check | ||
57 | igb: Implement Rx PTP2 timestamp | ||
58 | igb: Implement Tx timestamp | ||
59 | e1000e: Notify only new interrupts | ||
60 | igb: Notify only new interrupts | ||
61 | igb: Clear-on-read ICR when ICR.INTA is set | ||
62 | vmxnet3: Do not depend on PC | ||
63 | MAINTAINERS: Add a reviewer for network packet abstractions | ||
64 | docs/system/devices/igb: Note igb is tested for DPDK | ||
18 | 65 | ||
19 | Paolo Bonzini (1): | 66 | Stefan Hajnoczi (1): |
20 | net: do not exit on "netdev_add help" monitor command | 67 | rtl8139: fix large_send_mss divide-by-zero |
21 | 68 | ||
22 | Prasad J Pandit (1): | 69 | timothee.cocault@gmail.com (1): |
23 | hw/net/e1000e: advance desc_offset in case of null descriptor | 70 | e1000e: Fix tx/rx counters |
24 | 71 | ||
25 | Yuri Benditovich (1): | 72 | MAINTAINERS | 3 +- |
26 | net: purge queued rx packets on queue deletion | 73 | docs/system/devices/igb.rst | 14 +- |
27 | 74 | hw/net/Kconfig | 2 +- | |
28 | yuanjungong (1): | 75 | hw/net/e1000.c | 46 +- |
29 | tap: fix a memory leak | 76 | hw/net/e1000e_core.c | 297 ++++----- |
30 | 77 | hw/net/e1000e_core.h | 2 - | |
31 | hw/net/e1000e_core.c | 8 +++--- | 78 | hw/net/e1000x_common.c | 82 ++- |
32 | include/net/net.h | 1 + | 79 | hw/net/e1000x_common.h | 9 +- |
33 | monitor/hmp-cmds.c | 6 ++++ | 80 | hw/net/e1000x_regs.h | 24 +- |
34 | net/net.c | 80 +++++++++++++++++++++++++++------------------------- | 81 | hw/net/igb.c | 10 +- |
35 | net/tap.c | 5 +++- | 82 | hw/net/igb_common.h | 24 +- |
36 | 5 files changed, 57 insertions(+), 43 deletions(-) | 83 | hw/net/igb_core.c | 722 +++++++++++---------- |
37 | 84 | hw/net/igb_regs.h | 67 +- | |
38 | 85 | hw/net/igbvf.c | 7 - | |
86 | hw/net/net_rx_pkt.c | 107 +-- | ||
87 | hw/net/net_rx_pkt.h | 38 +- | ||
88 | hw/net/net_tx_pkt.c | 101 +-- | ||
89 | hw/net/net_tx_pkt.h | 46 +- | ||
90 | hw/net/rtl8139.c | 3 + | ||
91 | hw/net/trace-events | 19 +- | ||
92 | hw/net/virtio-net.c | 7 +- | ||
93 | hw/net/vmxnet3.c | 22 +- | ||
94 | include/net/eth.h | 29 +- | ||
95 | include/qemu/crc32c.h | 1 + | ||
96 | net/eth.c | 100 +-- | ||
97 | scripts/ci/org.centos/stream/8/x86_64/test-avocado | 3 +- | ||
98 | tests/avocado/netdev-ethtool.py | 17 +- | ||
99 | tests/qtest/libqos/igb.c | 1 + | ||
100 | util/crc32c.c | 8 + | ||
101 | 29 files changed, 979 insertions(+), 832 deletions(-) | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: "timothee.cocault@gmail.com" <timothee.cocault@gmail.com> | ||
1 | 2 | ||
3 | The bytes and packets counter registers are cleared on read. | ||
4 | |||
5 | Copying the "total counter" registers to the "good counter" registers has | ||
6 | side effects. | ||
7 | If the "total" register is never read by the OS, it only gets incremented. | ||
8 | This leads to exponential growth of the "good" register. | ||
9 | |||
10 | This commit increments the counters individually to avoid this. | ||
11 | |||
12 | Signed-off-by: Timothée Cocault <timothee.cocault@gmail.com> | ||
13 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
14 | --- | ||
15 | hw/net/e1000.c | 5 ++--- | ||
16 | hw/net/e1000e_core.c | 5 ++--- | ||
17 | hw/net/e1000x_common.c | 5 ++--- | ||
18 | hw/net/igb_core.c | 5 ++--- | ||
19 | 4 files changed, 8 insertions(+), 12 deletions(-) | ||
20 | |||
21 | diff --git a/hw/net/e1000.c b/hw/net/e1000.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/hw/net/e1000.c | ||
24 | +++ b/hw/net/e1000.c | ||
25 | @@ -XXX,XX +XXX,XX @@ xmit_seg(E1000State *s) | ||
26 | |||
27 | e1000x_inc_reg_if_not_full(s->mac_reg, TPT); | ||
28 | e1000x_grow_8reg_if_not_full(s->mac_reg, TOTL, s->tx.size + 4); | ||
29 | - s->mac_reg[GPTC] = s->mac_reg[TPT]; | ||
30 | - s->mac_reg[GOTCL] = s->mac_reg[TOTL]; | ||
31 | - s->mac_reg[GOTCH] = s->mac_reg[TOTH]; | ||
32 | + e1000x_inc_reg_if_not_full(s->mac_reg, GPTC); | ||
33 | + e1000x_grow_8reg_if_not_full(s->mac_reg, GOTCL, s->tx.size + 4); | ||
34 | } | ||
35 | |||
36 | static void | ||
37 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/hw/net/e1000e_core.c | ||
40 | +++ b/hw/net/e1000e_core.c | ||
41 | @@ -XXX,XX +XXX,XX @@ e1000e_on_tx_done_update_stats(E1000ECore *core, struct NetTxPkt *tx_pkt) | ||
42 | g_assert_not_reached(); | ||
43 | } | ||
44 | |||
45 | - core->mac[GPTC] = core->mac[TPT]; | ||
46 | - core->mac[GOTCL] = core->mac[TOTL]; | ||
47 | - core->mac[GOTCH] = core->mac[TOTH]; | ||
48 | + e1000x_inc_reg_if_not_full(core->mac, GPTC); | ||
49 | + e1000x_grow_8reg_if_not_full(core->mac, GOTCL, tot_len); | ||
50 | } | ||
51 | |||
52 | static void | ||
53 | diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c | ||
54 | index XXXXXXX..XXXXXXX 100644 | ||
55 | --- a/hw/net/e1000x_common.c | ||
56 | +++ b/hw/net/e1000x_common.c | ||
57 | @@ -XXX,XX +XXX,XX @@ e1000x_update_rx_total_stats(uint32_t *mac, | ||
58 | |||
59 | e1000x_increase_size_stats(mac, PRCregs, data_fcs_size); | ||
60 | e1000x_inc_reg_if_not_full(mac, TPR); | ||
61 | - mac[GPRC] = mac[TPR]; | ||
62 | + e1000x_inc_reg_if_not_full(mac, GPRC); | ||
63 | /* TOR - Total Octets Received: | ||
64 | * This register includes bytes received in a packet from the <Destination | ||
65 | * Address> field through the <CRC> field, inclusively. | ||
66 | * Always include FCS length (4) in size. | ||
67 | */ | ||
68 | e1000x_grow_8reg_if_not_full(mac, TORL, data_size + 4); | ||
69 | - mac[GORCL] = mac[TORL]; | ||
70 | - mac[GORCH] = mac[TORH]; | ||
71 | + e1000x_grow_8reg_if_not_full(mac, GORCL, data_size + 4); | ||
72 | } | ||
73 | |||
74 | void | ||
75 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
76 | index XXXXXXX..XXXXXXX 100644 | ||
77 | --- a/hw/net/igb_core.c | ||
78 | +++ b/hw/net/igb_core.c | ||
79 | @@ -XXX,XX +XXX,XX @@ igb_on_tx_done_update_stats(IGBCore *core, struct NetTxPkt *tx_pkt, int qn) | ||
80 | g_assert_not_reached(); | ||
81 | } | ||
82 | |||
83 | - core->mac[GPTC] = core->mac[TPT]; | ||
84 | - core->mac[GOTCL] = core->mac[TOTL]; | ||
85 | - core->mac[GOTCH] = core->mac[TOTH]; | ||
86 | + e1000x_inc_reg_if_not_full(core->mac, GPTC); | ||
87 | + e1000x_grow_8reg_if_not_full(core->mac, GOTCL, tot_len); | ||
88 | |||
89 | if (core->mac[MRQC] & 1) { | ||
90 | uint16_t pool = qn % IGB_NUM_VM_POOLS; | ||
91 | -- | ||
92 | 2.7.4 | ||
93 | |||
94 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | This is intended to be followed by another change for the interface. | ||
4 | It also fixes the leak of memory mapping when the specified memory is | ||
5 | partially mapped. | ||
6 | |||
7 | Fixes: e263cd49c7 ("Packet abstraction for VMWARE network devices") | ||
8 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
9 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
10 | --- | ||
11 | hw/net/net_tx_pkt.c | 53 +++++++++++++++++++++++++++++++++-------------------- | ||
12 | hw/net/net_tx_pkt.h | 9 +++++++++ | ||
13 | 2 files changed, 42 insertions(+), 20 deletions(-) | ||
14 | |||
15 | diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/net/net_tx_pkt.c | ||
18 | +++ b/hw/net/net_tx_pkt.c | ||
19 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt, | ||
20 | } | ||
21 | } | ||
22 | |||
23 | -bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, | ||
24 | - size_t len) | ||
25 | +static bool net_tx_pkt_add_raw_fragment_common(struct NetTxPkt *pkt, | ||
26 | + void *base, size_t len) | ||
27 | { | ||
28 | - hwaddr mapped_len = 0; | ||
29 | struct iovec *ventry; | ||
30 | assert(pkt); | ||
31 | |||
32 | @@ -XXX,XX +XXX,XX @@ bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, | ||
33 | return false; | ||
34 | } | ||
35 | |||
36 | - if (!len) { | ||
37 | - return true; | ||
38 | - } | ||
39 | - | ||
40 | ventry = &pkt->raw[pkt->raw_frags]; | ||
41 | - mapped_len = len; | ||
42 | + ventry->iov_base = base; | ||
43 | + ventry->iov_len = len; | ||
44 | + pkt->raw_frags++; | ||
45 | |||
46 | - ventry->iov_base = pci_dma_map(pkt->pci_dev, pa, | ||
47 | - &mapped_len, DMA_DIRECTION_TO_DEVICE); | ||
48 | - | ||
49 | - if ((ventry->iov_base != NULL) && (len == mapped_len)) { | ||
50 | - ventry->iov_len = mapped_len; | ||
51 | - pkt->raw_frags++; | ||
52 | - return true; | ||
53 | - } else { | ||
54 | - return false; | ||
55 | - } | ||
56 | + return true; | ||
57 | } | ||
58 | |||
59 | bool net_tx_pkt_has_fragments(struct NetTxPkt *pkt) | ||
60 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_reset(struct NetTxPkt *pkt, PCIDevice *pci_dev) | ||
61 | assert(pkt->raw); | ||
62 | for (i = 0; i < pkt->raw_frags; i++) { | ||
63 | assert(pkt->raw[i].iov_base); | ||
64 | - pci_dma_unmap(pkt->pci_dev, pkt->raw[i].iov_base, | ||
65 | - pkt->raw[i].iov_len, DMA_DIRECTION_TO_DEVICE, 0); | ||
66 | + net_tx_pkt_unmap_frag_pci(pkt->pci_dev, | ||
67 | + pkt->raw[i].iov_base, | ||
68 | + pkt->raw[i].iov_len); | ||
69 | } | ||
70 | } | ||
71 | pkt->pci_dev = pci_dev; | ||
72 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_reset(struct NetTxPkt *pkt, PCIDevice *pci_dev) | ||
73 | pkt->l4proto = 0; | ||
74 | } | ||
75 | |||
76 | +void net_tx_pkt_unmap_frag_pci(void *context, void *base, size_t len) | ||
77 | +{ | ||
78 | + pci_dma_unmap(context, base, len, DMA_DIRECTION_TO_DEVICE, 0); | ||
79 | +} | ||
80 | + | ||
81 | +bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, | ||
82 | + size_t len) | ||
83 | +{ | ||
84 | + dma_addr_t mapped_len = len; | ||
85 | + void *base = pci_dma_map(pkt->pci_dev, pa, &mapped_len, | ||
86 | + DMA_DIRECTION_TO_DEVICE); | ||
87 | + if (!base) { | ||
88 | + return false; | ||
89 | + } | ||
90 | + | ||
91 | + if (mapped_len != len || | ||
92 | + !net_tx_pkt_add_raw_fragment_common(pkt, base, len)) { | ||
93 | + net_tx_pkt_unmap_frag_pci(pkt->pci_dev, base, mapped_len); | ||
94 | + return false; | ||
95 | + } | ||
96 | + | ||
97 | + return true; | ||
98 | +} | ||
99 | + | ||
100 | static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt, | ||
101 | struct iovec *iov, uint32_t iov_len, | ||
102 | uint16_t csl) | ||
103 | diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h | ||
104 | index XXXXXXX..XXXXXXX 100644 | ||
105 | --- a/hw/net/net_tx_pkt.h | ||
106 | +++ b/hw/net/net_tx_pkt.h | ||
107 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_dump(struct NetTxPkt *pkt); | ||
108 | void net_tx_pkt_reset(struct NetTxPkt *pkt, PCIDevice *dev); | ||
109 | |||
110 | /** | ||
111 | + * Unmap a fragment mapped from a PCI device. | ||
112 | + * | ||
113 | + * @context: PCI device owning fragment | ||
114 | + * @base: pointer to fragment | ||
115 | + * @len: length of fragment | ||
116 | + */ | ||
117 | +void net_tx_pkt_unmap_frag_pci(void *context, void *base, size_t len); | ||
118 | + | ||
119 | +/** | ||
120 | * Send packet to qemu. handles sw offloads if vhdr is not supported. | ||
121 | * | ||
122 | * @pkt: packet | ||
123 | -- | ||
124 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | This allows to use the network packet abstractions even if PCI is not | ||
4 | used. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
8 | --- | ||
9 | hw/net/e1000e_core.c | 13 ++++++++----- | ||
10 | hw/net/igb_core.c | 13 ++++++------- | ||
11 | hw/net/net_tx_pkt.c | 36 +++++++++++++----------------------- | ||
12 | hw/net/net_tx_pkt.h | 31 ++++++++++++++++++++----------- | ||
13 | hw/net/vmxnet3.c | 14 +++++++------- | ||
14 | 5 files changed, 54 insertions(+), 53 deletions(-) | ||
15 | |||
16 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/net/e1000e_core.c | ||
19 | +++ b/hw/net/e1000e_core.c | ||
20 | @@ -XXX,XX +XXX,XX @@ e1000e_process_tx_desc(E1000ECore *core, | ||
21 | addr = le64_to_cpu(dp->buffer_addr); | ||
22 | |||
23 | if (!tx->skip_cp) { | ||
24 | - if (!net_tx_pkt_add_raw_fragment(tx->tx_pkt, addr, split_size)) { | ||
25 | + if (!net_tx_pkt_add_raw_fragment_pci(tx->tx_pkt, core->owner, | ||
26 | + addr, split_size)) { | ||
27 | tx->skip_cp = true; | ||
28 | } | ||
29 | } | ||
30 | @@ -XXX,XX +XXX,XX @@ e1000e_process_tx_desc(E1000ECore *core, | ||
31 | } | ||
32 | |||
33 | tx->skip_cp = false; | ||
34 | - net_tx_pkt_reset(tx->tx_pkt, core->owner); | ||
35 | + net_tx_pkt_reset(tx->tx_pkt, net_tx_pkt_unmap_frag_pci, core->owner); | ||
36 | |||
37 | tx->sum_needed = 0; | ||
38 | tx->cptse = 0; | ||
39 | @@ -XXX,XX +XXX,XX @@ e1000e_core_pci_realize(E1000ECore *core, | ||
40 | qemu_add_vm_change_state_handler(e1000e_vm_state_change, core); | ||
41 | |||
42 | for (i = 0; i < E1000E_NUM_QUEUES; i++) { | ||
43 | - net_tx_pkt_init(&core->tx[i].tx_pkt, core->owner, E1000E_MAX_TX_FRAGS); | ||
44 | + net_tx_pkt_init(&core->tx[i].tx_pkt, E1000E_MAX_TX_FRAGS); | ||
45 | } | ||
46 | |||
47 | net_rx_pkt_init(&core->rx_pkt); | ||
48 | @@ -XXX,XX +XXX,XX @@ e1000e_core_pci_uninit(E1000ECore *core) | ||
49 | qemu_del_vm_change_state_handler(core->vmstate); | ||
50 | |||
51 | for (i = 0; i < E1000E_NUM_QUEUES; i++) { | ||
52 | - net_tx_pkt_reset(core->tx[i].tx_pkt, core->owner); | ||
53 | + net_tx_pkt_reset(core->tx[i].tx_pkt, | ||
54 | + net_tx_pkt_unmap_frag_pci, core->owner); | ||
55 | net_tx_pkt_uninit(core->tx[i].tx_pkt); | ||
56 | } | ||
57 | |||
58 | @@ -XXX,XX +XXX,XX @@ static void e1000e_reset(E1000ECore *core, bool sw) | ||
59 | e1000x_reset_mac_addr(core->owner_nic, core->mac, core->permanent_mac); | ||
60 | |||
61 | for (i = 0; i < ARRAY_SIZE(core->tx); i++) { | ||
62 | - net_tx_pkt_reset(core->tx[i].tx_pkt, core->owner); | ||
63 | + net_tx_pkt_reset(core->tx[i].tx_pkt, | ||
64 | + net_tx_pkt_unmap_frag_pci, core->owner); | ||
65 | memset(&core->tx[i].props, 0, sizeof(core->tx[i].props)); | ||
66 | core->tx[i].skip_cp = false; | ||
67 | } | ||
68 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
69 | index XXXXXXX..XXXXXXX 100644 | ||
70 | --- a/hw/net/igb_core.c | ||
71 | +++ b/hw/net/igb_core.c | ||
72 | @@ -XXX,XX +XXX,XX @@ igb_process_tx_desc(IGBCore *core, | ||
73 | length = cmd_type_len & 0xFFFF; | ||
74 | |||
75 | if (!tx->skip_cp) { | ||
76 | - if (!net_tx_pkt_add_raw_fragment(tx->tx_pkt, buffer_addr, length)) { | ||
77 | + if (!net_tx_pkt_add_raw_fragment_pci(tx->tx_pkt, dev, | ||
78 | + buffer_addr, length)) { | ||
79 | tx->skip_cp = true; | ||
80 | } | ||
81 | } | ||
82 | @@ -XXX,XX +XXX,XX @@ igb_process_tx_desc(IGBCore *core, | ||
83 | |||
84 | tx->first = true; | ||
85 | tx->skip_cp = false; | ||
86 | - net_tx_pkt_reset(tx->tx_pkt, dev); | ||
87 | + net_tx_pkt_reset(tx->tx_pkt, net_tx_pkt_unmap_frag_pci, dev); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | @@ -XXX,XX +XXX,XX @@ igb_start_xmit(IGBCore *core, const IGB_TxRing *txr) | ||
92 | d = core->owner; | ||
93 | } | ||
94 | |||
95 | - net_tx_pkt_reset(txr->tx->tx_pkt, d); | ||
96 | - | ||
97 | while (!igb_ring_empty(core, txi)) { | ||
98 | base = igb_ring_head_descr(core, txi); | ||
99 | |||
100 | @@ -XXX,XX +XXX,XX @@ igb_start_xmit(IGBCore *core, const IGB_TxRing *txr) | ||
101 | core->mac[EICR] |= eic; | ||
102 | igb_set_interrupt_cause(core, E1000_ICR_TXDW); | ||
103 | } | ||
104 | + | ||
105 | + net_tx_pkt_reset(txr->tx->tx_pkt, net_tx_pkt_unmap_frag_pci, d); | ||
106 | } | ||
107 | |||
108 | static uint32_t | ||
109 | @@ -XXX,XX +XXX,XX @@ igb_core_pci_realize(IGBCore *core, | ||
110 | core->vmstate = qemu_add_vm_change_state_handler(igb_vm_state_change, core); | ||
111 | |||
112 | for (i = 0; i < IGB_NUM_QUEUES; i++) { | ||
113 | - net_tx_pkt_init(&core->tx[i].tx_pkt, NULL, E1000E_MAX_TX_FRAGS); | ||
114 | + net_tx_pkt_init(&core->tx[i].tx_pkt, E1000E_MAX_TX_FRAGS); | ||
115 | } | ||
116 | |||
117 | net_rx_pkt_init(&core->rx_pkt); | ||
118 | @@ -XXX,XX +XXX,XX @@ igb_core_pci_uninit(IGBCore *core) | ||
119 | qemu_del_vm_change_state_handler(core->vmstate); | ||
120 | |||
121 | for (i = 0; i < IGB_NUM_QUEUES; i++) { | ||
122 | - net_tx_pkt_reset(core->tx[i].tx_pkt, NULL); | ||
123 | net_tx_pkt_uninit(core->tx[i].tx_pkt); | ||
124 | } | ||
125 | |||
126 | @@ -XXX,XX +XXX,XX @@ static void igb_reset(IGBCore *core, bool sw) | ||
127 | |||
128 | for (i = 0; i < ARRAY_SIZE(core->tx); i++) { | ||
129 | tx = &core->tx[i]; | ||
130 | - net_tx_pkt_reset(tx->tx_pkt, NULL); | ||
131 | memset(tx->ctx, 0, sizeof(tx->ctx)); | ||
132 | tx->first = true; | ||
133 | tx->skip_cp = false; | ||
134 | diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c | ||
135 | index XXXXXXX..XXXXXXX 100644 | ||
136 | --- a/hw/net/net_tx_pkt.c | ||
137 | +++ b/hw/net/net_tx_pkt.c | ||
138 | @@ -XXX,XX +XXX,XX @@ | ||
139 | */ | ||
140 | |||
141 | #include "qemu/osdep.h" | ||
142 | -#include "net_tx_pkt.h" | ||
143 | #include "net/eth.h" | ||
144 | #include "net/checksum.h" | ||
145 | #include "net/tap.h" | ||
146 | #include "net/net.h" | ||
147 | #include "hw/pci/pci_device.h" | ||
148 | +#include "net_tx_pkt.h" | ||
149 | |||
150 | enum { | ||
151 | NET_TX_PKT_VHDR_FRAG = 0, | ||
152 | @@ -XXX,XX +XXX,XX @@ enum { | ||
153 | |||
154 | /* TX packet private context */ | ||
155 | struct NetTxPkt { | ||
156 | - PCIDevice *pci_dev; | ||
157 | - | ||
158 | struct virtio_net_hdr virt_hdr; | ||
159 | |||
160 | struct iovec *raw; | ||
161 | @@ -XXX,XX +XXX,XX @@ struct NetTxPkt { | ||
162 | uint8_t l4proto; | ||
163 | }; | ||
164 | |||
165 | -void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev, | ||
166 | - uint32_t max_frags) | ||
167 | +void net_tx_pkt_init(struct NetTxPkt **pkt, uint32_t max_frags) | ||
168 | { | ||
169 | struct NetTxPkt *p = g_malloc0(sizeof *p); | ||
170 | |||
171 | - p->pci_dev = pci_dev; | ||
172 | - | ||
173 | p->vec = g_new(struct iovec, max_frags + NET_TX_PKT_PL_START_FRAG); | ||
174 | |||
175 | p->raw = g_new(struct iovec, max_frags); | ||
176 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt, | ||
177 | } | ||
178 | } | ||
179 | |||
180 | -static bool net_tx_pkt_add_raw_fragment_common(struct NetTxPkt *pkt, | ||
181 | - void *base, size_t len) | ||
182 | +bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, void *base, size_t len) | ||
183 | { | ||
184 | struct iovec *ventry; | ||
185 | assert(pkt); | ||
186 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_dump(struct NetTxPkt *pkt) | ||
187 | #endif | ||
188 | } | ||
189 | |||
190 | -void net_tx_pkt_reset(struct NetTxPkt *pkt, PCIDevice *pci_dev) | ||
191 | +void net_tx_pkt_reset(struct NetTxPkt *pkt, | ||
192 | + NetTxPktFreeFrag callback, void *context) | ||
193 | { | ||
194 | int i; | ||
195 | |||
196 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_reset(struct NetTxPkt *pkt, PCIDevice *pci_dev) | ||
197 | assert(pkt->raw); | ||
198 | for (i = 0; i < pkt->raw_frags; i++) { | ||
199 | assert(pkt->raw[i].iov_base); | ||
200 | - net_tx_pkt_unmap_frag_pci(pkt->pci_dev, | ||
201 | - pkt->raw[i].iov_base, | ||
202 | - pkt->raw[i].iov_len); | ||
203 | + callback(context, pkt->raw[i].iov_base, pkt->raw[i].iov_len); | ||
204 | } | ||
205 | } | ||
206 | - pkt->pci_dev = pci_dev; | ||
207 | pkt->raw_frags = 0; | ||
208 | |||
209 | pkt->hdr_len = 0; | ||
210 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_unmap_frag_pci(void *context, void *base, size_t len) | ||
211 | pci_dma_unmap(context, base, len, DMA_DIRECTION_TO_DEVICE, 0); | ||
212 | } | ||
213 | |||
214 | -bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, | ||
215 | - size_t len) | ||
216 | +bool net_tx_pkt_add_raw_fragment_pci(struct NetTxPkt *pkt, PCIDevice *pci_dev, | ||
217 | + dma_addr_t pa, size_t len) | ||
218 | { | ||
219 | dma_addr_t mapped_len = len; | ||
220 | - void *base = pci_dma_map(pkt->pci_dev, pa, &mapped_len, | ||
221 | - DMA_DIRECTION_TO_DEVICE); | ||
222 | + void *base = pci_dma_map(pci_dev, pa, &mapped_len, DMA_DIRECTION_TO_DEVICE); | ||
223 | if (!base) { | ||
224 | return false; | ||
225 | } | ||
226 | |||
227 | - if (mapped_len != len || | ||
228 | - !net_tx_pkt_add_raw_fragment_common(pkt, base, len)) { | ||
229 | - net_tx_pkt_unmap_frag_pci(pkt->pci_dev, base, mapped_len); | ||
230 | + if (mapped_len != len || !net_tx_pkt_add_raw_fragment(pkt, base, len)) { | ||
231 | + net_tx_pkt_unmap_frag_pci(pci_dev, base, mapped_len); | ||
232 | return false; | ||
233 | } | ||
234 | |||
235 | @@ -XXX,XX +XXX,XX @@ static void net_tx_pkt_udp_fragment_fix(struct NetTxPkt *pkt, | ||
236 | } | ||
237 | |||
238 | static bool net_tx_pkt_do_sw_fragmentation(struct NetTxPkt *pkt, | ||
239 | - NetTxPktCallback callback, | ||
240 | + NetTxPktSend callback, | ||
241 | void *context) | ||
242 | { | ||
243 | uint8_t gso_type = pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN; | ||
244 | @@ -XXX,XX +XXX,XX @@ bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc) | ||
245 | } | ||
246 | |||
247 | bool net_tx_pkt_send_custom(struct NetTxPkt *pkt, bool offload, | ||
248 | - NetTxPktCallback callback, void *context) | ||
249 | + NetTxPktSend callback, void *context) | ||
250 | { | ||
251 | assert(pkt); | ||
252 | |||
253 | diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h | ||
254 | index XXXXXXX..XXXXXXX 100644 | ||
255 | --- a/hw/net/net_tx_pkt.h | ||
256 | +++ b/hw/net/net_tx_pkt.h | ||
257 | @@ -XXX,XX +XXX,XX @@ | ||
258 | |||
259 | struct NetTxPkt; | ||
260 | |||
261 | -typedef void (* NetTxPktCallback)(void *, const struct iovec *, int, const struct iovec *, int); | ||
262 | +typedef void (*NetTxPktFreeFrag)(void *, void *, size_t); | ||
263 | +typedef void (*NetTxPktSend)(void *, const struct iovec *, int, const struct iovec *, int); | ||
264 | |||
265 | /** | ||
266 | * Init function for tx packet functionality | ||
267 | * | ||
268 | * @pkt: packet pointer | ||
269 | - * @pci_dev: PCI device processing this packet | ||
270 | * @max_frags: max tx ip fragments | ||
271 | */ | ||
272 | -void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev, | ||
273 | - uint32_t max_frags); | ||
274 | +void net_tx_pkt_init(struct NetTxPkt **pkt, uint32_t max_frags); | ||
275 | |||
276 | /** | ||
277 | * Clean all tx packet resources. | ||
278 | @@ -XXX,XX +XXX,XX @@ net_tx_pkt_setup_vlan_header(struct NetTxPkt *pkt, uint16_t vlan) | ||
279 | * populate data fragment into pkt context. | ||
280 | * | ||
281 | * @pkt: packet | ||
282 | - * @pa: physical address of fragment | ||
283 | + * @base: pointer to fragment | ||
284 | * @len: length of fragment | ||
285 | * | ||
286 | */ | ||
287 | -bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, | ||
288 | - size_t len); | ||
289 | +bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, void *base, size_t len); | ||
290 | |||
291 | /** | ||
292 | * Fix ip header fields and calculate IP header and pseudo header checksums. | ||
293 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_dump(struct NetTxPkt *pkt); | ||
294 | * reset tx packet private context (needed to be called between packets) | ||
295 | * | ||
296 | * @pkt: packet | ||
297 | - * @dev: PCI device processing the next packet | ||
298 | - * | ||
299 | + * @callback: function to free the fragments | ||
300 | + * @context: pointer to be passed to the callback | ||
301 | */ | ||
302 | -void net_tx_pkt_reset(struct NetTxPkt *pkt, PCIDevice *dev); | ||
303 | +void net_tx_pkt_reset(struct NetTxPkt *pkt, | ||
304 | + NetTxPktFreeFrag callback, void *context); | ||
305 | |||
306 | /** | ||
307 | * Unmap a fragment mapped from a PCI device. | ||
308 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_reset(struct NetTxPkt *pkt, PCIDevice *dev); | ||
309 | void net_tx_pkt_unmap_frag_pci(void *context, void *base, size_t len); | ||
310 | |||
311 | /** | ||
312 | + * map data fragment from PCI device and populate it into pkt context. | ||
313 | + * | ||
314 | + * @pci_dev: PCI device owning fragment | ||
315 | + * @pa: physical address of fragment | ||
316 | + * @len: length of fragment | ||
317 | + */ | ||
318 | +bool net_tx_pkt_add_raw_fragment_pci(struct NetTxPkt *pkt, PCIDevice *pci_dev, | ||
319 | + dma_addr_t pa, size_t len); | ||
320 | + | ||
321 | +/** | ||
322 | * Send packet to qemu. handles sw offloads if vhdr is not supported. | ||
323 | * | ||
324 | * @pkt: packet | ||
325 | @@ -XXX,XX +XXX,XX @@ bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc); | ||
326 | * @ret: operation result | ||
327 | */ | ||
328 | bool net_tx_pkt_send_custom(struct NetTxPkt *pkt, bool offload, | ||
329 | - NetTxPktCallback callback, void *context); | ||
330 | + NetTxPktSend callback, void *context); | ||
331 | |||
332 | /** | ||
333 | * parse raw packet data and analyze offload requirements. | ||
334 | diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c | ||
335 | index XXXXXXX..XXXXXXX 100644 | ||
336 | --- a/hw/net/vmxnet3.c | ||
337 | +++ b/hw/net/vmxnet3.c | ||
338 | @@ -XXX,XX +XXX,XX @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx) | ||
339 | data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE; | ||
340 | data_pa = txd.addr; | ||
341 | |||
342 | - if (!net_tx_pkt_add_raw_fragment(s->tx_pkt, | ||
343 | - data_pa, | ||
344 | - data_len)) { | ||
345 | + if (!net_tx_pkt_add_raw_fragment_pci(s->tx_pkt, PCI_DEVICE(s), | ||
346 | + data_pa, data_len)) { | ||
347 | s->skip_current_tx_pkt = true; | ||
348 | } | ||
349 | } | ||
350 | @@ -XXX,XX +XXX,XX @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx) | ||
351 | vmxnet3_complete_packet(s, qidx, txd_idx); | ||
352 | s->tx_sop = true; | ||
353 | s->skip_current_tx_pkt = false; | ||
354 | - net_tx_pkt_reset(s->tx_pkt, PCI_DEVICE(s)); | ||
355 | + net_tx_pkt_reset(s->tx_pkt, | ||
356 | + net_tx_pkt_unmap_frag_pci, PCI_DEVICE(s)); | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | @@ -XXX,XX +XXX,XX @@ static void vmxnet3_deactivate_device(VMXNET3State *s) | ||
361 | { | ||
362 | if (s->device_active) { | ||
363 | VMW_CBPRN("Deactivating vmxnet3..."); | ||
364 | - net_tx_pkt_reset(s->tx_pkt, PCI_DEVICE(s)); | ||
365 | + net_tx_pkt_reset(s->tx_pkt, net_tx_pkt_unmap_frag_pci, PCI_DEVICE(s)); | ||
366 | net_tx_pkt_uninit(s->tx_pkt); | ||
367 | net_rx_pkt_uninit(s->rx_pkt); | ||
368 | s->device_active = false; | ||
369 | @@ -XXX,XX +XXX,XX @@ static void vmxnet3_activate_device(VMXNET3State *s) | ||
370 | |||
371 | /* Preallocate TX packet wrapper */ | ||
372 | VMW_CFPRN("Max TX fragments is %u", s->max_tx_frags); | ||
373 | - net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s), s->max_tx_frags); | ||
374 | + net_tx_pkt_init(&s->tx_pkt, s->max_tx_frags); | ||
375 | net_rx_pkt_init(&s->rx_pkt); | ||
376 | |||
377 | /* Read rings memory locations for RX queues */ | ||
378 | @@ -XXX,XX +XXX,XX @@ static int vmxnet3_post_load(void *opaque, int version_id) | ||
379 | { | ||
380 | VMXNET3State *s = opaque; | ||
381 | |||
382 | - net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s), s->max_tx_frags); | ||
383 | + net_tx_pkt_init(&s->tx_pkt, s->max_tx_frags); | ||
384 | net_rx_pkt_init(&s->rx_pkt); | ||
385 | |||
386 | if (s->msix_used) { | ||
387 | -- | ||
388 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | |
2 | |||
3 | Before this change, e1000 and the common code updated BPRC and MPRC | ||
4 | depending on the matched filter, but e1000e and igb decided to update | ||
5 | those counters by deriving the packet type independently. This | ||
6 | inconsistency caused a multicast packet to be counted twice. | ||
7 | |||
8 | Updating BPRC and MPRC depending on are fundamentally flawed anyway as | ||
9 | a filter can be used for different types of packets. For example, it is | ||
10 | possible to filter broadcast packets with MTA. | ||
11 | |||
12 | Always determine what counters to update by inspecting the packets. | ||
13 | |||
14 | Fixes: 3b27430177 ("e1000: Implementing various counters") | ||
15 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
16 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
17 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
18 | --- | ||
19 | hw/net/e1000.c | 6 +++--- | ||
20 | hw/net/e1000e_core.c | 20 +++----------------- | ||
21 | hw/net/e1000x_common.c | 25 +++++++++++++++++++------ | ||
22 | hw/net/e1000x_common.h | 5 +++-- | ||
23 | hw/net/igb_core.c | 22 +++++----------------- | ||
24 | 5 files changed, 33 insertions(+), 45 deletions(-) | ||
25 | |||
26 | diff --git a/hw/net/e1000.c b/hw/net/e1000.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/hw/net/e1000.c | ||
29 | +++ b/hw/net/e1000.c | ||
30 | @@ -XXX,XX +XXX,XX @@ receive_filter(E1000State *s, const uint8_t *buf, int size) | ||
31 | } | ||
32 | |||
33 | if (ismcast && (rctl & E1000_RCTL_MPE)) { /* promiscuous mcast */ | ||
34 | - e1000x_inc_reg_if_not_full(s->mac_reg, MPRC); | ||
35 | return 1; | ||
36 | } | ||
37 | |||
38 | if (isbcast && (rctl & E1000_RCTL_BAM)) { /* broadcast enabled */ | ||
39 | - e1000x_inc_reg_if_not_full(s->mac_reg, BPRC); | ||
40 | return 1; | ||
41 | } | ||
42 | |||
43 | @@ -XXX,XX +XXX,XX @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) | ||
44 | size_t desc_offset; | ||
45 | size_t desc_size; | ||
46 | size_t total_size; | ||
47 | + eth_pkt_types_e pkt_type; | ||
48 | |||
49 | if (!e1000x_hw_rx_enabled(s->mac_reg)) { | ||
50 | return -1; | ||
51 | @@ -XXX,XX +XXX,XX @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) | ||
52 | size -= 4; | ||
53 | } | ||
54 | |||
55 | + pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(filter_buf)); | ||
56 | rdh_start = s->mac_reg[RDH]; | ||
57 | desc_offset = 0; | ||
58 | total_size = size + e1000x_fcs_len(s->mac_reg); | ||
59 | @@ -XXX,XX +XXX,XX @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) | ||
60 | } | ||
61 | } while (desc_offset < total_size); | ||
62 | |||
63 | - e1000x_update_rx_total_stats(s->mac_reg, size, total_size); | ||
64 | + e1000x_update_rx_total_stats(s->mac_reg, pkt_type, size, total_size); | ||
65 | |||
66 | n = E1000_ICS_RXT0; | ||
67 | if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH]) | ||
68 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
69 | index XXXXXXX..XXXXXXX 100644 | ||
70 | --- a/hw/net/e1000e_core.c | ||
71 | +++ b/hw/net/e1000e_core.c | ||
72 | @@ -XXX,XX +XXX,XX @@ e1000e_write_to_rx_buffers(E1000ECore *core, | ||
73 | } | ||
74 | |||
75 | static void | ||
76 | -e1000e_update_rx_stats(E1000ECore *core, | ||
77 | - size_t data_size, | ||
78 | - size_t data_fcs_size) | ||
79 | +e1000e_update_rx_stats(E1000ECore *core, size_t pkt_size, size_t pkt_fcs_size) | ||
80 | { | ||
81 | - e1000x_update_rx_total_stats(core->mac, data_size, data_fcs_size); | ||
82 | - | ||
83 | - switch (net_rx_pkt_get_packet_type(core->rx_pkt)) { | ||
84 | - case ETH_PKT_BCAST: | ||
85 | - e1000x_inc_reg_if_not_full(core->mac, BPRC); | ||
86 | - break; | ||
87 | - | ||
88 | - case ETH_PKT_MCAST: | ||
89 | - e1000x_inc_reg_if_not_full(core->mac, MPRC); | ||
90 | - break; | ||
91 | - | ||
92 | - default: | ||
93 | - break; | ||
94 | - } | ||
95 | + eth_pkt_types_e pkt_type = net_rx_pkt_get_packet_type(core->rx_pkt); | ||
96 | + e1000x_update_rx_total_stats(core->mac, pkt_type, pkt_size, pkt_fcs_size); | ||
97 | } | ||
98 | |||
99 | static inline bool | ||
100 | diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c | ||
101 | index XXXXXXX..XXXXXXX 100644 | ||
102 | --- a/hw/net/e1000x_common.c | ||
103 | +++ b/hw/net/e1000x_common.c | ||
104 | @@ -XXX,XX +XXX,XX @@ bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf) | ||
105 | f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3]; | ||
106 | f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff; | ||
107 | if (mac[MTA + (f >> 5)] & (1 << (f & 0x1f))) { | ||
108 | - e1000x_inc_reg_if_not_full(mac, MPRC); | ||
109 | return true; | ||
110 | } | ||
111 | |||
112 | @@ -XXX,XX +XXX,XX @@ e1000x_rxbufsize(uint32_t rctl) | ||
113 | |||
114 | void | ||
115 | e1000x_update_rx_total_stats(uint32_t *mac, | ||
116 | - size_t data_size, | ||
117 | - size_t data_fcs_size) | ||
118 | + eth_pkt_types_e pkt_type, | ||
119 | + size_t pkt_size, | ||
120 | + size_t pkt_fcs_size) | ||
121 | { | ||
122 | static const int PRCregs[6] = { PRC64, PRC127, PRC255, PRC511, | ||
123 | PRC1023, PRC1522 }; | ||
124 | |||
125 | - e1000x_increase_size_stats(mac, PRCregs, data_fcs_size); | ||
126 | + e1000x_increase_size_stats(mac, PRCregs, pkt_fcs_size); | ||
127 | e1000x_inc_reg_if_not_full(mac, TPR); | ||
128 | e1000x_inc_reg_if_not_full(mac, GPRC); | ||
129 | /* TOR - Total Octets Received: | ||
130 | @@ -XXX,XX +XXX,XX @@ e1000x_update_rx_total_stats(uint32_t *mac, | ||
131 | * Address> field through the <CRC> field, inclusively. | ||
132 | * Always include FCS length (4) in size. | ||
133 | */ | ||
134 | - e1000x_grow_8reg_if_not_full(mac, TORL, data_size + 4); | ||
135 | - e1000x_grow_8reg_if_not_full(mac, GORCL, data_size + 4); | ||
136 | + e1000x_grow_8reg_if_not_full(mac, TORL, pkt_size + 4); | ||
137 | + e1000x_grow_8reg_if_not_full(mac, GORCL, pkt_size + 4); | ||
138 | + | ||
139 | + switch (pkt_type) { | ||
140 | + case ETH_PKT_BCAST: | ||
141 | + e1000x_inc_reg_if_not_full(mac, BPRC); | ||
142 | + break; | ||
143 | + | ||
144 | + case ETH_PKT_MCAST: | ||
145 | + e1000x_inc_reg_if_not_full(mac, MPRC); | ||
146 | + break; | ||
147 | + | ||
148 | + default: | ||
149 | + break; | ||
150 | + } | ||
151 | } | ||
152 | |||
153 | void | ||
154 | diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h | ||
155 | index XXXXXXX..XXXXXXX 100644 | ||
156 | --- a/hw/net/e1000x_common.h | ||
157 | +++ b/hw/net/e1000x_common.h | ||
158 | @@ -XXX,XX +XXX,XX @@ e1000x_update_regs_on_link_up(uint32_t *mac, uint16_t *phy) | ||
159 | } | ||
160 | |||
161 | void e1000x_update_rx_total_stats(uint32_t *mac, | ||
162 | - size_t data_size, | ||
163 | - size_t data_fcs_size); | ||
164 | + eth_pkt_types_e pkt_type, | ||
165 | + size_t pkt_size, | ||
166 | + size_t pkt_fcs_size); | ||
167 | |||
168 | void e1000x_core_prepare_eeprom(uint16_t *eeprom, | ||
169 | const uint16_t *templ, | ||
170 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
171 | index XXXXXXX..XXXXXXX 100644 | ||
172 | --- a/hw/net/igb_core.c | ||
173 | +++ b/hw/net/igb_core.c | ||
174 | @@ -XXX,XX +XXX,XX @@ igb_write_to_rx_buffers(IGBCore *core, | ||
175 | |||
176 | static void | ||
177 | igb_update_rx_stats(IGBCore *core, const E1000E_RingInfo *rxi, | ||
178 | - size_t data_size, size_t data_fcs_size) | ||
179 | + size_t pkt_size, size_t pkt_fcs_size) | ||
180 | { | ||
181 | - e1000x_update_rx_total_stats(core->mac, data_size, data_fcs_size); | ||
182 | - | ||
183 | - switch (net_rx_pkt_get_packet_type(core->rx_pkt)) { | ||
184 | - case ETH_PKT_BCAST: | ||
185 | - e1000x_inc_reg_if_not_full(core->mac, BPRC); | ||
186 | - break; | ||
187 | - | ||
188 | - case ETH_PKT_MCAST: | ||
189 | - e1000x_inc_reg_if_not_full(core->mac, MPRC); | ||
190 | - break; | ||
191 | - | ||
192 | - default: | ||
193 | - break; | ||
194 | - } | ||
195 | + eth_pkt_types_e pkt_type = net_rx_pkt_get_packet_type(core->rx_pkt); | ||
196 | + e1000x_update_rx_total_stats(core->mac, pkt_type, pkt_size, pkt_fcs_size); | ||
197 | |||
198 | if (core->mac[MRQC] & 1) { | ||
199 | uint16_t pool = rxi->idx % IGB_NUM_VM_POOLS; | ||
200 | |||
201 | - core->mac[PVFGORC0 + (pool * 64)] += data_size + 4; | ||
202 | + core->mac[PVFGORC0 + (pool * 64)] += pkt_size + 4; | ||
203 | core->mac[PVFGPRC0 + (pool * 64)]++; | ||
204 | - if (net_rx_pkt_get_packet_type(core->rx_pkt) == ETH_PKT_MCAST) { | ||
205 | + if (pkt_type == ETH_PKT_MCAST) { | ||
206 | core->mac[PVFMPRC0 + (pool * 64)]++; | ||
207 | } | ||
208 | } | ||
209 | -- | ||
210 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | igb's advanced descriptor uses a packet type encoding different from | ||
4 | one used in e1000e's extended descriptor. Fix the logic to encode | ||
5 | Rx packet type accordingly. | ||
6 | |||
7 | Fixes: 3a977deebe ("Intrdocue igb device emulation") | ||
8 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
9 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
10 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
11 | --- | ||
12 | hw/net/igb_core.c | 38 +++++++++++++++++++------------------- | ||
13 | hw/net/igb_regs.h | 5 +++++ | ||
14 | 2 files changed, 24 insertions(+), 19 deletions(-) | ||
15 | |||
16 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/net/igb_core.c | ||
19 | +++ b/hw/net/igb_core.c | ||
20 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
21 | struct virtio_net_hdr *vhdr; | ||
22 | bool hasip4, hasip6; | ||
23 | EthL4HdrProto l4hdr_proto; | ||
24 | - uint32_t pkt_type; | ||
25 | |||
26 | *status_flags = E1000_RXD_STAT_DD; | ||
27 | |||
28 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
29 | trace_e1000e_rx_metadata_ack(); | ||
30 | } | ||
31 | |||
32 | - if (hasip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_DIS)) { | ||
33 | - trace_e1000e_rx_metadata_ipv6_filtering_disabled(); | ||
34 | - pkt_type = E1000_RXD_PKT_MAC; | ||
35 | - } else if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP || | ||
36 | - l4hdr_proto == ETH_L4_HDR_PROTO_UDP) { | ||
37 | - pkt_type = hasip4 ? E1000_RXD_PKT_IP4_XDP : E1000_RXD_PKT_IP6_XDP; | ||
38 | - } else if (hasip4 || hasip6) { | ||
39 | - pkt_type = hasip4 ? E1000_RXD_PKT_IP4 : E1000_RXD_PKT_IP6; | ||
40 | - } else { | ||
41 | - pkt_type = E1000_RXD_PKT_MAC; | ||
42 | - } | ||
43 | + if (pkt_info) { | ||
44 | + *pkt_info = rss_info->enabled ? rss_info->type : 0; | ||
45 | |||
46 | - trace_e1000e_rx_metadata_pkt_type(pkt_type); | ||
47 | + if (hasip4) { | ||
48 | + *pkt_info |= E1000_ADVRXD_PKT_IP4; | ||
49 | + } | ||
50 | |||
51 | - if (pkt_info) { | ||
52 | - if (rss_info->enabled) { | ||
53 | - *pkt_info = rss_info->type; | ||
54 | + if (hasip6) { | ||
55 | + *pkt_info |= E1000_ADVRXD_PKT_IP6; | ||
56 | } | ||
57 | |||
58 | - *pkt_info |= (pkt_type << 4); | ||
59 | - } else { | ||
60 | - *status_flags |= E1000_RXD_PKT_TYPE(pkt_type); | ||
61 | + switch (l4hdr_proto) { | ||
62 | + case ETH_L4_HDR_PROTO_TCP: | ||
63 | + *pkt_info |= E1000_ADVRXD_PKT_TCP; | ||
64 | + break; | ||
65 | + | ||
66 | + case ETH_L4_HDR_PROTO_UDP: | ||
67 | + *pkt_info |= E1000_ADVRXD_PKT_UDP; | ||
68 | + break; | ||
69 | + | ||
70 | + default: | ||
71 | + break; | ||
72 | + } | ||
73 | } | ||
74 | |||
75 | if (hdr_info) { | ||
76 | diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h | ||
77 | index XXXXXXX..XXXXXXX 100644 | ||
78 | --- a/hw/net/igb_regs.h | ||
79 | +++ b/hw/net/igb_regs.h | ||
80 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
81 | |||
82 | #define E1000_STATUS_NUM_VFS_SHIFT 14 | ||
83 | |||
84 | +#define E1000_ADVRXD_PKT_IP4 BIT(4) | ||
85 | +#define E1000_ADVRXD_PKT_IP6 BIT(6) | ||
86 | +#define E1000_ADVRXD_PKT_TCP BIT(8) | ||
87 | +#define E1000_ADVRXD_PKT_UDP BIT(9) | ||
88 | + | ||
89 | static inline uint8_t igb_ivar_entry_rx(uint8_t i) | ||
90 | { | ||
91 | return i < 8 ? i * 4 : (i - 8) * 4 + 2; | ||
92 | -- | ||
93 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | While the datasheet of e1000e says it checks CTRL.VME for tx VLAN | ||
4 | tagging, igb's datasheet has no such statements. It also says for | ||
5 | "CTRL.VLE": | ||
6 | > This register only affects the VLAN Strip in Rx it does not have any | ||
7 | > influence in the Tx path in the 82576. | ||
8 | (Appendix A. Changes from the 82575) | ||
9 | |||
10 | There is no "CTRL.VLE" so it is more likely that it is a mistake of | ||
11 | CTRL.VME. | ||
12 | |||
13 | Fixes: fba7c3b788 ("igb: respect VMVIR and VMOLR for VLAN") | ||
14 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
15 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
16 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
17 | --- | ||
18 | hw/net/igb_core.c | 2 +- | ||
19 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
20 | |||
21 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/hw/net/igb_core.c | ||
24 | +++ b/hw/net/igb_core.c | ||
25 | @@ -XXX,XX +XXX,XX @@ igb_tx_insert_vlan(IGBCore *core, uint16_t qn, struct igb_tx *tx, | ||
26 | } | ||
27 | } | ||
28 | |||
29 | - if (insert_vlan && e1000x_vlan_enabled(core->mac)) { | ||
30 | + if (insert_vlan) { | ||
31 | net_tx_pkt_setup_vlan_header_ex(tx->tx_pkt, vlan, | ||
32 | core->mac[VET] & 0xffff); | ||
33 | } | ||
34 | -- | ||
35 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | The datasheet says contradicting statements regarding ICR accesses so it | ||
4 | is not reliable to determine the behavior of ICR accesses. However, | ||
5 | e1000e does clear IMS bits when reading ICR accesses and Linux also | ||
6 | expects ICR accesses will clear IMS bits according to: | ||
7 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/igb/igb_main.c?h=v6.2#n8048 | ||
8 | |||
9 | Fixes: 3a977deebe ("Intrdocue igb device emulation") | ||
10 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
11 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
12 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
13 | --- | ||
14 | hw/net/igb_core.c | 8 ++++---- | ||
15 | 1 file changed, 4 insertions(+), 4 deletions(-) | ||
16 | |||
17 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/hw/net/igb_core.c | ||
20 | +++ b/hw/net/igb_core.c | ||
21 | @@ -XXX,XX +XXX,XX @@ igb_set_ims(IGBCore *core, int index, uint32_t val) | ||
22 | static void igb_commit_icr(IGBCore *core) | ||
23 | { | ||
24 | /* | ||
25 | - * If GPIE.NSICR = 0, then the copy of IAM to IMS will occur only if at | ||
26 | + * If GPIE.NSICR = 0, then the clear of IMS will occur only if at | ||
27 | * least one bit is set in the IMS and there is a true interrupt as | ||
28 | * reflected in ICR.INTA. | ||
29 | */ | ||
30 | if ((core->mac[GPIE] & E1000_GPIE_NSICR) || | ||
31 | (core->mac[IMS] && (core->mac[ICR] & E1000_ICR_INT_ASSERTED))) { | ||
32 | - igb_set_ims(core, IMS, core->mac[IAM]); | ||
33 | - } else { | ||
34 | - igb_update_interrupt_state(core); | ||
35 | + igb_clear_ims_bits(core, core->mac[IAM]); | ||
36 | } | ||
37 | + | ||
38 | + igb_update_interrupt_state(core); | ||
39 | } | ||
40 | |||
41 | static void igb_set_icr(IGBCore *core, int index, uint32_t val) | ||
42 | -- | ||
43 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | igb does not properly ensure the buffer passed to | ||
4 | net_rx_pkt_set_protocols() is contiguous for the entire L2/L3/L4 header. | ||
5 | Allow it to pass scattered data to net_rx_pkt_set_protocols(). | ||
6 | |||
7 | Fixes: 3a977deebe ("Intrdocue igb device emulation") | ||
8 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
9 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
10 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
11 | --- | ||
12 | hw/net/igb_core.c | 2 +- | ||
13 | hw/net/net_rx_pkt.c | 14 +++++--------- | ||
14 | hw/net/net_rx_pkt.h | 10 ++++++---- | ||
15 | hw/net/virtio-net.c | 7 +++++-- | ||
16 | hw/net/vmxnet3.c | 7 ++++++- | ||
17 | include/net/eth.h | 6 +++--- | ||
18 | net/eth.c | 18 ++++++++---------- | ||
19 | 7 files changed, 34 insertions(+), 30 deletions(-) | ||
20 | |||
21 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/hw/net/igb_core.c | ||
24 | +++ b/hw/net/igb_core.c | ||
25 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
26 | |||
27 | ehdr = PKT_GET_ETH_HDR(filter_buf); | ||
28 | net_rx_pkt_set_packet_type(core->rx_pkt, get_eth_packet_type(ehdr)); | ||
29 | - net_rx_pkt_set_protocols(core->rx_pkt, filter_buf, size); | ||
30 | + net_rx_pkt_set_protocols(core->rx_pkt, iov, iovcnt, iov_ofs); | ||
31 | |||
32 | queues = igb_receive_assign(core, ehdr, size, &rss_info, external_tx); | ||
33 | if (!queues) { | ||
34 | diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c | ||
35 | index XXXXXXX..XXXXXXX 100644 | ||
36 | --- a/hw/net/net_rx_pkt.c | ||
37 | +++ b/hw/net/net_rx_pkt.c | ||
38 | @@ -XXX,XX +XXX,XX @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt, | ||
39 | iov, iovcnt, ploff, pkt->tot_len); | ||
40 | } | ||
41 | |||
42 | - eth_get_protocols(pkt->vec, pkt->vec_len, &pkt->hasip4, &pkt->hasip6, | ||
43 | + eth_get_protocols(pkt->vec, pkt->vec_len, 0, &pkt->hasip4, &pkt->hasip6, | ||
44 | &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off, | ||
45 | &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info); | ||
46 | |||
47 | @@ -XXX,XX +XXX,XX @@ size_t net_rx_pkt_get_total_len(struct NetRxPkt *pkt) | ||
48 | return pkt->tot_len; | ||
49 | } | ||
50 | |||
51 | -void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data, | ||
52 | - size_t len) | ||
53 | +void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, | ||
54 | + const struct iovec *iov, size_t iovcnt, | ||
55 | + size_t iovoff) | ||
56 | { | ||
57 | - const struct iovec iov = { | ||
58 | - .iov_base = (void *)data, | ||
59 | - .iov_len = len | ||
60 | - }; | ||
61 | - | ||
62 | assert(pkt); | ||
63 | |||
64 | - eth_get_protocols(&iov, 1, &pkt->hasip4, &pkt->hasip6, | ||
65 | + eth_get_protocols(iov, iovcnt, iovoff, &pkt->hasip4, &pkt->hasip6, | ||
66 | &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off, | ||
67 | &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info); | ||
68 | } | ||
69 | diff --git a/hw/net/net_rx_pkt.h b/hw/net/net_rx_pkt.h | ||
70 | index XXXXXXX..XXXXXXX 100644 | ||
71 | --- a/hw/net/net_rx_pkt.h | ||
72 | +++ b/hw/net/net_rx_pkt.h | ||
73 | @@ -XXX,XX +XXX,XX @@ size_t net_rx_pkt_get_total_len(struct NetRxPkt *pkt); | ||
74 | * parse and set packet analysis results | ||
75 | * | ||
76 | * @pkt: packet | ||
77 | - * @data: pointer to the data buffer to be parsed | ||
78 | - * @len: data length | ||
79 | + * @iov: received data scatter-gather list | ||
80 | + * @iovcnt: number of elements in iov | ||
81 | + * @iovoff: data start offset in the iov | ||
82 | * | ||
83 | */ | ||
84 | -void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data, | ||
85 | - size_t len); | ||
86 | +void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, | ||
87 | + const struct iovec *iov, size_t iovcnt, | ||
88 | + size_t iovoff); | ||
89 | |||
90 | /** | ||
91 | * fetches packet analysis results | ||
92 | diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c | ||
93 | index XXXXXXX..XXXXXXX 100644 | ||
94 | --- a/hw/net/virtio-net.c | ||
95 | +++ b/hw/net/virtio-net.c | ||
96 | @@ -XXX,XX +XXX,XX @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf, | ||
97 | VIRTIO_NET_HASH_REPORT_UDPv6, | ||
98 | VIRTIO_NET_HASH_REPORT_UDPv6_EX | ||
99 | }; | ||
100 | + struct iovec iov = { | ||
101 | + .iov_base = (void *)buf, | ||
102 | + .iov_len = size | ||
103 | + }; | ||
104 | |||
105 | - net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len, | ||
106 | - size - n->host_hdr_len); | ||
107 | + net_rx_pkt_set_protocols(pkt, &iov, 1, n->host_hdr_len); | ||
108 | net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto); | ||
109 | net_hash_type = virtio_net_get_hash_type(hasip4, hasip6, l4hdr_proto, | ||
110 | n->rss_data.hash_types); | ||
111 | diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c | ||
112 | index XXXXXXX..XXXXXXX 100644 | ||
113 | --- a/hw/net/vmxnet3.c | ||
114 | +++ b/hw/net/vmxnet3.c | ||
115 | @@ -XXX,XX +XXX,XX @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size) | ||
116 | get_eth_packet_type(PKT_GET_ETH_HDR(buf))); | ||
117 | |||
118 | if (vmxnet3_rx_filter_may_indicate(s, buf, size)) { | ||
119 | - net_rx_pkt_set_protocols(s->rx_pkt, buf, size); | ||
120 | + struct iovec iov = { | ||
121 | + .iov_base = (void *)buf, | ||
122 | + .iov_len = size | ||
123 | + }; | ||
124 | + | ||
125 | + net_rx_pkt_set_protocols(s->rx_pkt, &iov, 1, 0); | ||
126 | vmxnet3_rx_need_csum_calculate(s->rx_pkt, buf, size); | ||
127 | net_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping); | ||
128 | bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1; | ||
129 | diff --git a/include/net/eth.h b/include/net/eth.h | ||
130 | index XXXXXXX..XXXXXXX 100644 | ||
131 | --- a/include/net/eth.h | ||
132 | +++ b/include/net/eth.h | ||
133 | @@ -XXX,XX +XXX,XX @@ eth_get_l2_hdr_length(const void *p) | ||
134 | } | ||
135 | |||
136 | static inline uint32_t | ||
137 | -eth_get_l2_hdr_length_iov(const struct iovec *iov, int iovcnt) | ||
138 | +eth_get_l2_hdr_length_iov(const struct iovec *iov, size_t iovcnt, size_t iovoff) | ||
139 | { | ||
140 | uint8_t p[sizeof(struct eth_header) + sizeof(struct vlan_header)]; | ||
141 | - size_t copied = iov_to_buf(iov, iovcnt, 0, p, ARRAY_SIZE(p)); | ||
142 | + size_t copied = iov_to_buf(iov, iovcnt, iovoff, p, ARRAY_SIZE(p)); | ||
143 | |||
144 | if (copied < ARRAY_SIZE(p)) { | ||
145 | return copied; | ||
146 | @@ -XXX,XX +XXX,XX @@ typedef struct eth_l4_hdr_info_st { | ||
147 | bool has_tcp_data; | ||
148 | } eth_l4_hdr_info; | ||
149 | |||
150 | -void eth_get_protocols(const struct iovec *iov, int iovcnt, | ||
151 | +void eth_get_protocols(const struct iovec *iov, size_t iovcnt, size_t iovoff, | ||
152 | bool *hasip4, bool *hasip6, | ||
153 | size_t *l3hdr_off, | ||
154 | size_t *l4hdr_off, | ||
155 | diff --git a/net/eth.c b/net/eth.c | ||
156 | index XXXXXXX..XXXXXXX 100644 | ||
157 | --- a/net/eth.c | ||
158 | +++ b/net/eth.c | ||
159 | @@ -XXX,XX +XXX,XX @@ _eth_tcp_has_data(bool is_ip4, | ||
160 | return l4len > TCP_HEADER_DATA_OFFSET(tcp); | ||
161 | } | ||
162 | |||
163 | -void eth_get_protocols(const struct iovec *iov, int iovcnt, | ||
164 | +void eth_get_protocols(const struct iovec *iov, size_t iovcnt, size_t iovoff, | ||
165 | bool *hasip4, bool *hasip6, | ||
166 | size_t *l3hdr_off, | ||
167 | size_t *l4hdr_off, | ||
168 | @@ -XXX,XX +XXX,XX @@ void eth_get_protocols(const struct iovec *iov, int iovcnt, | ||
169 | { | ||
170 | int proto; | ||
171 | bool fragment = false; | ||
172 | - size_t l2hdr_len = eth_get_l2_hdr_length_iov(iov, iovcnt); | ||
173 | size_t input_size = iov_size(iov, iovcnt); | ||
174 | size_t copied; | ||
175 | uint8_t ip_p; | ||
176 | |||
177 | *hasip4 = *hasip6 = false; | ||
178 | + *l3hdr_off = iovoff + eth_get_l2_hdr_length_iov(iov, iovcnt, iovoff); | ||
179 | l4hdr_info->proto = ETH_L4_HDR_PROTO_INVALID; | ||
180 | |||
181 | - proto = eth_get_l3_proto(iov, iovcnt, l2hdr_len); | ||
182 | - | ||
183 | - *l3hdr_off = l2hdr_len; | ||
184 | + proto = eth_get_l3_proto(iov, iovcnt, *l3hdr_off); | ||
185 | |||
186 | if (proto == ETH_P_IP) { | ||
187 | struct ip_header *iphdr = &ip4hdr_info->ip4_hdr; | ||
188 | |||
189 | - if (input_size < l2hdr_len) { | ||
190 | + if (input_size < *l3hdr_off) { | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | - copied = iov_to_buf(iov, iovcnt, l2hdr_len, iphdr, sizeof(*iphdr)); | ||
195 | + copied = iov_to_buf(iov, iovcnt, *l3hdr_off, iphdr, sizeof(*iphdr)); | ||
196 | if (copied < sizeof(*iphdr) || | ||
197 | IP_HEADER_VERSION(iphdr) != IP_HEADER_VERSION_4) { | ||
198 | return; | ||
199 | @@ -XXX,XX +XXX,XX @@ void eth_get_protocols(const struct iovec *iov, int iovcnt, | ||
200 | *hasip4 = true; | ||
201 | ip_p = iphdr->ip_p; | ||
202 | ip4hdr_info->fragment = IP4_IS_FRAGMENT(iphdr); | ||
203 | - *l4hdr_off = l2hdr_len + IP_HDR_GET_LEN(iphdr); | ||
204 | + *l4hdr_off = *l3hdr_off + IP_HDR_GET_LEN(iphdr); | ||
205 | |||
206 | fragment = ip4hdr_info->fragment; | ||
207 | } else if (proto == ETH_P_IPV6) { | ||
208 | - if (!eth_parse_ipv6_hdr(iov, iovcnt, l2hdr_len, ip6hdr_info)) { | ||
209 | + if (!eth_parse_ipv6_hdr(iov, iovcnt, *l3hdr_off, ip6hdr_info)) { | ||
210 | return; | ||
211 | } | ||
212 | |||
213 | *hasip6 = true; | ||
214 | ip_p = ip6hdr_info->l4proto; | ||
215 | - *l4hdr_off = l2hdr_len + ip6hdr_info->full_hdr_len; | ||
216 | + *l4hdr_off = *l3hdr_off + ip6hdr_info->full_hdr_len; | ||
217 | fragment = ip6hdr_info->fragment; | ||
218 | } else { | ||
219 | return; | ||
220 | -- | ||
221 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | e1000e_receive_internal() used to check the iov length to determine | ||
4 | copy the iovs to a contiguous buffer, but the check is flawed in two | ||
5 | ways: | ||
6 | - It does not ensure that iovcnt > 0. | ||
7 | - It does not take virtio-net header into consideration. | ||
8 | |||
9 | The size of this copy is just 18 octets, which can be even less than | ||
10 | the code size required for checks. This (wrong) optimization is probably | ||
11 | not worth so just remove it. | ||
12 | |||
13 | Fixes: 6f3fbe4ed0 ("net: Introduce e1000e device emulation") | ||
14 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
15 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
16 | --- | ||
17 | hw/net/e1000e_core.c | 26 ++++++++++---------------- | ||
18 | 1 file changed, 10 insertions(+), 16 deletions(-) | ||
19 | |||
20 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/hw/net/e1000e_core.c | ||
23 | +++ b/hw/net/e1000e_core.c | ||
24 | @@ -XXX,XX +XXX,XX @@ static ssize_t | ||
25 | e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt, | ||
26 | bool has_vnet) | ||
27 | { | ||
28 | - static const int maximum_ethernet_hdr_len = (ETH_HLEN + 4); | ||
29 | - | ||
30 | uint32_t n = 0; | ||
31 | - uint8_t min_buf[ETH_ZLEN]; | ||
32 | + uint8_t buf[ETH_ZLEN]; | ||
33 | struct iovec min_iov; | ||
34 | - uint8_t *filter_buf; | ||
35 | size_t size, orig_size; | ||
36 | size_t iov_ofs = 0; | ||
37 | E1000E_RxRing rxr; | ||
38 | @@ -XXX,XX +XXX,XX @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt, | ||
39 | net_rx_pkt_unset_vhdr(core->rx_pkt); | ||
40 | } | ||
41 | |||
42 | - filter_buf = iov->iov_base + iov_ofs; | ||
43 | orig_size = iov_size(iov, iovcnt); | ||
44 | size = orig_size - iov_ofs; | ||
45 | |||
46 | /* Pad to minimum Ethernet frame length */ | ||
47 | - if (size < sizeof(min_buf)) { | ||
48 | - iov_to_buf(iov, iovcnt, iov_ofs, min_buf, size); | ||
49 | - memset(&min_buf[size], 0, sizeof(min_buf) - size); | ||
50 | + if (size < sizeof(buf)) { | ||
51 | + iov_to_buf(iov, iovcnt, iov_ofs, buf, size); | ||
52 | + memset(&buf[size], 0, sizeof(buf) - size); | ||
53 | e1000x_inc_reg_if_not_full(core->mac, RUC); | ||
54 | - min_iov.iov_base = filter_buf = min_buf; | ||
55 | - min_iov.iov_len = size = sizeof(min_buf); | ||
56 | + min_iov.iov_base = buf; | ||
57 | + min_iov.iov_len = size = sizeof(buf); | ||
58 | iovcnt = 1; | ||
59 | iov = &min_iov; | ||
60 | iov_ofs = 0; | ||
61 | - } else if (iov->iov_len < maximum_ethernet_hdr_len) { | ||
62 | - /* This is very unlikely, but may happen. */ | ||
63 | - iov_to_buf(iov, iovcnt, iov_ofs, min_buf, maximum_ethernet_hdr_len); | ||
64 | - filter_buf = min_buf; | ||
65 | + } else { | ||
66 | + iov_to_buf(iov, iovcnt, iov_ofs, buf, ETH_HLEN + 4); | ||
67 | } | ||
68 | |||
69 | /* Discard oversized packets if !LPE and !SBP. */ | ||
70 | @@ -XXX,XX +XXX,XX @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt, | ||
71 | } | ||
72 | |||
73 | net_rx_pkt_set_packet_type(core->rx_pkt, | ||
74 | - get_eth_packet_type(PKT_GET_ETH_HDR(filter_buf))); | ||
75 | + get_eth_packet_type(PKT_GET_ETH_HDR(buf))); | ||
76 | |||
77 | - if (!e1000e_receive_filter(core, filter_buf, size)) { | ||
78 | + if (!e1000e_receive_filter(core, buf, size)) { | ||
79 | trace_e1000e_rx_flt_dropped(); | ||
80 | return orig_size; | ||
81 | } | ||
82 | -- | ||
83 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | igb_receive_internal() used to check the iov length to determine | ||
4 | copy the iovs to a contiguous buffer, but the check is flawed in two | ||
5 | ways: | ||
6 | - It does not ensure that iovcnt > 0. | ||
7 | - It does not take virtio-net header into consideration. | ||
8 | |||
9 | The size of this copy is just 22 octets, which can be even less than | ||
10 | the code size required for checks. This (wrong) optimization is probably | ||
11 | not worth so just remove it. Removing this also allows igb to assume | ||
12 | aligned accesses for the ethernet header. | ||
13 | |||
14 | Fixes: 3a977deebe ("Intrdocue igb device emulation") | ||
15 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
16 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
17 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
18 | --- | ||
19 | hw/net/igb_core.c | 43 +++++++++++++++++++++++-------------------- | ||
20 | 1 file changed, 23 insertions(+), 20 deletions(-) | ||
21 | |||
22 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/hw/net/igb_core.c | ||
25 | +++ b/hw/net/igb_core.c | ||
26 | @@ -XXX,XX +XXX,XX @@ typedef struct IGBTxPktVmdqCallbackContext { | ||
27 | NetClientState *nc; | ||
28 | } IGBTxPktVmdqCallbackContext; | ||
29 | |||
30 | +typedef struct L2Header { | ||
31 | + struct eth_header eth; | ||
32 | + struct vlan_header vlan; | ||
33 | +} L2Header; | ||
34 | + | ||
35 | static ssize_t | ||
36 | igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
37 | bool has_vnet, bool *external_tx); | ||
38 | @@ -XXX,XX +XXX,XX @@ igb_rx_is_oversized(IGBCore *core, uint16_t qn, size_t size) | ||
39 | return size > (lpe ? max_ethernet_lpe_size : max_ethernet_vlan_size); | ||
40 | } | ||
41 | |||
42 | -static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr, | ||
43 | +static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
44 | size_t size, E1000E_RSSInfo *rss_info, | ||
45 | bool *external_tx) | ||
46 | { | ||
47 | static const int ta_shift[] = { 4, 3, 2, 0 }; | ||
48 | + const struct eth_header *ehdr = &l2_header->eth; | ||
49 | uint32_t f, ra[2], *macp, rctl = core->mac[RCTL]; | ||
50 | uint16_t queues = 0; | ||
51 | uint16_t oversized = 0; | ||
52 | - uint16_t vid = lduw_be_p(&PKT_GET_VLAN_HDR(ehdr)->h_tci) & VLAN_VID_MASK; | ||
53 | + uint16_t vid = be16_to_cpu(l2_header->vlan.h_tci) & VLAN_VID_MASK; | ||
54 | bool accepted = false; | ||
55 | int i; | ||
56 | |||
57 | @@ -XXX,XX +XXX,XX @@ static ssize_t | ||
58 | igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
59 | bool has_vnet, bool *external_tx) | ||
60 | { | ||
61 | - static const int maximum_ethernet_hdr_len = (ETH_HLEN + 4); | ||
62 | - | ||
63 | uint16_t queues = 0; | ||
64 | uint32_t n = 0; | ||
65 | - uint8_t min_buf[ETH_ZLEN]; | ||
66 | + union { | ||
67 | + L2Header l2_header; | ||
68 | + uint8_t octets[ETH_ZLEN]; | ||
69 | + } buf; | ||
70 | struct iovec min_iov; | ||
71 | - struct eth_header *ehdr; | ||
72 | - uint8_t *filter_buf; | ||
73 | size_t size, orig_size; | ||
74 | size_t iov_ofs = 0; | ||
75 | E1000E_RxRing rxr; | ||
76 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
77 | net_rx_pkt_unset_vhdr(core->rx_pkt); | ||
78 | } | ||
79 | |||
80 | - filter_buf = iov->iov_base + iov_ofs; | ||
81 | orig_size = iov_size(iov, iovcnt); | ||
82 | size = orig_size - iov_ofs; | ||
83 | |||
84 | /* Pad to minimum Ethernet frame length */ | ||
85 | - if (size < sizeof(min_buf)) { | ||
86 | - iov_to_buf(iov, iovcnt, iov_ofs, min_buf, size); | ||
87 | - memset(&min_buf[size], 0, sizeof(min_buf) - size); | ||
88 | + if (size < sizeof(buf)) { | ||
89 | + iov_to_buf(iov, iovcnt, iov_ofs, &buf, size); | ||
90 | + memset(&buf.octets[size], 0, sizeof(buf) - size); | ||
91 | e1000x_inc_reg_if_not_full(core->mac, RUC); | ||
92 | - min_iov.iov_base = filter_buf = min_buf; | ||
93 | - min_iov.iov_len = size = sizeof(min_buf); | ||
94 | + min_iov.iov_base = &buf; | ||
95 | + min_iov.iov_len = size = sizeof(buf); | ||
96 | iovcnt = 1; | ||
97 | iov = &min_iov; | ||
98 | iov_ofs = 0; | ||
99 | - } else if (iov->iov_len < maximum_ethernet_hdr_len) { | ||
100 | - /* This is very unlikely, but may happen. */ | ||
101 | - iov_to_buf(iov, iovcnt, iov_ofs, min_buf, maximum_ethernet_hdr_len); | ||
102 | - filter_buf = min_buf; | ||
103 | + } else { | ||
104 | + iov_to_buf(iov, iovcnt, iov_ofs, &buf, sizeof(buf.l2_header)); | ||
105 | } | ||
106 | |||
107 | /* Discard oversized packets if !LPE and !SBP. */ | ||
108 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
109 | return orig_size; | ||
110 | } | ||
111 | |||
112 | - ehdr = PKT_GET_ETH_HDR(filter_buf); | ||
113 | - net_rx_pkt_set_packet_type(core->rx_pkt, get_eth_packet_type(ehdr)); | ||
114 | + net_rx_pkt_set_packet_type(core->rx_pkt, | ||
115 | + get_eth_packet_type(&buf.l2_header.eth)); | ||
116 | net_rx_pkt_set_protocols(core->rx_pkt, iov, iovcnt, iov_ofs); | ||
117 | |||
118 | - queues = igb_receive_assign(core, ehdr, size, &rss_info, external_tx); | ||
119 | + queues = igb_receive_assign(core, &buf.l2_header, size, | ||
120 | + &rss_info, external_tx); | ||
121 | if (!queues) { | ||
122 | trace_e1000e_rx_flt_dropped(); | ||
123 | return orig_size; | ||
124 | -- | ||
125 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Fixes: 9f95111474 ("tests/avocado: re-factor igb test to avoid timeouts") | ||
4 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
6 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
7 | --- | ||
8 | MAINTAINERS | 2 +- | ||
9 | docs/system/devices/igb.rst | 2 +- | ||
10 | scripts/ci/org.centos/stream/8/x86_64/test-avocado | 2 +- | ||
11 | 3 files changed, 3 insertions(+), 3 deletions(-) | ||
12 | |||
13 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/MAINTAINERS | ||
16 | +++ b/MAINTAINERS | ||
17 | @@ -XXX,XX +XXX,XX @@ R: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
18 | S: Maintained | ||
19 | F: docs/system/devices/igb.rst | ||
20 | F: hw/net/igb* | ||
21 | -F: tests/avocado/igb.py | ||
22 | +F: tests/avocado/netdev-ethtool.py | ||
23 | F: tests/qtest/igb-test.c | ||
24 | F: tests/qtest/libqos/igb.c | ||
25 | |||
26 | diff --git a/docs/system/devices/igb.rst b/docs/system/devices/igb.rst | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/docs/system/devices/igb.rst | ||
29 | +++ b/docs/system/devices/igb.rst | ||
30 | @@ -XXX,XX +XXX,XX @@ Avocado test and can be ran with the following command: | ||
31 | |||
32 | .. code:: shell | ||
33 | |||
34 | - make check-avocado AVOCADO_TESTS=tests/avocado/igb.py | ||
35 | + make check-avocado AVOCADO_TESTS=tests/avocado/netdev-ethtool.py | ||
36 | |||
37 | References | ||
38 | ========== | ||
39 | diff --git a/scripts/ci/org.centos/stream/8/x86_64/test-avocado b/scripts/ci/org.centos/stream/8/x86_64/test-avocado | ||
40 | index XXXXXXX..XXXXXXX 100755 | ||
41 | --- a/scripts/ci/org.centos/stream/8/x86_64/test-avocado | ||
42 | +++ b/scripts/ci/org.centos/stream/8/x86_64/test-avocado | ||
43 | @@ -XXX,XX +XXX,XX @@ make get-vm-images | ||
44 | tests/avocado/cpu_queries.py:QueryCPUModelExpansion.test \ | ||
45 | tests/avocado/empty_cpu_model.py:EmptyCPUModel.test \ | ||
46 | tests/avocado/hotplug_cpu.py:HotPlugCPU.test \ | ||
47 | - tests/avocado/igb.py:IGB.test \ | ||
48 | + tests/avocado/netdev-ethtool.py:NetDevEthtool.test_igb_nomsi \ | ||
49 | tests/avocado/info_usernet.py:InfoUsernet.test_hostfwd \ | ||
50 | tests/avocado/intel_iommu.py:IntelIOMMU.test_intel_iommu \ | ||
51 | tests/avocado/intel_iommu.py:IntelIOMMU.test_intel_iommu_pt \ | ||
52 | -- | ||
53 | 2.7.4 | ||
54 | |||
55 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
5 | --- | ||
6 | tests/avocado/netdev-ethtool.py | 1 - | ||
7 | 1 file changed, 1 deletion(-) | ||
8 | |||
9 | diff --git a/tests/avocado/netdev-ethtool.py b/tests/avocado/netdev-ethtool.py | ||
10 | index XXXXXXX..XXXXXXX 100644 | ||
11 | --- a/tests/avocado/netdev-ethtool.py | ||
12 | +++ b/tests/avocado/netdev-ethtool.py | ||
13 | @@ -XXX,XX +XXX,XX @@ | ||
14 | |||
15 | from avocado import skip | ||
16 | from avocado_qemu import QemuSystemTest | ||
17 | -from avocado_qemu import exec_command, exec_command_and_wait_for_pattern | ||
18 | from avocado_qemu import wait_for_console_pattern | ||
19 | |||
20 | class NetDevEthtool(QemuSystemTest): | ||
21 | -- | ||
22 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | It is unlikely to find more bugs with KVM so remove test_igb_nomsi_kvm | ||
4 | to save time to run it. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
8 | Acked-by: Alex Bennée <alex.bennee@linaro.org> | ||
9 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
10 | --- | ||
11 | tests/avocado/netdev-ethtool.py | 12 +----------- | ||
12 | 1 file changed, 1 insertion(+), 11 deletions(-) | ||
13 | |||
14 | diff --git a/tests/avocado/netdev-ethtool.py b/tests/avocado/netdev-ethtool.py | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/tests/avocado/netdev-ethtool.py | ||
17 | +++ b/tests/avocado/netdev-ethtool.py | ||
18 | @@ -XXX,XX +XXX,XX @@ def get_asset(self, name, sha1): | ||
19 | # URL into a unique one | ||
20 | return self.fetch_asset(name=name, locations=(url), asset_hash=sha1) | ||
21 | |||
22 | - def common_test_code(self, netdev, extra_args=None, kvm=False): | ||
23 | + def common_test_code(self, netdev, extra_args=None): | ||
24 | |||
25 | # This custom kernel has drivers for all the supported network | ||
26 | # devices we can emulate in QEMU | ||
27 | @@ -XXX,XX +XXX,XX @@ def common_test_code(self, netdev, extra_args=None, kvm=False): | ||
28 | '-drive', drive, | ||
29 | '-device', netdev) | ||
30 | |||
31 | - if kvm: | ||
32 | - self.vm.add_args('-accel', 'kvm') | ||
33 | - | ||
34 | self.vm.set_console(console_index=0) | ||
35 | self.vm.launch() | ||
36 | |||
37 | @@ -XXX,XX +XXX,XX @@ def test_igb_nomsi(self): | ||
38 | """ | ||
39 | self.common_test_code("igb", "pci=nomsi") | ||
40 | |||
41 | - def test_igb_nomsi_kvm(self): | ||
42 | - """ | ||
43 | - :avocado: tags=device:igb | ||
44 | - """ | ||
45 | - self.require_accelerator('kvm') | ||
46 | - self.common_test_code("igb", "pci=nomsi", True) | ||
47 | - | ||
48 | # It seems the other popular cards we model in QEMU currently fail | ||
49 | # the pattern test with: | ||
50 | # | ||
51 | -- | ||
52 | 2.7.4 | ||
53 | |||
54 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | This function is not used. | ||
4 | |||
5 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
6 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
7 | --- | ||
8 | hw/net/net_rx_pkt.c | 5 ----- | ||
9 | hw/net/net_rx_pkt.h | 9 --------- | ||
10 | 2 files changed, 14 deletions(-) | ||
11 | |||
12 | diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/net/net_rx_pkt.c | ||
15 | +++ b/hw/net/net_rx_pkt.c | ||
16 | @@ -XXX,XX +XXX,XX @@ eth_ip4_hdr_info *net_rx_pkt_get_ip4_info(struct NetRxPkt *pkt) | ||
17 | return &pkt->ip4hdr_info; | ||
18 | } | ||
19 | |||
20 | -eth_l4_hdr_info *net_rx_pkt_get_l4_info(struct NetRxPkt *pkt) | ||
21 | -{ | ||
22 | - return &pkt->l4hdr_info; | ||
23 | -} | ||
24 | - | ||
25 | static inline void | ||
26 | _net_rx_rss_add_chunk(uint8_t *rss_input, size_t *bytes_written, | ||
27 | void *ptr, size_t size) | ||
28 | diff --git a/hw/net/net_rx_pkt.h b/hw/net/net_rx_pkt.h | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/hw/net/net_rx_pkt.h | ||
31 | +++ b/hw/net/net_rx_pkt.h | ||
32 | @@ -XXX,XX +XXX,XX @@ eth_ip6_hdr_info *net_rx_pkt_get_ip6_info(struct NetRxPkt *pkt); | ||
33 | */ | ||
34 | eth_ip4_hdr_info *net_rx_pkt_get_ip4_info(struct NetRxPkt *pkt); | ||
35 | |||
36 | -/** | ||
37 | - * fetches L4 header analysis results | ||
38 | - * | ||
39 | - * Return: pointer to analysis results structure which is stored in internal | ||
40 | - * packet area. | ||
41 | - * | ||
42 | - */ | ||
43 | -eth_l4_hdr_info *net_rx_pkt_get_l4_info(struct NetRxPkt *pkt); | ||
44 | - | ||
45 | typedef enum { | ||
46 | NetPktRssIpV4, | ||
47 | NetPktRssIpV4Tcp, | ||
48 | -- | ||
49 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | The old eth_setup_vlan_headers has no user so remove it and rename | ||
4 | eth_setup_vlan_headers_ex. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
8 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
9 | --- | ||
10 | hw/net/net_tx_pkt.c | 2 +- | ||
11 | include/net/eth.h | 9 +-------- | ||
12 | net/eth.c | 2 +- | ||
13 | 3 files changed, 3 insertions(+), 10 deletions(-) | ||
14 | |||
15 | diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/net/net_tx_pkt.c | ||
18 | +++ b/hw/net/net_tx_pkt.c | ||
19 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt, | ||
20 | bool is_new; | ||
21 | assert(pkt); | ||
22 | |||
23 | - eth_setup_vlan_headers_ex(pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_base, | ||
24 | + eth_setup_vlan_headers(pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_base, | ||
25 | vlan, vlan_ethtype, &is_new); | ||
26 | |||
27 | /* update l2hdrlen */ | ||
28 | diff --git a/include/net/eth.h b/include/net/eth.h | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/include/net/eth.h | ||
31 | +++ b/include/net/eth.h | ||
32 | @@ -XXX,XX +XXX,XX @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
33 | uint16_t | ||
34 | eth_get_l3_proto(const struct iovec *l2hdr_iov, int iovcnt, size_t l2hdr_len); | ||
35 | |||
36 | -void eth_setup_vlan_headers_ex(struct eth_header *ehdr, uint16_t vlan_tag, | ||
37 | +void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, | ||
38 | uint16_t vlan_ethtype, bool *is_new); | ||
39 | |||
40 | -static inline void | ||
41 | -eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, | ||
42 | - bool *is_new) | ||
43 | -{ | ||
44 | - eth_setup_vlan_headers_ex(ehdr, vlan_tag, ETH_P_VLAN, is_new); | ||
45 | -} | ||
46 | - | ||
47 | |||
48 | uint8_t eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto); | ||
49 | |||
50 | diff --git a/net/eth.c b/net/eth.c | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/net/eth.c | ||
53 | +++ b/net/eth.c | ||
54 | @@ -XXX,XX +XXX,XX @@ | ||
55 | #include "net/checksum.h" | ||
56 | #include "net/tap.h" | ||
57 | |||
58 | -void eth_setup_vlan_headers_ex(struct eth_header *ehdr, uint16_t vlan_tag, | ||
59 | +void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, | ||
60 | uint16_t vlan_ethtype, bool *is_new) | ||
61 | { | ||
62 | struct vlan_header *vhdr = PKT_GET_VLAN_HDR(ehdr); | ||
63 | -- | ||
64 | 2.7.4 | ||
65 | |||
66 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | This saves some code and enables tracepoint for e1000's VLAN filtering. | ||
4 | |||
5 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
6 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
8 | --- | ||
9 | hw/net/e1000.c | 35 +++++------------------------------ | ||
10 | hw/net/e1000e_core.c | 47 +++++------------------------------------------ | ||
11 | hw/net/e1000x_common.c | 44 ++++++++++++++++++++++++++++++++++++++------ | ||
12 | hw/net/e1000x_common.h | 4 +++- | ||
13 | hw/net/igb_core.c | 41 +++-------------------------------------- | ||
14 | hw/net/trace-events | 4 ++-- | ||
15 | 6 files changed, 56 insertions(+), 119 deletions(-) | ||
16 | |||
17 | diff --git a/hw/net/e1000.c b/hw/net/e1000.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/hw/net/e1000.c | ||
20 | +++ b/hw/net/e1000.c | ||
21 | @@ -XXX,XX +XXX,XX @@ start_xmit(E1000State *s) | ||
22 | } | ||
23 | |||
24 | static int | ||
25 | -receive_filter(E1000State *s, const uint8_t *buf, int size) | ||
26 | +receive_filter(E1000State *s, const void *buf) | ||
27 | { | ||
28 | - uint32_t rctl = s->mac_reg[RCTL]; | ||
29 | - int isbcast = is_broadcast_ether_addr(buf); | ||
30 | - int ismcast = is_multicast_ether_addr(buf); | ||
31 | - | ||
32 | - if (e1000x_is_vlan_packet(buf, le16_to_cpu(s->mac_reg[VET])) && | ||
33 | - e1000x_vlan_rx_filter_enabled(s->mac_reg)) { | ||
34 | - uint16_t vid = lduw_be_p(&PKT_GET_VLAN_HDR(buf)->h_tci); | ||
35 | - uint32_t vfta = | ||
36 | - ldl_le_p((uint32_t *)(s->mac_reg + VFTA) + | ||
37 | - ((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK)); | ||
38 | - if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) { | ||
39 | - return 0; | ||
40 | - } | ||
41 | - } | ||
42 | - | ||
43 | - if (!isbcast && !ismcast && (rctl & E1000_RCTL_UPE)) { /* promiscuous ucast */ | ||
44 | - return 1; | ||
45 | - } | ||
46 | - | ||
47 | - if (ismcast && (rctl & E1000_RCTL_MPE)) { /* promiscuous mcast */ | ||
48 | - return 1; | ||
49 | - } | ||
50 | - | ||
51 | - if (isbcast && (rctl & E1000_RCTL_BAM)) { /* broadcast enabled */ | ||
52 | - return 1; | ||
53 | - } | ||
54 | - | ||
55 | - return e1000x_rx_group_filter(s->mac_reg, buf); | ||
56 | + return (!e1000x_is_vlan_packet(buf, s->mac_reg[VET]) || | ||
57 | + e1000x_rx_vlan_filter(s->mac_reg, PKT_GET_VLAN_HDR(buf))) && | ||
58 | + e1000x_rx_group_filter(s->mac_reg, buf); | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | @@ -XXX,XX +XXX,XX @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) | ||
63 | return size; | ||
64 | } | ||
65 | |||
66 | - if (!receive_filter(s, filter_buf, size)) { | ||
67 | + if (!receive_filter(s, filter_buf)) { | ||
68 | return size; | ||
69 | } | ||
70 | |||
71 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/hw/net/e1000e_core.c | ||
74 | +++ b/hw/net/e1000e_core.c | ||
75 | @@ -XXX,XX +XXX,XX @@ e1000e_rx_l4_cso_enabled(E1000ECore *core) | ||
76 | } | ||
77 | |||
78 | static bool | ||
79 | -e1000e_receive_filter(E1000ECore *core, const uint8_t *buf, int size) | ||
80 | +e1000e_receive_filter(E1000ECore *core, const void *buf) | ||
81 | { | ||
82 | - uint32_t rctl = core->mac[RCTL]; | ||
83 | - | ||
84 | - if (e1000x_is_vlan_packet(buf, core->mac[VET]) && | ||
85 | - e1000x_vlan_rx_filter_enabled(core->mac)) { | ||
86 | - uint16_t vid = lduw_be_p(&PKT_GET_VLAN_HDR(buf)->h_tci); | ||
87 | - uint32_t vfta = | ||
88 | - ldl_le_p((uint32_t *)(core->mac + VFTA) + | ||
89 | - ((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK)); | ||
90 | - if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) { | ||
91 | - trace_e1000e_rx_flt_vlan_mismatch(vid); | ||
92 | - return false; | ||
93 | - } else { | ||
94 | - trace_e1000e_rx_flt_vlan_match(vid); | ||
95 | - } | ||
96 | - } | ||
97 | - | ||
98 | - switch (net_rx_pkt_get_packet_type(core->rx_pkt)) { | ||
99 | - case ETH_PKT_UCAST: | ||
100 | - if (rctl & E1000_RCTL_UPE) { | ||
101 | - return true; /* promiscuous ucast */ | ||
102 | - } | ||
103 | - break; | ||
104 | - | ||
105 | - case ETH_PKT_BCAST: | ||
106 | - if (rctl & E1000_RCTL_BAM) { | ||
107 | - return true; /* broadcast enabled */ | ||
108 | - } | ||
109 | - break; | ||
110 | - | ||
111 | - case ETH_PKT_MCAST: | ||
112 | - if (rctl & E1000_RCTL_MPE) { | ||
113 | - return true; /* promiscuous mcast */ | ||
114 | - } | ||
115 | - break; | ||
116 | - | ||
117 | - default: | ||
118 | - g_assert_not_reached(); | ||
119 | - } | ||
120 | - | ||
121 | - return e1000x_rx_group_filter(core->mac, buf); | ||
122 | + return (!e1000x_is_vlan_packet(buf, core->mac[VET]) || | ||
123 | + e1000x_rx_vlan_filter(core->mac, PKT_GET_VLAN_HDR(buf))) && | ||
124 | + e1000x_rx_group_filter(core->mac, buf); | ||
125 | } | ||
126 | |||
127 | static inline void | ||
128 | @@ -XXX,XX +XXX,XX @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt, | ||
129 | net_rx_pkt_set_packet_type(core->rx_pkt, | ||
130 | get_eth_packet_type(PKT_GET_ETH_HDR(buf))); | ||
131 | |||
132 | - if (!e1000e_receive_filter(core, buf, size)) { | ||
133 | + if (!e1000e_receive_filter(core, buf)) { | ||
134 | trace_e1000e_rx_flt_dropped(); | ||
135 | return orig_size; | ||
136 | } | ||
137 | diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c | ||
138 | index XXXXXXX..XXXXXXX 100644 | ||
139 | --- a/hw/net/e1000x_common.c | ||
140 | +++ b/hw/net/e1000x_common.c | ||
141 | @@ -XXX,XX +XXX,XX @@ bool e1000x_is_vlan_packet(const void *buf, uint16_t vet) | ||
142 | return res; | ||
143 | } | ||
144 | |||
145 | -bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf) | ||
146 | +bool e1000x_rx_vlan_filter(uint32_t *mac, const struct vlan_header *vhdr) | ||
147 | +{ | ||
148 | + if (e1000x_vlan_rx_filter_enabled(mac)) { | ||
149 | + uint16_t vid = lduw_be_p(&vhdr->h_tci); | ||
150 | + uint32_t vfta = | ||
151 | + ldl_le_p((uint32_t *)(mac + VFTA) + | ||
152 | + ((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK)); | ||
153 | + if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) { | ||
154 | + trace_e1000x_rx_flt_vlan_mismatch(vid); | ||
155 | + return false; | ||
156 | + } | ||
157 | + | ||
158 | + trace_e1000x_rx_flt_vlan_match(vid); | ||
159 | + } | ||
160 | + | ||
161 | + return true; | ||
162 | +} | ||
163 | + | ||
164 | +bool e1000x_rx_group_filter(uint32_t *mac, const struct eth_header *ehdr) | ||
165 | { | ||
166 | static const int mta_shift[] = { 4, 3, 2, 0 }; | ||
167 | uint32_t f, ra[2], *rp, rctl = mac[RCTL]; | ||
168 | |||
169 | + if (is_broadcast_ether_addr(ehdr->h_dest)) { | ||
170 | + if (rctl & E1000_RCTL_BAM) { | ||
171 | + return true; | ||
172 | + } | ||
173 | + } else if (is_multicast_ether_addr(ehdr->h_dest)) { | ||
174 | + if (rctl & E1000_RCTL_MPE) { | ||
175 | + return true; | ||
176 | + } | ||
177 | + } else { | ||
178 | + if (rctl & E1000_RCTL_UPE) { | ||
179 | + return true; | ||
180 | + } | ||
181 | + } | ||
182 | + | ||
183 | for (rp = mac + RA; rp < mac + RA + 32; rp += 2) { | ||
184 | if (!(rp[1] & E1000_RAH_AV)) { | ||
185 | continue; | ||
186 | } | ||
187 | ra[0] = cpu_to_le32(rp[0]); | ||
188 | ra[1] = cpu_to_le32(rp[1]); | ||
189 | - if (!memcmp(buf, (uint8_t *)ra, ETH_ALEN)) { | ||
190 | + if (!memcmp(ehdr->h_dest, (uint8_t *)ra, ETH_ALEN)) { | ||
191 | trace_e1000x_rx_flt_ucast_match((int)(rp - mac - RA) / 2, | ||
192 | - MAC_ARG(buf)); | ||
193 | + MAC_ARG(ehdr->h_dest)); | ||
194 | return true; | ||
195 | } | ||
196 | } | ||
197 | - trace_e1000x_rx_flt_ucast_mismatch(MAC_ARG(buf)); | ||
198 | + trace_e1000x_rx_flt_ucast_mismatch(MAC_ARG(ehdr->h_dest)); | ||
199 | |||
200 | f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3]; | ||
201 | - f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff; | ||
202 | + f = (((ehdr->h_dest[5] << 8) | ehdr->h_dest[4]) >> f) & 0xfff; | ||
203 | if (mac[MTA + (f >> 5)] & (1 << (f & 0x1f))) { | ||
204 | return true; | ||
205 | } | ||
206 | |||
207 | - trace_e1000x_rx_flt_inexact_mismatch(MAC_ARG(buf), | ||
208 | + trace_e1000x_rx_flt_inexact_mismatch(MAC_ARG(ehdr->h_dest), | ||
209 | (rctl >> E1000_RCTL_MO_SHIFT) & 3, | ||
210 | f >> 5, | ||
211 | mac[MTA + (f >> 5)]); | ||
212 | diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h | ||
213 | index XXXXXXX..XXXXXXX 100644 | ||
214 | --- a/hw/net/e1000x_common.h | ||
215 | +++ b/hw/net/e1000x_common.h | ||
216 | @@ -XXX,XX +XXX,XX @@ bool e1000x_rx_ready(PCIDevice *d, uint32_t *mac); | ||
217 | |||
218 | bool e1000x_is_vlan_packet(const void *buf, uint16_t vet); | ||
219 | |||
220 | -bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf); | ||
221 | +bool e1000x_rx_vlan_filter(uint32_t *mac, const struct vlan_header *vhdr); | ||
222 | + | ||
223 | +bool e1000x_rx_group_filter(uint32_t *mac, const struct eth_header *ehdr); | ||
224 | |||
225 | bool e1000x_hw_rx_enabled(uint32_t *mac); | ||
226 | |||
227 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
228 | index XXXXXXX..XXXXXXX 100644 | ||
229 | --- a/hw/net/igb_core.c | ||
230 | +++ b/hw/net/igb_core.c | ||
231 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
232 | uint16_t queues = 0; | ||
233 | uint16_t oversized = 0; | ||
234 | uint16_t vid = be16_to_cpu(l2_header->vlan.h_tci) & VLAN_VID_MASK; | ||
235 | - bool accepted = false; | ||
236 | int i; | ||
237 | |||
238 | memset(rss_info, 0, sizeof(E1000E_RSSInfo)); | ||
239 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
240 | } | ||
241 | |||
242 | if (e1000x_is_vlan_packet(ehdr, core->mac[VET] & 0xffff) && | ||
243 | - e1000x_vlan_rx_filter_enabled(core->mac)) { | ||
244 | - uint32_t vfta = | ||
245 | - ldl_le_p((uint32_t *)(core->mac + VFTA) + | ||
246 | - ((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK)); | ||
247 | - if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) { | ||
248 | - trace_e1000e_rx_flt_vlan_mismatch(vid); | ||
249 | - return queues; | ||
250 | - } else { | ||
251 | - trace_e1000e_rx_flt_vlan_match(vid); | ||
252 | - } | ||
253 | + !e1000x_rx_vlan_filter(core->mac, PKT_GET_VLAN_HDR(ehdr))) { | ||
254 | + return queues; | ||
255 | } | ||
256 | |||
257 | if (core->mac[MRQC] & 1) { | ||
258 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
259 | } | ||
260 | } | ||
261 | } else { | ||
262 | - switch (net_rx_pkt_get_packet_type(core->rx_pkt)) { | ||
263 | - case ETH_PKT_UCAST: | ||
264 | - if (rctl & E1000_RCTL_UPE) { | ||
265 | - accepted = true; /* promiscuous ucast */ | ||
266 | - } | ||
267 | - break; | ||
268 | - | ||
269 | - case ETH_PKT_BCAST: | ||
270 | - if (rctl & E1000_RCTL_BAM) { | ||
271 | - accepted = true; /* broadcast enabled */ | ||
272 | - } | ||
273 | - break; | ||
274 | - | ||
275 | - case ETH_PKT_MCAST: | ||
276 | - if (rctl & E1000_RCTL_MPE) { | ||
277 | - accepted = true; /* promiscuous mcast */ | ||
278 | - } | ||
279 | - break; | ||
280 | - | ||
281 | - default: | ||
282 | - g_assert_not_reached(); | ||
283 | - } | ||
284 | - | ||
285 | - if (!accepted) { | ||
286 | - accepted = e1000x_rx_group_filter(core->mac, ehdr->h_dest); | ||
287 | - } | ||
288 | - | ||
289 | + bool accepted = e1000x_rx_group_filter(core->mac, ehdr); | ||
290 | if (!accepted) { | ||
291 | for (macp = core->mac + RA2; macp < core->mac + RA2 + 16; macp += 2) { | ||
292 | if (!(macp[1] & E1000_RAH_AV)) { | ||
293 | diff --git a/hw/net/trace-events b/hw/net/trace-events | ||
294 | index XXXXXXX..XXXXXXX 100644 | ||
295 | --- a/hw/net/trace-events | ||
296 | +++ b/hw/net/trace-events | ||
297 | @@ -XXX,XX +XXX,XX @@ e1000_receiver_overrun(size_t s, uint32_t rdh, uint32_t rdt) "Receiver overrun: | ||
298 | # e1000x_common.c | ||
299 | e1000x_rx_can_recv_disabled(bool link_up, bool rx_enabled, bool pci_master) "link_up: %d, rx_enabled %d, pci_master %d" | ||
300 | e1000x_vlan_is_vlan_pkt(bool is_vlan_pkt, uint16_t eth_proto, uint16_t vet) "Is VLAN packet: %d, ETH proto: 0x%X, VET: 0x%X" | ||
301 | +e1000x_rx_flt_vlan_mismatch(uint16_t vid) "VID mismatch: 0x%X" | ||
302 | +e1000x_rx_flt_vlan_match(uint16_t vid) "VID match: 0x%X" | ||
303 | e1000x_rx_flt_ucast_match(uint32_t idx, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x" | ||
304 | e1000x_rx_flt_ucast_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x" | ||
305 | e1000x_rx_flt_inexact_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint32_t mo, uint32_t mta, uint32_t mta_val) "inexact mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] 0x%x" | ||
306 | @@ -XXX,XX +XXX,XX @@ e1000e_rx_can_recv_rings_full(void) "Cannot receive: all rings are full" | ||
307 | e1000e_rx_can_recv(void) "Can receive" | ||
308 | e1000e_rx_has_buffers(int ridx, uint32_t free_desc, size_t total_size, uint32_t desc_buf_size) "ring #%d: free descr: %u, packet size %zu, descr buffer size %u" | ||
309 | e1000e_rx_null_descriptor(void) "Null RX descriptor!!" | ||
310 | -e1000e_rx_flt_vlan_mismatch(uint16_t vid) "VID mismatch: 0x%X" | ||
311 | -e1000e_rx_flt_vlan_match(uint16_t vid) "VID match: 0x%X" | ||
312 | e1000e_rx_desc_ps_read(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) "buffers: [0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64"]" | ||
313 | e1000e_rx_desc_ps_write(uint16_t a0, uint16_t a1, uint16_t a2, uint16_t a3) "bytes written: [%u, %u, %u, %u]" | ||
314 | e1000e_rx_desc_buff_sizes(uint32_t b0, uint32_t b1, uint32_t b2, uint32_t b3) "buffer sizes: [%u, %u, %u, %u]" | ||
315 | -- | ||
316 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Section 13.7.15 Receive Length Error Count says: | ||
4 | > Packets over 1522 bytes are oversized if LongPacketEnable is 0b | ||
5 | > (RCTL.LPE). If LongPacketEnable (LPE) is 1b, then an incoming packet | ||
6 | > is considered oversized if it exceeds 16384 bytes. | ||
7 | |||
8 | > These lengths are based on bytes in the received packet from | ||
9 | > <Destination Address> through <CRC>, inclusively. | ||
10 | |||
11 | As QEMU processes packets without CRC, the number of bytes for CRC | ||
12 | need to be subtracted. This change adds some size definitions to be used | ||
13 | to derive the new size thresholds to eth.h. | ||
14 | |||
15 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
16 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
17 | --- | ||
18 | hw/net/e1000x_common.c | 10 +++++----- | ||
19 | include/net/eth.h | 2 ++ | ||
20 | 2 files changed, 7 insertions(+), 5 deletions(-) | ||
21 | |||
22 | diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/hw/net/e1000x_common.c | ||
25 | +++ b/hw/net/e1000x_common.c | ||
26 | @@ -XXX,XX +XXX,XX @@ bool e1000x_hw_rx_enabled(uint32_t *mac) | ||
27 | |||
28 | bool e1000x_is_oversized(uint32_t *mac, size_t size) | ||
29 | { | ||
30 | + size_t header_size = sizeof(struct eth_header) + sizeof(struct vlan_header); | ||
31 | /* this is the size past which hardware will | ||
32 | drop packets when setting LPE=0 */ | ||
33 | - static const int maximum_ethernet_vlan_size = 1522; | ||
34 | + size_t maximum_short_size = header_size + ETH_MTU; | ||
35 | /* this is the size past which hardware will | ||
36 | drop packets when setting LPE=1 */ | ||
37 | - static const int maximum_ethernet_lpe_size = 16 * KiB; | ||
38 | + size_t maximum_large_size = 16 * KiB - ETH_FCS_LEN; | ||
39 | |||
40 | - if ((size > maximum_ethernet_lpe_size || | ||
41 | - (size > maximum_ethernet_vlan_size | ||
42 | - && !(mac[RCTL] & E1000_RCTL_LPE))) | ||
43 | + if ((size > maximum_large_size || | ||
44 | + (size > maximum_short_size && !(mac[RCTL] & E1000_RCTL_LPE))) | ||
45 | && !(mac[RCTL] & E1000_RCTL_SBP)) { | ||
46 | e1000x_inc_reg_if_not_full(mac, ROC); | ||
47 | trace_e1000x_rx_oversized(size); | ||
48 | diff --git a/include/net/eth.h b/include/net/eth.h | ||
49 | index XXXXXXX..XXXXXXX 100644 | ||
50 | --- a/include/net/eth.h | ||
51 | +++ b/include/net/eth.h | ||
52 | @@ -XXX,XX +XXX,XX @@ | ||
53 | #define ETH_ALEN 6 | ||
54 | #define ETH_HLEN 14 | ||
55 | #define ETH_ZLEN 60 /* Min. octets in frame without FCS */ | ||
56 | +#define ETH_FCS_LEN 4 | ||
57 | +#define ETH_MTU 1500 | ||
58 | |||
59 | struct eth_header { | ||
60 | uint8_t h_dest[ETH_ALEN]; /* destination eth addr */ | ||
61 | -- | ||
62 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | e1000e and igb employs NetPktRssIpV6TcpEx for RSS hash if TcpIpv6 MRQC | ||
4 | bit is set. Moreover, igb also has a MRQC bit for NetPktRssIpV6Tcp | ||
5 | though it is not implemented yet. Rename it to TcpIpv6Ex to avoid | ||
6 | confusion. | ||
7 | |||
8 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
9 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
10 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
11 | --- | ||
12 | hw/net/e1000e_core.c | 8 ++++---- | ||
13 | hw/net/e1000x_regs.h | 24 ++++++++++++------------ | ||
14 | hw/net/igb_core.c | 8 ++++---- | ||
15 | hw/net/trace-events | 2 +- | ||
16 | 4 files changed, 21 insertions(+), 21 deletions(-) | ||
17 | |||
18 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/hw/net/e1000e_core.c | ||
21 | +++ b/hw/net/e1000e_core.c | ||
22 | @@ -XXX,XX +XXX,XX @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt) | ||
23 | ip6info->rss_ex_dst_valid, | ||
24 | ip6info->rss_ex_src_valid, | ||
25 | core->mac[MRQC], | ||
26 | - E1000_MRQC_EN_TCPIPV6(core->mac[MRQC]), | ||
27 | + E1000_MRQC_EN_TCPIPV6EX(core->mac[MRQC]), | ||
28 | E1000_MRQC_EN_IPV6EX(core->mac[MRQC]), | ||
29 | E1000_MRQC_EN_IPV6(core->mac[MRQC])); | ||
30 | |||
31 | @@ -XXX,XX +XXX,XX @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt) | ||
32 | ip6info->rss_ex_src_valid))) { | ||
33 | |||
34 | if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP && | ||
35 | - E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) { | ||
36 | - return E1000_MRQ_RSS_TYPE_IPV6TCP; | ||
37 | + E1000_MRQC_EN_TCPIPV6EX(core->mac[MRQC])) { | ||
38 | + return E1000_MRQ_RSS_TYPE_IPV6TCPEX; | ||
39 | } | ||
40 | |||
41 | if (E1000_MRQC_EN_IPV6EX(core->mac[MRQC])) { | ||
42 | @@ -XXX,XX +XXX,XX @@ e1000e_rss_calc_hash(E1000ECore *core, | ||
43 | case E1000_MRQ_RSS_TYPE_IPV4TCP: | ||
44 | type = NetPktRssIpV4Tcp; | ||
45 | break; | ||
46 | - case E1000_MRQ_RSS_TYPE_IPV6TCP: | ||
47 | + case E1000_MRQ_RSS_TYPE_IPV6TCPEX: | ||
48 | type = NetPktRssIpV6TcpEx; | ||
49 | break; | ||
50 | case E1000_MRQ_RSS_TYPE_IPV6: | ||
51 | diff --git a/hw/net/e1000x_regs.h b/hw/net/e1000x_regs.h | ||
52 | index XXXXXXX..XXXXXXX 100644 | ||
53 | --- a/hw/net/e1000x_regs.h | ||
54 | +++ b/hw/net/e1000x_regs.h | ||
55 | @@ -XXX,XX +XXX,XX @@ | ||
56 | #define E1000_RETA_IDX(hash) ((hash) & (BIT(7) - 1)) | ||
57 | #define E1000_RETA_VAL(reta, hash) (((uint8_t *)(reta))[E1000_RETA_IDX(hash)]) | ||
58 | |||
59 | -#define E1000_MRQC_EN_TCPIPV4(mrqc) ((mrqc) & BIT(16)) | ||
60 | -#define E1000_MRQC_EN_IPV4(mrqc) ((mrqc) & BIT(17)) | ||
61 | -#define E1000_MRQC_EN_TCPIPV6(mrqc) ((mrqc) & BIT(18)) | ||
62 | -#define E1000_MRQC_EN_IPV6EX(mrqc) ((mrqc) & BIT(19)) | ||
63 | -#define E1000_MRQC_EN_IPV6(mrqc) ((mrqc) & BIT(20)) | ||
64 | - | ||
65 | -#define E1000_MRQ_RSS_TYPE_NONE (0) | ||
66 | -#define E1000_MRQ_RSS_TYPE_IPV4TCP (1) | ||
67 | -#define E1000_MRQ_RSS_TYPE_IPV4 (2) | ||
68 | -#define E1000_MRQ_RSS_TYPE_IPV6TCP (3) | ||
69 | -#define E1000_MRQ_RSS_TYPE_IPV6EX (4) | ||
70 | -#define E1000_MRQ_RSS_TYPE_IPV6 (5) | ||
71 | +#define E1000_MRQC_EN_TCPIPV4(mrqc) ((mrqc) & BIT(16)) | ||
72 | +#define E1000_MRQC_EN_IPV4(mrqc) ((mrqc) & BIT(17)) | ||
73 | +#define E1000_MRQC_EN_TCPIPV6EX(mrqc) ((mrqc) & BIT(18)) | ||
74 | +#define E1000_MRQC_EN_IPV6EX(mrqc) ((mrqc) & BIT(19)) | ||
75 | +#define E1000_MRQC_EN_IPV6(mrqc) ((mrqc) & BIT(20)) | ||
76 | + | ||
77 | +#define E1000_MRQ_RSS_TYPE_NONE (0) | ||
78 | +#define E1000_MRQ_RSS_TYPE_IPV4TCP (1) | ||
79 | +#define E1000_MRQ_RSS_TYPE_IPV4 (2) | ||
80 | +#define E1000_MRQ_RSS_TYPE_IPV6TCPEX (3) | ||
81 | +#define E1000_MRQ_RSS_TYPE_IPV6EX (4) | ||
82 | +#define E1000_MRQ_RSS_TYPE_IPV6 (5) | ||
83 | |||
84 | #define E1000_ICR_ASSERTED BIT(31) | ||
85 | #define E1000_EIAC_MASK 0x01F00000 | ||
86 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
87 | index XXXXXXX..XXXXXXX 100644 | ||
88 | --- a/hw/net/igb_core.c | ||
89 | +++ b/hw/net/igb_core.c | ||
90 | @@ -XXX,XX +XXX,XX @@ igb_rss_get_hash_type(IGBCore *core, struct NetRxPkt *pkt) | ||
91 | ip6info->rss_ex_dst_valid, | ||
92 | ip6info->rss_ex_src_valid, | ||
93 | core->mac[MRQC], | ||
94 | - E1000_MRQC_EN_TCPIPV6(core->mac[MRQC]), | ||
95 | + E1000_MRQC_EN_TCPIPV6EX(core->mac[MRQC]), | ||
96 | E1000_MRQC_EN_IPV6EX(core->mac[MRQC]), | ||
97 | E1000_MRQC_EN_IPV6(core->mac[MRQC])); | ||
98 | |||
99 | @@ -XXX,XX +XXX,XX @@ igb_rss_get_hash_type(IGBCore *core, struct NetRxPkt *pkt) | ||
100 | ip6info->rss_ex_src_valid))) { | ||
101 | |||
102 | if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP && | ||
103 | - E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) { | ||
104 | - return E1000_MRQ_RSS_TYPE_IPV6TCP; | ||
105 | + E1000_MRQC_EN_TCPIPV6EX(core->mac[MRQC])) { | ||
106 | + return E1000_MRQ_RSS_TYPE_IPV6TCPEX; | ||
107 | } | ||
108 | |||
109 | if (E1000_MRQC_EN_IPV6EX(core->mac[MRQC])) { | ||
110 | @@ -XXX,XX +XXX,XX @@ igb_rss_calc_hash(IGBCore *core, struct NetRxPkt *pkt, E1000E_RSSInfo *info) | ||
111 | case E1000_MRQ_RSS_TYPE_IPV4TCP: | ||
112 | type = NetPktRssIpV4Tcp; | ||
113 | break; | ||
114 | - case E1000_MRQ_RSS_TYPE_IPV6TCP: | ||
115 | + case E1000_MRQ_RSS_TYPE_IPV6TCPEX: | ||
116 | type = NetPktRssIpV6TcpEx; | ||
117 | break; | ||
118 | case E1000_MRQ_RSS_TYPE_IPV6: | ||
119 | diff --git a/hw/net/trace-events b/hw/net/trace-events | ||
120 | index XXXXXXX..XXXXXXX 100644 | ||
121 | --- a/hw/net/trace-events | ||
122 | +++ b/hw/net/trace-events | ||
123 | @@ -XXX,XX +XXX,XX @@ e1000e_rx_rss_disabled(void) "RSS is disabled" | ||
124 | e1000e_rx_rss_type(uint32_t type) "RSS type is %u" | ||
125 | e1000e_rx_rss_ip4(int l4hdr_proto, uint32_t mrqc, bool tcpipv4_enabled, bool ipv4_enabled) "RSS IPv4: L4 header protocol %d, mrqc 0x%X, tcpipv4 enabled %d, ipv4 enabled %d" | ||
126 | e1000e_rx_rss_ip6_rfctl(uint32_t rfctl) "RSS IPv6: rfctl 0x%X" | ||
127 | -e1000e_rx_rss_ip6(bool ex_dis, bool new_ex_dis, int l4hdr_proto, bool has_ext_headers, bool ex_dst_valid, bool ex_src_valid, uint32_t mrqc, bool tcpipv6_enabled, bool ipv6ex_enabled, bool ipv6_enabled) "RSS IPv6: ex_dis: %d, new_ex_dis: %d, L4 header protocol %d, has_ext_headers %d, ex_dst_valid %d, ex_src_valid %d, mrqc 0x%X, tcpipv6 enabled %d, ipv6ex enabled %d, ipv6 enabled %d" | ||
128 | +e1000e_rx_rss_ip6(bool ex_dis, bool new_ex_dis, int l4hdr_proto, bool has_ext_headers, bool ex_dst_valid, bool ex_src_valid, uint32_t mrqc, bool tcpipv6ex_enabled, bool ipv6ex_enabled, bool ipv6_enabled) "RSS IPv6: ex_dis: %d, new_ex_dis: %d, L4 header protocol %d, has_ext_headers %d, ex_dst_valid %d, ex_src_valid %d, mrqc 0x%X, tcpipv6ex enabled %d, ipv6ex enabled %d, ipv6 enabled %d" | ||
129 | |||
130 | e1000e_rx_metadata_protocols(bool hasip4, bool hasip6, int l4hdr_protocol) "protocols: ip4: %d, ip6: %d, l4hdr: %d" | ||
131 | e1000e_rx_metadata_vlan(uint16_t vlan_tag) "VLAN tag is 0x%X" | ||
132 | -- | ||
133 | 2.7.4 | diff view generated by jsdifflib |
1 | From: Prasad J Pandit <pjp@fedoraproject.org> | 1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> |
---|---|---|---|
2 | 2 | ||
3 | While receiving packets via e1000e_write_packet_to_guest() routine, | 3 | Without this change, the status flags may not be traced e.g. if checksum |
4 | 'desc_offset' is advanced only when RX descriptor is processed. And | 4 | offloading is disabled. |
5 | RX descriptor is not processed if it has NULL buffer address. | ||
6 | This may lead to an infinite loop condition. Increament 'desc_offset' | ||
7 | to process next descriptor in the ring to avoid infinite loop. | ||
8 | 5 | ||
9 | Reported-by: Cheol-woo Myung <330cjfdn@gmail.com> | 6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
10 | Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> | 7 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
11 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 8 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
12 | --- | 9 | --- |
13 | hw/net/e1000e_core.c | 8 ++++---- | 10 | hw/net/e1000e_core.c | 3 +-- |
14 | 1 file changed, 4 insertions(+), 4 deletions(-) | 11 | 1 file changed, 1 insertion(+), 2 deletions(-) |
15 | 12 | ||
16 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | 13 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c |
17 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/hw/net/e1000e_core.c | 15 | --- a/hw/net/e1000e_core.c |
19 | +++ b/hw/net/e1000e_core.c | 16 | +++ b/hw/net/e1000e_core.c |
20 | @@ -XXX,XX +XXX,XX @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt, | 17 | @@ -XXX,XX +XXX,XX @@ e1000e_build_rx_metadata(E1000ECore *core, |
21 | (const char *) &fcs_pad, e1000x_fcs_len(core->mac)); | 18 | trace_e1000e_rx_metadata_l4_cso_disabled(); |
22 | } | 19 | } |
23 | } | 20 | |
24 | - desc_offset += desc_size; | 21 | - trace_e1000e_rx_metadata_status_flags(*status_flags); |
25 | - if (desc_offset >= total_size) { | 22 | - |
26 | - is_last = true; | 23 | func_exit: |
27 | - } | 24 | + trace_e1000e_rx_metadata_status_flags(*status_flags); |
28 | } else { /* as per intel docs; skip descriptors with null buf addr */ | 25 | *status_flags = cpu_to_le32(*status_flags); |
29 | trace_e1000e_rx_null_descriptor(); | 26 | } |
30 | } | 27 | |
31 | + desc_offset += desc_size; | ||
32 | + if (desc_offset >= total_size) { | ||
33 | + is_last = true; | ||
34 | + } | ||
35 | |||
36 | e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL, | ||
37 | rss_info, do_ps ? ps_hdr_len : 0, &bastate.written); | ||
38 | -- | 28 | -- |
39 | 2.7.4 | 29 | 2.7.4 |
40 | 30 | ||
41 | 31 | diff view generated by jsdifflib |
1 | From: Yuri Benditovich <yuri.benditovich@daynix.com> | 1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> |
---|---|---|---|
2 | 2 | ||
3 | https://bugzilla.redhat.com/show_bug.cgi?id=1829272 | 3 | Without this change, the status flags may not be traced e.g. if checksum |
4 | When deleting queue pair, purge pending RX packets if any. | 4 | offloading is disabled. |
5 | Example of problematic flow: | ||
6 | 1. Bring up q35 VM with tap (vhost off) and virtio-net or e1000e | ||
7 | 2. Run ping flood to the VM NIC ( 1 ms interval) | ||
8 | 3. Hot unplug the NIC device (device_del) | ||
9 | During unplug process one or more packets come, the NIC | ||
10 | can't receive, tap disables read_poll | ||
11 | 4. Hot plug the device (device_add) with the same netdev | ||
12 | The tap stays with read_poll disabled and does not receive | ||
13 | any packets anymore (tap_send never triggered) | ||
14 | 5 | ||
15 | Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com> | 6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
7 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
16 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 8 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
17 | --- | 9 | --- |
18 | net/net.c | 12 ++++++++---- | 10 | hw/net/igb_core.c | 3 +-- |
19 | 1 file changed, 8 insertions(+), 4 deletions(-) | 11 | 1 file changed, 1 insertion(+), 2 deletions(-) |
20 | 12 | ||
21 | diff --git a/net/net.c b/net/net.c | 13 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c |
22 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/net/net.c | 15 | --- a/hw/net/igb_core.c |
24 | +++ b/net/net.c | 16 | +++ b/hw/net/igb_core.c |
25 | @@ -XXX,XX +XXX,XX @@ void qemu_del_nic(NICState *nic) | 17 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, |
26 | 18 | trace_e1000e_rx_metadata_l4_cso_disabled(); | |
27 | qemu_macaddr_set_free(&nic->conf->macaddr); | ||
28 | |||
29 | - /* If this is a peer NIC and peer has already been deleted, free it now. */ | ||
30 | - if (nic->peer_deleted) { | ||
31 | - for (i = 0; i < queues; i++) { | ||
32 | - qemu_free_net_client(qemu_get_subqueue(nic, i)->peer); | ||
33 | + for (i = 0; i < queues; i++) { | ||
34 | + NetClientState *nc = qemu_get_subqueue(nic, i); | ||
35 | + /* If this is a peer NIC and peer has already been deleted, free it now. */ | ||
36 | + if (nic->peer_deleted) { | ||
37 | + qemu_free_net_client(nc->peer); | ||
38 | + } else if (nc->peer) { | ||
39 | + /* if there are RX packets pending, complete them */ | ||
40 | + qemu_purge_queued_packets(nc->peer); | ||
41 | } | ||
42 | } | 19 | } |
20 | |||
21 | - trace_e1000e_rx_metadata_status_flags(*status_flags); | ||
22 | - | ||
23 | func_exit: | ||
24 | + trace_e1000e_rx_metadata_status_flags(*status_flags); | ||
25 | *status_flags = cpu_to_le32(*status_flags); | ||
26 | } | ||
43 | 27 | ||
44 | -- | 28 | -- |
45 | 2.7.4 | 29 | 2.7.4 |
46 | 30 | ||
47 | 31 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | The goto is a bit confusing as it changes the control flow only if L4 | ||
4 | protocol is not recognized. It is also different from e1000e, and | ||
5 | noisy when comparing e1000e and igb. | ||
6 | |||
7 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
8 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
9 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
10 | --- | ||
11 | hw/net/igb_core.c | 2 +- | ||
12 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/net/igb_core.c | ||
17 | +++ b/hw/net/igb_core.c | ||
18 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
19 | break; | ||
20 | |||
21 | default: | ||
22 | - goto func_exit; | ||
23 | + break; | ||
24 | } | ||
25 | } else { | ||
26 | trace_e1000e_rx_metadata_l4_cso_disabled(); | ||
27 | -- | ||
28 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Section 7.2.2.3 Advanced Transmit Data Descriptor says: | ||
4 | > For frames that spans multiple descriptors, all fields apart from | ||
5 | > DCMD.EOP, DCMD.RS, DCMD.DEXT, DTALEN, Address and DTYP are valid only | ||
6 | > in the first descriptors and are ignored in the subsequent ones. | ||
7 | |||
8 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
9 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
10 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
11 | --- | ||
12 | hw/net/igb_core.c | 2 +- | ||
13 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
14 | |||
15 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/net/igb_core.c | ||
18 | +++ b/hw/net/igb_core.c | ||
19 | @@ -XXX,XX +XXX,XX @@ igb_process_tx_desc(IGBCore *core, | ||
20 | idx = (tx->first_olinfo_status >> 4) & 1; | ||
21 | igb_tx_insert_vlan(core, queue_index, tx, | ||
22 | tx->ctx[idx].vlan_macip_lens >> 16, | ||
23 | - !!(cmd_type_len & E1000_TXD_CMD_VLE)); | ||
24 | + !!(tx->first_cmd_type_len & E1000_TXD_CMD_VLE)); | ||
25 | |||
26 | if (igb_tx_pkt_send(core, tx, queue_index)) { | ||
27 | igb_on_tx_done_update_stats(core, tx->tx_pkt, queue_index); | ||
28 | -- | ||
29 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Keeping Tx packet state after the transmit queue is emptied has some | ||
4 | problems: | ||
5 | - The datasheet says the descriptors can be reused after the transmit | ||
6 | queue is emptied, but the Tx packet state may keep references to them. | ||
7 | - The Tx packet state cannot be migrated so it can be reset anytime the | ||
8 | migration happens. | ||
9 | |||
10 | Always reset Tx packet state always after the queue is emptied. | ||
11 | |||
12 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
13 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
14 | --- | ||
15 | hw/net/e1000e_core.c | 6 ++---- | ||
16 | 1 file changed, 2 insertions(+), 4 deletions(-) | ||
17 | |||
18 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/hw/net/e1000e_core.c | ||
21 | +++ b/hw/net/e1000e_core.c | ||
22 | @@ -XXX,XX +XXX,XX @@ e1000e_start_xmit(E1000ECore *core, const E1000E_TxRing *txr) | ||
23 | if (!ide || !e1000e_intrmgr_delay_tx_causes(core, &cause)) { | ||
24 | e1000e_set_interrupt_cause(core, cause); | ||
25 | } | ||
26 | + | ||
27 | + net_tx_pkt_reset(txr->tx->tx_pkt, net_tx_pkt_unmap_frag_pci, core->owner); | ||
28 | } | ||
29 | |||
30 | static bool | ||
31 | @@ -XXX,XX +XXX,XX @@ e1000e_core_pci_uninit(E1000ECore *core) | ||
32 | qemu_del_vm_change_state_handler(core->vmstate); | ||
33 | |||
34 | for (i = 0; i < E1000E_NUM_QUEUES; i++) { | ||
35 | - net_tx_pkt_reset(core->tx[i].tx_pkt, | ||
36 | - net_tx_pkt_unmap_frag_pci, core->owner); | ||
37 | net_tx_pkt_uninit(core->tx[i].tx_pkt); | ||
38 | } | ||
39 | |||
40 | @@ -XXX,XX +XXX,XX @@ static void e1000e_reset(E1000ECore *core, bool sw) | ||
41 | e1000x_reset_mac_addr(core->owner_nic, core->mac, core->permanent_mac); | ||
42 | |||
43 | for (i = 0; i < ARRAY_SIZE(core->tx); i++) { | ||
44 | - net_tx_pkt_reset(core->tx[i].tx_pkt, | ||
45 | - net_tx_pkt_unmap_frag_pci, core->owner); | ||
46 | memset(&core->tx[i].props, 0, sizeof(core->tx[i].props)); | ||
47 | core->tx[i].skip_cp = false; | ||
48 | } | ||
49 | -- | ||
50 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Keeping Tx packet state after the transmit queue is emptied but this | ||
4 | behavior is unreliable as the state can be reset anytime the migration | ||
5 | happens. | ||
6 | |||
7 | Always reset Tx packet state always after the queue is emptied. | ||
8 | |||
9 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
10 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
11 | --- | ||
12 | hw/net/vmxnet3.c | 3 ++- | ||
13 | 1 file changed, 2 insertions(+), 1 deletion(-) | ||
14 | |||
15 | diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/net/vmxnet3.c | ||
18 | +++ b/hw/net/vmxnet3.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx) | ||
20 | net_tx_pkt_unmap_frag_pci, PCI_DEVICE(s)); | ||
21 | } | ||
22 | } | ||
23 | + | ||
24 | + net_tx_pkt_reset(s->tx_pkt, net_tx_pkt_unmap_frag_pci, PCI_DEVICE(s)); | ||
25 | } | ||
26 | |||
27 | static inline void | ||
28 | @@ -XXX,XX +XXX,XX @@ static void vmxnet3_deactivate_device(VMXNET3State *s) | ||
29 | { | ||
30 | if (s->device_active) { | ||
31 | VMW_CBPRN("Deactivating vmxnet3..."); | ||
32 | - net_tx_pkt_reset(s->tx_pkt, net_tx_pkt_unmap_frag_pci, PCI_DEVICE(s)); | ||
33 | net_tx_pkt_uninit(s->tx_pkt); | ||
34 | net_rx_pkt_uninit(s->rx_pkt); | ||
35 | s->device_active = false; | ||
36 | -- | ||
37 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
6 | --- | ||
7 | hw/net/igb_core.c | 4 ++-- | ||
8 | hw/net/igb_regs.h | 32 +++++++++++++++++++++++++++----- | ||
9 | 2 files changed, 29 insertions(+), 7 deletions(-) | ||
10 | |||
11 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/hw/net/igb_core.c | ||
14 | +++ b/hw/net/igb_core.c | ||
15 | @@ -XXX,XX +XXX,XX @@ igb_setup_tx_offloads(IGBCore *core, struct igb_tx *tx) | ||
16 | { | ||
17 | if (tx->first_cmd_type_len & E1000_ADVTXD_DCMD_TSE) { | ||
18 | uint32_t idx = (tx->first_olinfo_status >> 4) & 1; | ||
19 | - uint32_t mss = tx->ctx[idx].mss_l4len_idx >> 16; | ||
20 | + uint32_t mss = tx->ctx[idx].mss_l4len_idx >> E1000_ADVTXD_MSS_SHIFT; | ||
21 | if (!net_tx_pkt_build_vheader(tx->tx_pkt, true, true, mss)) { | ||
22 | return false; | ||
23 | } | ||
24 | @@ -XXX,XX +XXX,XX @@ igb_process_tx_desc(IGBCore *core, | ||
25 | if (!tx->skip_cp && net_tx_pkt_parse(tx->tx_pkt)) { | ||
26 | idx = (tx->first_olinfo_status >> 4) & 1; | ||
27 | igb_tx_insert_vlan(core, queue_index, tx, | ||
28 | - tx->ctx[idx].vlan_macip_lens >> 16, | ||
29 | + tx->ctx[idx].vlan_macip_lens >> IGB_TX_FLAGS_VLAN_SHIFT, | ||
30 | !!(tx->first_cmd_type_len & E1000_TXD_CMD_VLE)); | ||
31 | |||
32 | if (igb_tx_pkt_send(core, tx, queue_index)) { | ||
33 | diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/hw/net/igb_regs.h | ||
36 | +++ b/hw/net/igb_regs.h | ||
37 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_tx_desc { | ||
38 | } wb; | ||
39 | }; | ||
40 | |||
41 | -#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ | ||
42 | -#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ | ||
43 | -#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor Extension (1=Adv) */ | ||
44 | -#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP/UDP Segmentation Enable */ | ||
45 | - | ||
46 | #define E1000_ADVTXD_POTS_IXSM 0x00000100 /* Insert TCP/UDP Checksum */ | ||
47 | #define E1000_ADVTXD_POTS_TXSM 0x00000200 /* Insert TCP/UDP Checksum */ | ||
48 | |||
49 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
50 | #define IGB_82576_VF_DEV_ID 0x10CA | ||
51 | #define IGB_I350_VF_DEV_ID 0x1520 | ||
52 | |||
53 | +/* VLAN info */ | ||
54 | +#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 | ||
55 | +#define IGB_TX_FLAGS_VLAN_SHIFT 16 | ||
56 | + | ||
57 | /* from igb/e1000_82575.h */ | ||
58 | |||
59 | #define E1000_MRQC_ENABLE_RSS_MQ 0x00000002 | ||
60 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
61 | #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 | ||
62 | #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 | ||
63 | |||
64 | +/* Adv Transmit Descriptor Config Masks */ | ||
65 | +#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ | ||
66 | +#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ | ||
67 | +#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ | ||
68 | +#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ | ||
69 | +#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ | ||
70 | +#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */ | ||
71 | +#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */ | ||
72 | +#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */ | ||
73 | +#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ | ||
74 | +#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ | ||
75 | + | ||
76 | +#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ | ||
77 | +#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ | ||
78 | +#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ | ||
79 | +#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ | ||
80 | +#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */ | ||
81 | +/* IPSec Encrypt Enable for ESP */ | ||
82 | +#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ | ||
83 | +#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ | ||
84 | +/* Adv ctxt IPSec SA IDX mask */ | ||
85 | +/* Adv ctxt IPSec ESP len mask */ | ||
86 | + | ||
87 | /* Additional Transmit Descriptor Control definitions */ | ||
88 | #define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */ | ||
89 | |||
90 | -- | ||
91 | 2.7.4 | diff view generated by jsdifflib |
1 | From: Paolo Bonzini <pbonzini@redhat.com> | 1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> |
---|---|---|---|
2 | 2 | ||
3 | "netdev_add help" is causing QEMU to exit because the code that | 3 | The constants need to be consistent between the PF and VF. |
4 | invokes show_netdevs is shared between CLI and HMP processing. | ||
5 | Move the check to the callers so that exit(0) remains only | ||
6 | in the CLI flow. | ||
7 | 4 | ||
8 | "netdev_add help" is not fixed by this patch; that is left for | 5 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
9 | later work. | 6 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
10 | 7 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | |
11 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> | ||
12 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 8 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
13 | --- | 9 | --- |
14 | include/net/net.h | 1 + | 10 | hw/net/igb.c | 10 +++++----- |
15 | monitor/hmp-cmds.c | 6 +++++ | 11 | hw/net/igb_common.h | 8 ++++++++ |
16 | net/net.c | 68 +++++++++++++++++++++++++++--------------------------- | 12 | hw/net/igbvf.c | 7 ------- |
17 | 3 files changed, 41 insertions(+), 34 deletions(-) | 13 | 3 files changed, 13 insertions(+), 12 deletions(-) |
18 | 14 | ||
19 | diff --git a/include/net/net.h b/include/net/net.h | 15 | diff --git a/hw/net/igb.c b/hw/net/igb.c |
20 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/include/net/net.h | 17 | --- a/hw/net/igb.c |
22 | +++ b/include/net/net.h | 18 | +++ b/hw/net/igb.c |
23 | @@ -XXX,XX +XXX,XX @@ extern const char *host_net_devices[]; | 19 | @@ -XXX,XX +XXX,XX @@ static void igb_pci_realize(PCIDevice *pci_dev, Error **errp) |
24 | 20 | ||
25 | /* from net.c */ | 21 | pcie_ari_init(pci_dev, 0x150, 1); |
26 | int net_client_parse(QemuOptsList *opts_list, const char *str); | 22 | |
27 | +void show_netdevs(void); | 23 | - pcie_sriov_pf_init(pci_dev, IGB_CAP_SRIOV_OFFSET, "igbvf", |
28 | int net_init_clients(Error **errp); | 24 | + pcie_sriov_pf_init(pci_dev, IGB_CAP_SRIOV_OFFSET, TYPE_IGBVF, |
29 | void net_check_clients(void); | 25 | IGB_82576_VF_DEV_ID, IGB_MAX_VF_FUNCTIONS, IGB_MAX_VF_FUNCTIONS, |
30 | void net_cleanup(void); | 26 | IGB_VF_OFFSET, IGB_VF_STRIDE); |
31 | diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c | 27 | |
28 | - pcie_sriov_pf_init_vf_bar(pci_dev, 0, | ||
29 | + pcie_sriov_pf_init_vf_bar(pci_dev, IGBVF_MMIO_BAR_IDX, | ||
30 | PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH, | ||
31 | - 16 * KiB); | ||
32 | - pcie_sriov_pf_init_vf_bar(pci_dev, 3, | ||
33 | + IGBVF_MMIO_SIZE); | ||
34 | + pcie_sriov_pf_init_vf_bar(pci_dev, IGBVF_MSIX_BAR_IDX, | ||
35 | PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH, | ||
36 | - 16 * KiB); | ||
37 | + IGBVF_MSIX_SIZE); | ||
38 | |||
39 | igb_init_net_peer(s, pci_dev, macaddr); | ||
40 | |||
41 | diff --git a/hw/net/igb_common.h b/hw/net/igb_common.h | ||
32 | index XXXXXXX..XXXXXXX 100644 | 42 | index XXXXXXX..XXXXXXX 100644 |
33 | --- a/monitor/hmp-cmds.c | 43 | --- a/hw/net/igb_common.h |
34 | +++ b/monitor/hmp-cmds.c | 44 | +++ b/hw/net/igb_common.h |
35 | @@ -XXX,XX +XXX,XX @@ | 45 | @@ -XXX,XX +XXX,XX @@ |
36 | #include "qemu/option.h" | 46 | |
37 | #include "qemu/timer.h" | 47 | #include "igb_regs.h" |
38 | #include "qemu/sockets.h" | 48 | |
39 | +#include "qemu/help_option.h" | 49 | +#define TYPE_IGBVF "igbvf" |
40 | #include "monitor/monitor-internal.h" | 50 | + |
51 | +#define IGBVF_MMIO_BAR_IDX (0) | ||
52 | +#define IGBVF_MSIX_BAR_IDX (3) | ||
53 | + | ||
54 | +#define IGBVF_MMIO_SIZE (16 * 1024) | ||
55 | +#define IGBVF_MSIX_SIZE (16 * 1024) | ||
56 | + | ||
57 | #define defreg(x) x = (E1000_##x >> 2) | ||
58 | #define defreg_indexed(x, i) x##i = (E1000_##x(i) >> 2) | ||
59 | #define defreg_indexeda(x, i) x##i##_A = (E1000_##x##_A(i) >> 2) | ||
60 | diff --git a/hw/net/igbvf.c b/hw/net/igbvf.c | ||
61 | index XXXXXXX..XXXXXXX 100644 | ||
62 | --- a/hw/net/igbvf.c | ||
63 | +++ b/hw/net/igbvf.c | ||
64 | @@ -XXX,XX +XXX,XX @@ | ||
65 | #include "trace.h" | ||
41 | #include "qapi/error.h" | 66 | #include "qapi/error.h" |
42 | #include "qapi/clone-visitor.h" | 67 | |
43 | @@ -XXX,XX +XXX,XX @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict) | 68 | -#define TYPE_IGBVF "igbvf" |
44 | { | 69 | OBJECT_DECLARE_SIMPLE_TYPE(IgbVfState, IGBVF) |
45 | Error *err = NULL; | 70 | |
46 | QemuOpts *opts; | 71 | -#define IGBVF_MMIO_BAR_IDX (0) |
47 | + const char *type = qdict_get_try_str(qdict, "type"); | 72 | -#define IGBVF_MSIX_BAR_IDX (3) |
48 | |||
49 | + if (type && is_help_option(type)) { | ||
50 | + show_netdevs(); | ||
51 | + return; | ||
52 | + } | ||
53 | opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err); | ||
54 | if (err) { | ||
55 | goto out; | ||
56 | diff --git a/net/net.c b/net/net.c | ||
57 | index XXXXXXX..XXXXXXX 100644 | ||
58 | --- a/net/net.c | ||
59 | +++ b/net/net.c | ||
60 | @@ -XXX,XX +XXX,XX @@ | ||
61 | #include "qemu/config-file.h" | ||
62 | #include "qemu/ctype.h" | ||
63 | #include "qemu/iov.h" | ||
64 | +#include "qemu/qemu-print.h" | ||
65 | #include "qemu/main-loop.h" | ||
66 | #include "qemu/option.h" | ||
67 | #include "qapi/error.h" | ||
68 | @@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp) | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | -static void show_netdevs(void) | ||
73 | +void show_netdevs(void) | ||
74 | { | ||
75 | int idx; | ||
76 | const char *available_netdevs[] = { | ||
77 | @@ -XXX,XX +XXX,XX @@ static void show_netdevs(void) | ||
78 | #endif | ||
79 | }; | ||
80 | |||
81 | - printf("Available netdev backend types:\n"); | ||
82 | + qemu_printf("Available netdev backend types:\n"); | ||
83 | for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) { | ||
84 | - puts(available_netdevs[idx]); | ||
85 | + qemu_printf("%s\n", available_netdevs[idx]); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | @@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) | ||
90 | int ret = -1; | ||
91 | Visitor *v = opts_visitor_new(opts); | ||
92 | |||
93 | - const char *type = qemu_opt_get(opts, "type"); | ||
94 | - | 73 | - |
95 | - if (is_netdev && type && is_help_option(type)) { | 74 | -#define IGBVF_MMIO_SIZE (16 * 1024) |
96 | - show_netdevs(); | 75 | -#define IGBVF_MSIX_SIZE (16 * 1024) |
97 | - exit(0); | ||
98 | - } else { | ||
99 | - /* Parse convenience option format ip6-net=fec0::0[/64] */ | ||
100 | - const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); | ||
101 | + /* Parse convenience option format ip6-net=fec0::0[/64] */ | ||
102 | + const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); | ||
103 | |||
104 | - if (ip6_net) { | ||
105 | - char *prefix_addr; | ||
106 | - unsigned long prefix_len = 64; /* Default 64bit prefix length. */ | ||
107 | + if (ip6_net) { | ||
108 | + char *prefix_addr; | ||
109 | + unsigned long prefix_len = 64; /* Default 64bit prefix length. */ | ||
110 | |||
111 | - substrings = g_strsplit(ip6_net, "/", 2); | ||
112 | - if (!substrings || !substrings[0]) { | ||
113 | - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net", | ||
114 | - "a valid IPv6 prefix"); | ||
115 | - goto out; | ||
116 | - } | ||
117 | + substrings = g_strsplit(ip6_net, "/", 2); | ||
118 | + if (!substrings || !substrings[0]) { | ||
119 | + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net", | ||
120 | + "a valid IPv6 prefix"); | ||
121 | + goto out; | ||
122 | + } | ||
123 | |||
124 | - prefix_addr = substrings[0]; | ||
125 | + prefix_addr = substrings[0]; | ||
126 | |||
127 | - /* Handle user-specified prefix length. */ | ||
128 | - if (substrings[1] && | ||
129 | - qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) | ||
130 | - { | ||
131 | - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, | ||
132 | - "ipv6-prefixlen", "a number"); | ||
133 | - goto out; | ||
134 | - } | ||
135 | - | 76 | - |
136 | - qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort); | 77 | struct IgbVfState { |
137 | - qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len, | 78 | PCIDevice parent_obj; |
138 | - &error_abort); | ||
139 | - qemu_opt_unset(opts, "ipv6-net"); | ||
140 | + /* Handle user-specified prefix length. */ | ||
141 | + if (substrings[1] && | ||
142 | + qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) | ||
143 | + { | ||
144 | + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, | ||
145 | + "ipv6-prefixlen", "a number"); | ||
146 | + goto out; | ||
147 | } | ||
148 | + | ||
149 | + qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort); | ||
150 | + qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len, | ||
151 | + &error_abort); | ||
152 | + qemu_opt_unset(opts, "ipv6-net"); | ||
153 | } | ||
154 | |||
155 | /* Create an ID for -net if the user did not specify one */ | ||
156 | @@ -XXX,XX +XXX,XX @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp) | ||
157 | |||
158 | static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) | ||
159 | { | ||
160 | + const char *type = qemu_opt_get(opts, "type"); | ||
161 | + | ||
162 | + if (type && is_help_option(type)) { | ||
163 | + show_netdevs(); | ||
164 | + exit(0); | ||
165 | + } | ||
166 | return net_client_init(opts, true, errp); | ||
167 | } | ||
168 | 79 | ||
169 | -- | 80 | -- |
170 | 2.7.4 | 81 | 2.7.4 |
171 | 82 | ||
172 | 83 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
6 | --- | ||
7 | hw/net/igb_core.c | 96 +++++++++++++++++++++++++++---------------------------- | ||
8 | 1 file changed, 48 insertions(+), 48 deletions(-) | ||
9 | |||
10 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
11 | index XXXXXXX..XXXXXXX 100644 | ||
12 | --- a/hw/net/igb_core.c | ||
13 | +++ b/hw/net/igb_core.c | ||
14 | @@ -XXX,XX +XXX,XX @@ static const uint32_t igb_mac_reg_init[] = { | ||
15 | [VMOLR0 ... VMOLR0 + 7] = 0x2600 | E1000_VMOLR_STRCRC, | ||
16 | [RPLOLR] = E1000_RPLOLR_STRCRC, | ||
17 | [RLPML] = 0x2600, | ||
18 | - [TXCTL0] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
19 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
20 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
21 | - [TXCTL1] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
22 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
23 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
24 | - [TXCTL2] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
25 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
26 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
27 | - [TXCTL3] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
28 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
29 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
30 | - [TXCTL4] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
31 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
32 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
33 | - [TXCTL5] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
34 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
35 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
36 | - [TXCTL6] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
37 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
38 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
39 | - [TXCTL7] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
40 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
41 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
42 | - [TXCTL8] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
43 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
44 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
45 | - [TXCTL9] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
46 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
47 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
48 | - [TXCTL10] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
49 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
50 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
51 | - [TXCTL11] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
52 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
53 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
54 | - [TXCTL12] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
55 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
56 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
57 | - [TXCTL13] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
58 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
59 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
60 | - [TXCTL14] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
61 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
62 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
63 | - [TXCTL15] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
64 | - E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
65 | - E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
66 | + [TXCTL0] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
67 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
68 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
69 | + [TXCTL1] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
70 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
71 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
72 | + [TXCTL2] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
73 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
74 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
75 | + [TXCTL3] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
76 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
77 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
78 | + [TXCTL4] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
79 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
80 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
81 | + [TXCTL5] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
82 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
83 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
84 | + [TXCTL6] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
85 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
86 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
87 | + [TXCTL7] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
88 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
89 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
90 | + [TXCTL8] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
91 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
92 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
93 | + [TXCTL9] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
94 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
95 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
96 | + [TXCTL10] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
97 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
98 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
99 | + [TXCTL11] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
100 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
101 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
102 | + [TXCTL12] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
103 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
104 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
105 | + [TXCTL13] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
106 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
107 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
108 | + [TXCTL14] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
109 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
110 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
111 | + [TXCTL15] = E1000_DCA_TXCTRL_DATA_RRO_EN | | ||
112 | + E1000_DCA_TXCTRL_TX_WB_RO_EN | | ||
113 | + E1000_DCA_TXCTRL_DESC_RRO_EN, | ||
114 | }; | ||
115 | |||
116 | static void igb_reset(IGBCore *core, bool sw) | ||
117 | -- | ||
118 | 2.7.4 | ||
119 | |||
120 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Section 7.3.4.1 says: | ||
4 | > When auto-clear is enabled for an interrupt cause, the EICR bit is | ||
5 | > set when a cause event mapped to this vector occurs. When the EITR | ||
6 | > Counter reaches zero, the MSI-X message is sent on PCIe. Then the | ||
7 | > EICR bit is cleared and enabled to be set by a new cause event | ||
8 | |||
9 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
10 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
11 | --- | ||
12 | hw/net/igb_core.c | 21 ++++++++++++--------- | ||
13 | 1 file changed, 12 insertions(+), 9 deletions(-) | ||
14 | |||
15 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/net/igb_core.c | ||
18 | +++ b/hw/net/igb_core.c | ||
19 | @@ -XXX,XX +XXX,XX @@ igb_lower_legacy_irq(IGBCore *core) | ||
20 | pci_set_irq(core->owner, 0); | ||
21 | } | ||
22 | |||
23 | -static void igb_msix_notify(IGBCore *core, unsigned int vector) | ||
24 | +static void igb_msix_notify(IGBCore *core, unsigned int cause) | ||
25 | { | ||
26 | PCIDevice *dev = core->owner; | ||
27 | uint16_t vfn; | ||
28 | + uint32_t effective_eiac; | ||
29 | + unsigned int vector; | ||
30 | |||
31 | - vfn = 8 - (vector + 2) / IGBVF_MSIX_VEC_NUM; | ||
32 | + vfn = 8 - (cause + 2) / IGBVF_MSIX_VEC_NUM; | ||
33 | if (vfn < pcie_sriov_num_vfs(core->owner)) { | ||
34 | dev = pcie_sriov_get_vf_at_index(core->owner, vfn); | ||
35 | assert(dev); | ||
36 | - vector = (vector + 2) % IGBVF_MSIX_VEC_NUM; | ||
37 | - } else if (vector >= IGB_MSIX_VEC_NUM) { | ||
38 | + vector = (cause + 2) % IGBVF_MSIX_VEC_NUM; | ||
39 | + } else if (cause >= IGB_MSIX_VEC_NUM) { | ||
40 | qemu_log_mask(LOG_GUEST_ERROR, | ||
41 | "igb: Tried to use vector unavailable for PF"); | ||
42 | return; | ||
43 | + } else { | ||
44 | + vector = cause; | ||
45 | } | ||
46 | |||
47 | msix_notify(dev, vector); | ||
48 | + | ||
49 | + trace_e1000e_irq_icr_clear_eiac(core->mac[EICR], core->mac[EIAC]); | ||
50 | + effective_eiac = core->mac[EIAC] & BIT(cause); | ||
51 | + core->mac[EICR] &= ~effective_eiac; | ||
52 | } | ||
53 | |||
54 | static inline void | ||
55 | @@ -XXX,XX +XXX,XX @@ igb_eitr_should_postpone(IGBCore *core, int idx) | ||
56 | static void igb_send_msix(IGBCore *core) | ||
57 | { | ||
58 | uint32_t causes = core->mac[EICR] & core->mac[EIMS]; | ||
59 | - uint32_t effective_eiac; | ||
60 | int vector; | ||
61 | |||
62 | for (vector = 0; vector < IGB_INTR_NUM; ++vector) { | ||
63 | @@ -XXX,XX +XXX,XX @@ static void igb_send_msix(IGBCore *core) | ||
64 | |||
65 | trace_e1000e_irq_msix_notify_vec(vector); | ||
66 | igb_msix_notify(core, vector); | ||
67 | - | ||
68 | - trace_e1000e_irq_icr_clear_eiac(core->mac[EICR], core->mac[EIAC]); | ||
69 | - effective_eiac = core->mac[EIAC] & BIT(vector); | ||
70 | - core->mac[EICR] &= ~effective_eiac; | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | -- | ||
75 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Rename variable "n" to "causes", which properly represents the content | ||
4 | of the variable. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
8 | --- | ||
9 | hw/net/e1000e_core.c | 18 +++++++++--------- | ||
10 | 1 file changed, 9 insertions(+), 9 deletions(-) | ||
11 | |||
12 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/net/e1000e_core.c | ||
15 | +++ b/hw/net/e1000e_core.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static ssize_t | ||
17 | e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt, | ||
18 | bool has_vnet) | ||
19 | { | ||
20 | - uint32_t n = 0; | ||
21 | + uint32_t causes = 0; | ||
22 | uint8_t buf[ETH_ZLEN]; | ||
23 | struct iovec min_iov; | ||
24 | size_t size, orig_size; | ||
25 | @@ -XXX,XX +XXX,XX @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt, | ||
26 | |||
27 | /* Perform small receive detection (RSRPD) */ | ||
28 | if (total_size < core->mac[RSRPD]) { | ||
29 | - n |= E1000_ICS_SRPD; | ||
30 | + causes |= E1000_ICS_SRPD; | ||
31 | } | ||
32 | |||
33 | /* Perform ACK receive detection */ | ||
34 | if (!(core->mac[RFCTL] & E1000_RFCTL_ACK_DIS) && | ||
35 | (e1000e_is_tcp_ack(core, core->rx_pkt))) { | ||
36 | - n |= E1000_ICS_ACK; | ||
37 | + causes |= E1000_ICS_ACK; | ||
38 | } | ||
39 | |||
40 | /* Check if receive descriptor minimum threshold hit */ | ||
41 | rdmts_hit = e1000e_rx_descr_threshold_hit(core, rxr.i); | ||
42 | - n |= e1000e_rx_wb_interrupt_cause(core, rxr.i->idx, rdmts_hit); | ||
43 | + causes |= e1000e_rx_wb_interrupt_cause(core, rxr.i->idx, rdmts_hit); | ||
44 | |||
45 | trace_e1000e_rx_written_to_guest(rxr.i->idx); | ||
46 | } else { | ||
47 | - n |= E1000_ICS_RXO; | ||
48 | + causes |= E1000_ICS_RXO; | ||
49 | retval = 0; | ||
50 | |||
51 | trace_e1000e_rx_not_written_to_guest(rxr.i->idx); | ||
52 | } | ||
53 | |||
54 | - if (!e1000e_intrmgr_delay_rx_causes(core, &n)) { | ||
55 | - trace_e1000e_rx_interrupt_set(n); | ||
56 | - e1000e_set_interrupt_cause(core, n); | ||
57 | + if (!e1000e_intrmgr_delay_rx_causes(core, &causes)) { | ||
58 | + trace_e1000e_rx_interrupt_set(causes); | ||
59 | + e1000e_set_interrupt_cause(core, causes); | ||
60 | } else { | ||
61 | - trace_e1000e_rx_interrupt_delayed(n); | ||
62 | + trace_e1000e_rx_interrupt_delayed(causes); | ||
63 | } | ||
64 | |||
65 | return retval; | ||
66 | -- | ||
67 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Rename variable "n" to "causes", which properly represents the content | ||
4 | of the variable. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
8 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
9 | --- | ||
10 | hw/net/igb_core.c | 12 ++++++------ | ||
11 | 1 file changed, 6 insertions(+), 6 deletions(-) | ||
12 | |||
13 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/hw/net/igb_core.c | ||
16 | +++ b/hw/net/igb_core.c | ||
17 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
18 | bool has_vnet, bool *external_tx) | ||
19 | { | ||
20 | uint16_t queues = 0; | ||
21 | - uint32_t n = 0; | ||
22 | + uint32_t causes = 0; | ||
23 | union { | ||
24 | L2Header l2_header; | ||
25 | uint8_t octets[ETH_ZLEN]; | ||
26 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
27 | e1000x_fcs_len(core->mac); | ||
28 | |||
29 | if (!igb_has_rxbufs(core, rxr.i, total_size)) { | ||
30 | - n |= E1000_ICS_RXO; | ||
31 | + causes |= E1000_ICS_RXO; | ||
32 | trace_e1000e_rx_not_written_to_guest(rxr.i->idx); | ||
33 | continue; | ||
34 | } | ||
35 | |||
36 | - n |= E1000_ICR_RXDW; | ||
37 | + causes |= E1000_ICR_RXDW; | ||
38 | |||
39 | igb_rx_fix_l4_csum(core, core->rx_pkt); | ||
40 | igb_write_packet_to_guest(core, core->rx_pkt, &rxr, &rss_info); | ||
41 | |||
42 | /* Check if receive descriptor minimum threshold hit */ | ||
43 | if (igb_rx_descr_threshold_hit(core, rxr.i)) { | ||
44 | - n |= E1000_ICS_RXDMT0; | ||
45 | + causes |= E1000_ICS_RXDMT0; | ||
46 | } | ||
47 | |||
48 | core->mac[EICR] |= igb_rx_wb_eic(core, rxr.i->idx); | ||
49 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
50 | trace_e1000e_rx_written_to_guest(rxr.i->idx); | ||
51 | } | ||
52 | |||
53 | - trace_e1000e_rx_interrupt_set(n); | ||
54 | - igb_set_interrupt_cause(core, n); | ||
55 | + trace_e1000e_rx_interrupt_set(causes); | ||
56 | + igb_set_interrupt_cause(core, causes); | ||
57 | |||
58 | return orig_size; | ||
59 | } | ||
60 | -- | ||
61 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | The uses of uint8_t pointers were misleading as they are never accessed | ||
4 | as an array of octets and it even require more strict alignment to | ||
5 | access as struct eth_header. | ||
6 | |||
7 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
9 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
10 | --- | ||
11 | include/net/eth.h | 4 ++-- | ||
12 | net/eth.c | 6 +++--- | ||
13 | 2 files changed, 5 insertions(+), 5 deletions(-) | ||
14 | |||
15 | diff --git a/include/net/eth.h b/include/net/eth.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/include/net/eth.h | ||
18 | +++ b/include/net/eth.h | ||
19 | @@ -XXX,XX +XXX,XX @@ eth_get_pkt_tci(const void *p) | ||
20 | |||
21 | size_t | ||
22 | eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
23 | - uint8_t *new_ehdr_buf, | ||
24 | + void *new_ehdr_buf, | ||
25 | uint16_t *payload_offset, uint16_t *tci); | ||
26 | |||
27 | size_t | ||
28 | eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
29 | - uint16_t vet, uint8_t *new_ehdr_buf, | ||
30 | + uint16_t vet, void *new_ehdr_buf, | ||
31 | uint16_t *payload_offset, uint16_t *tci); | ||
32 | |||
33 | uint16_t | ||
34 | diff --git a/net/eth.c b/net/eth.c | ||
35 | index XXXXXXX..XXXXXXX 100644 | ||
36 | --- a/net/eth.c | ||
37 | +++ b/net/eth.c | ||
38 | @@ -XXX,XX +XXX,XX @@ void eth_get_protocols(const struct iovec *iov, size_t iovcnt, size_t iovoff, | ||
39 | |||
40 | size_t | ||
41 | eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
42 | - uint8_t *new_ehdr_buf, | ||
43 | + void *new_ehdr_buf, | ||
44 | uint16_t *payload_offset, uint16_t *tci) | ||
45 | { | ||
46 | struct vlan_header vlan_hdr; | ||
47 | - struct eth_header *new_ehdr = (struct eth_header *) new_ehdr_buf; | ||
48 | + struct eth_header *new_ehdr = new_ehdr_buf; | ||
49 | |||
50 | size_t copied = iov_to_buf(iov, iovcnt, iovoff, | ||
51 | new_ehdr, sizeof(*new_ehdr)); | ||
52 | @@ -XXX,XX +XXX,XX @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
53 | |||
54 | size_t | ||
55 | eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
56 | - uint16_t vet, uint8_t *new_ehdr_buf, | ||
57 | + uint16_t vet, void *new_ehdr_buf, | ||
58 | uint16_t *payload_offset, uint16_t *tci) | ||
59 | { | ||
60 | struct vlan_header vlan_hdr; | ||
61 | -- | ||
62 | 2.7.4 | ||
63 | |||
64 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | It is possible to have another VLAN tag even if the packet is already | ||
4 | tagged. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
8 | --- | ||
9 | hw/net/net_tx_pkt.c | 16 +++++++--------- | ||
10 | include/net/eth.h | 4 ++-- | ||
11 | net/eth.c | 22 ++++++---------------- | ||
12 | 3 files changed, 15 insertions(+), 27 deletions(-) | ||
13 | |||
14 | diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/net/net_tx_pkt.c | ||
17 | +++ b/hw/net/net_tx_pkt.c | ||
18 | @@ -XXX,XX +XXX,XX @@ struct NetTxPkt { | ||
19 | |||
20 | struct iovec *vec; | ||
21 | |||
22 | - uint8_t l2_hdr[ETH_MAX_L2_HDR_LEN]; | ||
23 | + struct { | ||
24 | + struct eth_header eth; | ||
25 | + struct vlan_header vlan[3]; | ||
26 | + } l2_hdr; | ||
27 | union { | ||
28 | struct ip_header ip; | ||
29 | struct ip6_header ip6; | ||
30 | @@ -XXX,XX +XXX,XX @@ bool net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable, | ||
31 | void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt, | ||
32 | uint16_t vlan, uint16_t vlan_ethtype) | ||
33 | { | ||
34 | - bool is_new; | ||
35 | assert(pkt); | ||
36 | |||
37 | eth_setup_vlan_headers(pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_base, | ||
38 | - vlan, vlan_ethtype, &is_new); | ||
39 | + &pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len, | ||
40 | + vlan, vlan_ethtype); | ||
41 | |||
42 | - /* update l2hdrlen */ | ||
43 | - if (is_new) { | ||
44 | - pkt->hdr_len += sizeof(struct vlan_header); | ||
45 | - pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len += | ||
46 | - sizeof(struct vlan_header); | ||
47 | - } | ||
48 | + pkt->hdr_len += sizeof(struct vlan_header); | ||
49 | } | ||
50 | |||
51 | bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, void *base, size_t len) | ||
52 | diff --git a/include/net/eth.h b/include/net/eth.h | ||
53 | index XXXXXXX..XXXXXXX 100644 | ||
54 | --- a/include/net/eth.h | ||
55 | +++ b/include/net/eth.h | ||
56 | @@ -XXX,XX +XXX,XX @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
57 | uint16_t | ||
58 | eth_get_l3_proto(const struct iovec *l2hdr_iov, int iovcnt, size_t l2hdr_len); | ||
59 | |||
60 | -void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, | ||
61 | - uint16_t vlan_ethtype, bool *is_new); | ||
62 | +void eth_setup_vlan_headers(struct eth_header *ehdr, size_t *ehdr_size, | ||
63 | + uint16_t vlan_tag, uint16_t vlan_ethtype); | ||
64 | |||
65 | |||
66 | uint8_t eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto); | ||
67 | diff --git a/net/eth.c b/net/eth.c | ||
68 | index XXXXXXX..XXXXXXX 100644 | ||
69 | --- a/net/eth.c | ||
70 | +++ b/net/eth.c | ||
71 | @@ -XXX,XX +XXX,XX @@ | ||
72 | #include "net/checksum.h" | ||
73 | #include "net/tap.h" | ||
74 | |||
75 | -void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, | ||
76 | - uint16_t vlan_ethtype, bool *is_new) | ||
77 | +void eth_setup_vlan_headers(struct eth_header *ehdr, size_t *ehdr_size, | ||
78 | + uint16_t vlan_tag, uint16_t vlan_ethtype) | ||
79 | { | ||
80 | struct vlan_header *vhdr = PKT_GET_VLAN_HDR(ehdr); | ||
81 | |||
82 | - switch (be16_to_cpu(ehdr->h_proto)) { | ||
83 | - case ETH_P_VLAN: | ||
84 | - case ETH_P_DVLAN: | ||
85 | - /* vlan hdr exists */ | ||
86 | - *is_new = false; | ||
87 | - break; | ||
88 | - | ||
89 | - default: | ||
90 | - /* No VLAN header, put a new one */ | ||
91 | - vhdr->h_proto = ehdr->h_proto; | ||
92 | - ehdr->h_proto = cpu_to_be16(vlan_ethtype); | ||
93 | - *is_new = true; | ||
94 | - break; | ||
95 | - } | ||
96 | + memmove(vhdr + 1, vhdr, *ehdr_size - ETH_HLEN); | ||
97 | vhdr->h_tci = cpu_to_be16(vlan_tag); | ||
98 | + vhdr->h_proto = ehdr->h_proto; | ||
99 | + ehdr->h_proto = cpu_to_be16(vlan_ethtype); | ||
100 | + *ehdr_size += sizeof(*vhdr); | ||
101 | } | ||
102 | |||
103 | uint8_t | ||
104 | -- | ||
105 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | eth_strip_vlan and eth_strip_vlan_ex refers to ehdr_buf as struct | ||
4 | eth_header. Enforce alignment for the structure. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
8 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
9 | --- | ||
10 | hw/net/net_rx_pkt.c | 11 +++++++---- | ||
11 | 1 file changed, 7 insertions(+), 4 deletions(-) | ||
12 | |||
13 | diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/hw/net/net_rx_pkt.c | ||
16 | +++ b/hw/net/net_rx_pkt.c | ||
17 | @@ -XXX,XX +XXX,XX @@ | ||
18 | |||
19 | struct NetRxPkt { | ||
20 | struct virtio_net_hdr virt_hdr; | ||
21 | - uint8_t ehdr_buf[sizeof(struct eth_header) + sizeof(struct vlan_header)]; | ||
22 | + struct { | ||
23 | + struct eth_header eth; | ||
24 | + struct vlan_header vlan; | ||
25 | + } ehdr_buf; | ||
26 | struct iovec *vec; | ||
27 | uint16_t vec_len_total; | ||
28 | uint16_t vec_len; | ||
29 | @@ -XXX,XX +XXX,XX @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt, | ||
30 | if (pkt->ehdr_buf_len) { | ||
31 | net_rx_pkt_iovec_realloc(pkt, iovcnt + 1); | ||
32 | |||
33 | - pkt->vec[0].iov_base = pkt->ehdr_buf; | ||
34 | + pkt->vec[0].iov_base = &pkt->ehdr_buf; | ||
35 | pkt->vec[0].iov_len = pkt->ehdr_buf_len; | ||
36 | |||
37 | pkt->tot_len = pllen + pkt->ehdr_buf_len; | ||
38 | @@ -XXX,XX +XXX,XX @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt, | ||
39 | assert(pkt); | ||
40 | |||
41 | if (strip_vlan) { | ||
42 | - pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf, | ||
43 | + pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, &pkt->ehdr_buf, | ||
44 | &ploff, &tci); | ||
45 | } else { | ||
46 | pkt->ehdr_buf_len = 0; | ||
47 | @@ -XXX,XX +XXX,XX @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt, | ||
48 | |||
49 | if (strip_vlan) { | ||
50 | pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet, | ||
51 | - pkt->ehdr_buf, | ||
52 | + &pkt->ehdr_buf, | ||
53 | &ploff, &tci); | ||
54 | } else { | ||
55 | pkt->ehdr_buf_len = 0; | ||
56 | -- | ||
57 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | GPIE.Multiple_MSIX is not set by default, and needs to be set to get | ||
4 | interrupts from multiple MSI-X vectors. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
8 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
9 | --- | ||
10 | tests/qtest/libqos/igb.c | 1 + | ||
11 | 1 file changed, 1 insertion(+) | ||
12 | |||
13 | diff --git a/tests/qtest/libqos/igb.c b/tests/qtest/libqos/igb.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/tests/qtest/libqos/igb.c | ||
16 | +++ b/tests/qtest/libqos/igb.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static void igb_pci_start_hw(QOSGraphObject *obj) | ||
18 | e1000e_macreg_write(&d->e1000e, E1000_RCTL, E1000_RCTL_EN); | ||
19 | |||
20 | /* Enable all interrupts */ | ||
21 | + e1000e_macreg_write(&d->e1000e, E1000_GPIE, E1000_GPIE_MSIX_MODE); | ||
22 | e1000e_macreg_write(&d->e1000e, E1000_IMS, 0xFFFFFFFF); | ||
23 | e1000e_macreg_write(&d->e1000e, E1000_EIMS, 0xFFFFFFFF); | ||
24 | |||
25 | -- | ||
26 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
6 | --- | ||
7 | hw/net/igb_core.c | 9 +++++++-- | ||
8 | 1 file changed, 7 insertions(+), 2 deletions(-) | ||
9 | |||
10 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
11 | index XXXXXXX..XXXXXXX 100644 | ||
12 | --- a/hw/net/igb_core.c | ||
13 | +++ b/hw/net/igb_core.c | ||
14 | @@ -XXX,XX +XXX,XX @@ igb_update_interrupt_state(IGBCore *core) | ||
15 | |||
16 | icr = core->mac[ICR] & core->mac[IMS]; | ||
17 | |||
18 | - if (msix_enabled(core->owner)) { | ||
19 | + if (core->mac[GPIE] & E1000_GPIE_MSIX_MODE) { | ||
20 | if (icr) { | ||
21 | causes = 0; | ||
22 | if (icr & E1000_ICR_DRSTA) { | ||
23 | @@ -XXX,XX +XXX,XX @@ igb_update_interrupt_state(IGBCore *core) | ||
24 | trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS], | ||
25 | core->mac[ICR], core->mac[IMS]); | ||
26 | |||
27 | - if (msi_enabled(core->owner)) { | ||
28 | + if (msix_enabled(core->owner)) { | ||
29 | + if (icr) { | ||
30 | + trace_e1000e_irq_msix_notify_vec(0); | ||
31 | + msix_notify(core->owner, 0); | ||
32 | + } | ||
33 | + } else if (msi_enabled(core->owner)) { | ||
34 | if (icr) { | ||
35 | msi_notify(core->owner, 0); | ||
36 | } | ||
37 | -- | ||
38 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | e1000e does not support using UDP for RSS hash, but igb does. | ||
4 | |||
5 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
6 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
8 | --- | ||
9 | hw/net/igb_core.c | 16 ++++++++++++++++ | ||
10 | hw/net/igb_regs.h | 3 +++ | ||
11 | 2 files changed, 19 insertions(+) | ||
12 | |||
13 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/hw/net/igb_core.c | ||
16 | +++ b/hw/net/igb_core.c | ||
17 | @@ -XXX,XX +XXX,XX @@ igb_rss_get_hash_type(IGBCore *core, struct NetRxPkt *pkt) | ||
18 | return E1000_MRQ_RSS_TYPE_IPV4TCP; | ||
19 | } | ||
20 | |||
21 | + if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP && | ||
22 | + (core->mac[MRQC] & E1000_MRQC_RSS_FIELD_IPV4_UDP)) { | ||
23 | + return E1000_MRQ_RSS_TYPE_IPV4UDP; | ||
24 | + } | ||
25 | + | ||
26 | if (E1000_MRQC_EN_IPV4(core->mac[MRQC])) { | ||
27 | return E1000_MRQ_RSS_TYPE_IPV4; | ||
28 | } | ||
29 | @@ -XXX,XX +XXX,XX @@ igb_rss_get_hash_type(IGBCore *core, struct NetRxPkt *pkt) | ||
30 | return E1000_MRQ_RSS_TYPE_IPV6TCPEX; | ||
31 | } | ||
32 | |||
33 | + if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP && | ||
34 | + (core->mac[MRQC] & E1000_MRQC_RSS_FIELD_IPV6_UDP)) { | ||
35 | + return E1000_MRQ_RSS_TYPE_IPV6UDP; | ||
36 | + } | ||
37 | + | ||
38 | if (E1000_MRQC_EN_IPV6EX(core->mac[MRQC])) { | ||
39 | return E1000_MRQ_RSS_TYPE_IPV6EX; | ||
40 | } | ||
41 | @@ -XXX,XX +XXX,XX @@ igb_rss_calc_hash(IGBCore *core, struct NetRxPkt *pkt, E1000E_RSSInfo *info) | ||
42 | case E1000_MRQ_RSS_TYPE_IPV6EX: | ||
43 | type = NetPktRssIpV6Ex; | ||
44 | break; | ||
45 | + case E1000_MRQ_RSS_TYPE_IPV4UDP: | ||
46 | + type = NetPktRssIpV4Udp; | ||
47 | + break; | ||
48 | + case E1000_MRQ_RSS_TYPE_IPV6UDP: | ||
49 | + type = NetPktRssIpV6Udp; | ||
50 | + break; | ||
51 | default: | ||
52 | assert(false); | ||
53 | return 0; | ||
54 | diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/hw/net/igb_regs.h | ||
57 | +++ b/hw/net/igb_regs.h | ||
58 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
59 | |||
60 | #define E1000_RSS_QUEUE(reta, hash) (E1000_RETA_VAL(reta, hash) & 0x0F) | ||
61 | |||
62 | +#define E1000_MRQ_RSS_TYPE_IPV4UDP 7 | ||
63 | +#define E1000_MRQ_RSS_TYPE_IPV6UDP 8 | ||
64 | + | ||
65 | #define E1000_STATUS_IOV_MODE 0x00040000 | ||
66 | |||
67 | #define E1000_STATUS_NUM_VFS_SHIFT 14 | ||
68 | -- | ||
69 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
6 | --- | ||
7 | hw/net/e1000e_core.c | 5 ++++ | ||
8 | hw/net/igb_core.c | 15 +++++++++++- | ||
9 | hw/net/igb_regs.h | 1 + | ||
10 | hw/net/net_rx_pkt.c | 64 ++++++++++++++++++++++++++++++++++++++++++--------- | ||
11 | include/net/eth.h | 4 +++- | ||
12 | include/qemu/crc32c.h | 1 + | ||
13 | net/eth.c | 4 ++++ | ||
14 | util/crc32c.c | 8 +++++++ | ||
15 | 8 files changed, 89 insertions(+), 13 deletions(-) | ||
16 | |||
17 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/hw/net/e1000e_core.c | ||
20 | +++ b/hw/net/e1000e_core.c | ||
21 | @@ -XXX,XX +XXX,XX @@ e1000e_verify_csum_in_sw(E1000ECore *core, | ||
22 | return; | ||
23 | } | ||
24 | |||
25 | + if (l4hdr_proto != ETH_L4_HDR_PROTO_TCP && | ||
26 | + l4hdr_proto != ETH_L4_HDR_PROTO_UDP) { | ||
27 | + return; | ||
28 | + } | ||
29 | + | ||
30 | if (!net_rx_pkt_validate_l4_csum(pkt, &csum_valid)) { | ||
31 | trace_e1000e_rx_metadata_l4_csum_validation_failed(); | ||
32 | return; | ||
33 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/hw/net/igb_core.c | ||
36 | +++ b/hw/net/igb_core.c | ||
37 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
38 | uint16_t *vlan_tag) | ||
39 | { | ||
40 | struct virtio_net_hdr *vhdr; | ||
41 | - bool hasip4, hasip6; | ||
42 | + bool hasip4, hasip6, csum_valid; | ||
43 | EthL4HdrProto l4hdr_proto; | ||
44 | |||
45 | *status_flags = E1000_RXD_STAT_DD; | ||
46 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
47 | *pkt_info |= E1000_ADVRXD_PKT_UDP; | ||
48 | break; | ||
49 | |||
50 | + case ETH_L4_HDR_PROTO_SCTP: | ||
51 | + *pkt_info |= E1000_ADVRXD_PKT_SCTP; | ||
52 | + break; | ||
53 | + | ||
54 | default: | ||
55 | break; | ||
56 | } | ||
57 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
58 | |||
59 | if (igb_rx_l4_cso_enabled(core)) { | ||
60 | switch (l4hdr_proto) { | ||
61 | + case ETH_L4_HDR_PROTO_SCTP: | ||
62 | + if (!net_rx_pkt_validate_l4_csum(pkt, &csum_valid)) { | ||
63 | + trace_e1000e_rx_metadata_l4_csum_validation_failed(); | ||
64 | + goto func_exit; | ||
65 | + } | ||
66 | + if (!csum_valid) { | ||
67 | + *status_flags |= E1000_RXDEXT_STATERR_TCPE; | ||
68 | + } | ||
69 | + /* fall through */ | ||
70 | case ETH_L4_HDR_PROTO_TCP: | ||
71 | *status_flags |= E1000_RXD_STAT_TCPCS; | ||
72 | break; | ||
73 | diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h | ||
74 | index XXXXXXX..XXXXXXX 100644 | ||
75 | --- a/hw/net/igb_regs.h | ||
76 | +++ b/hw/net/igb_regs.h | ||
77 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
78 | #define E1000_ADVRXD_PKT_IP6 BIT(6) | ||
79 | #define E1000_ADVRXD_PKT_TCP BIT(8) | ||
80 | #define E1000_ADVRXD_PKT_UDP BIT(9) | ||
81 | +#define E1000_ADVRXD_PKT_SCTP BIT(10) | ||
82 | |||
83 | static inline uint8_t igb_ivar_entry_rx(uint8_t i) | ||
84 | { | ||
85 | diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c | ||
86 | index XXXXXXX..XXXXXXX 100644 | ||
87 | --- a/hw/net/net_rx_pkt.c | ||
88 | +++ b/hw/net/net_rx_pkt.c | ||
89 | @@ -XXX,XX +XXX,XX @@ | ||
90 | */ | ||
91 | |||
92 | #include "qemu/osdep.h" | ||
93 | +#include "qemu/crc32c.h" | ||
94 | #include "trace.h" | ||
95 | #include "net_rx_pkt.h" | ||
96 | #include "net/checksum.h" | ||
97 | @@ -XXX,XX +XXX,XX @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt) | ||
98 | return csum; | ||
99 | } | ||
100 | |||
101 | -bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid) | ||
102 | +static bool | ||
103 | +_net_rx_pkt_validate_sctp_sum(struct NetRxPkt *pkt) | ||
104 | { | ||
105 | - uint16_t csum; | ||
106 | + size_t csum_off; | ||
107 | + size_t off = pkt->l4hdr_off; | ||
108 | + size_t vec_len = pkt->vec_len; | ||
109 | + struct iovec *vec; | ||
110 | + uint32_t calculated = 0; | ||
111 | + uint32_t original; | ||
112 | + bool valid; | ||
113 | |||
114 | - trace_net_rx_pkt_l4_csum_validate_entry(); | ||
115 | + for (vec = pkt->vec; vec->iov_len < off; vec++) { | ||
116 | + off -= vec->iov_len; | ||
117 | + vec_len--; | ||
118 | + } | ||
119 | |||
120 | - if (pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_TCP && | ||
121 | - pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_UDP) { | ||
122 | - trace_net_rx_pkt_l4_csum_validate_not_xxp(); | ||
123 | + csum_off = off + 8; | ||
124 | + | ||
125 | + if (!iov_to_buf(vec, vec_len, csum_off, &original, sizeof(original))) { | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | - if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP && | ||
130 | - pkt->l4hdr_info.hdr.udp.uh_sum == 0) { | ||
131 | - trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum(); | ||
132 | + if (!iov_from_buf(vec, vec_len, csum_off, | ||
133 | + &calculated, sizeof(calculated))) { | ||
134 | return false; | ||
135 | } | ||
136 | |||
137 | + calculated = crc32c(0xffffffff, | ||
138 | + (uint8_t *)vec->iov_base + off, vec->iov_len - off); | ||
139 | + calculated = iov_crc32c(calculated ^ 0xffffffff, vec + 1, vec_len - 1); | ||
140 | + valid = calculated == le32_to_cpu(original); | ||
141 | + iov_from_buf(vec, vec_len, csum_off, &original, sizeof(original)); | ||
142 | + | ||
143 | + return valid; | ||
144 | +} | ||
145 | + | ||
146 | +bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid) | ||
147 | +{ | ||
148 | + uint32_t csum; | ||
149 | + | ||
150 | + trace_net_rx_pkt_l4_csum_validate_entry(); | ||
151 | + | ||
152 | if (pkt->hasip4 && pkt->ip4hdr_info.fragment) { | ||
153 | trace_net_rx_pkt_l4_csum_validate_ip4_fragment(); | ||
154 | return false; | ||
155 | } | ||
156 | |||
157 | - csum = _net_rx_pkt_calc_l4_csum(pkt); | ||
158 | + switch (pkt->l4hdr_info.proto) { | ||
159 | + case ETH_L4_HDR_PROTO_UDP: | ||
160 | + if (pkt->l4hdr_info.hdr.udp.uh_sum == 0) { | ||
161 | + trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum(); | ||
162 | + return false; | ||
163 | + } | ||
164 | + /* fall through */ | ||
165 | + case ETH_L4_HDR_PROTO_TCP: | ||
166 | + csum = _net_rx_pkt_calc_l4_csum(pkt); | ||
167 | + *csum_valid = ((csum == 0) || (csum == 0xFFFF)); | ||
168 | + break; | ||
169 | + | ||
170 | + case ETH_L4_HDR_PROTO_SCTP: | ||
171 | + *csum_valid = _net_rx_pkt_validate_sctp_sum(pkt); | ||
172 | + break; | ||
173 | |||
174 | - *csum_valid = ((csum == 0) || (csum == 0xFFFF)); | ||
175 | + default: | ||
176 | + trace_net_rx_pkt_l4_csum_validate_not_xxp(); | ||
177 | + return false; | ||
178 | + } | ||
179 | |||
180 | trace_net_rx_pkt_l4_csum_validate_csum(*csum_valid); | ||
181 | |||
182 | diff --git a/include/net/eth.h b/include/net/eth.h | ||
183 | index XXXXXXX..XXXXXXX 100644 | ||
184 | --- a/include/net/eth.h | ||
185 | +++ b/include/net/eth.h | ||
186 | @@ -XXX,XX +XXX,XX @@ struct tcp_hdr { | ||
187 | #define IP_HEADER_VERSION_6 (6) | ||
188 | #define IP_PROTO_TCP (6) | ||
189 | #define IP_PROTO_UDP (17) | ||
190 | +#define IP_PROTO_SCTP (132) | ||
191 | #define IPTOS_ECN_MASK 0x03 | ||
192 | #define IPTOS_ECN(x) ((x) & IPTOS_ECN_MASK) | ||
193 | #define IPTOS_ECN_CE 0x03 | ||
194 | @@ -XXX,XX +XXX,XX @@ typedef struct eth_ip4_hdr_info_st { | ||
195 | typedef enum EthL4HdrProto { | ||
196 | ETH_L4_HDR_PROTO_INVALID, | ||
197 | ETH_L4_HDR_PROTO_TCP, | ||
198 | - ETH_L4_HDR_PROTO_UDP | ||
199 | + ETH_L4_HDR_PROTO_UDP, | ||
200 | + ETH_L4_HDR_PROTO_SCTP | ||
201 | } EthL4HdrProto; | ||
202 | |||
203 | typedef struct eth_l4_hdr_info_st { | ||
204 | diff --git a/include/qemu/crc32c.h b/include/qemu/crc32c.h | ||
205 | index XXXXXXX..XXXXXXX 100644 | ||
206 | --- a/include/qemu/crc32c.h | ||
207 | +++ b/include/qemu/crc32c.h | ||
208 | @@ -XXX,XX +XXX,XX @@ | ||
209 | |||
210 | |||
211 | uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length); | ||
212 | +uint32_t iov_crc32c(uint32_t crc, const struct iovec *iov, size_t iov_cnt); | ||
213 | |||
214 | #endif | ||
215 | diff --git a/net/eth.c b/net/eth.c | ||
216 | index XXXXXXX..XXXXXXX 100644 | ||
217 | --- a/net/eth.c | ||
218 | +++ b/net/eth.c | ||
219 | @@ -XXX,XX +XXX,XX @@ void eth_get_protocols(const struct iovec *iov, size_t iovcnt, size_t iovoff, | ||
220 | *l5hdr_off = *l4hdr_off + sizeof(l4hdr_info->hdr.udp); | ||
221 | } | ||
222 | break; | ||
223 | + | ||
224 | + case IP_PROTO_SCTP: | ||
225 | + l4hdr_info->proto = ETH_L4_HDR_PROTO_SCTP; | ||
226 | + break; | ||
227 | } | ||
228 | } | ||
229 | |||
230 | diff --git a/util/crc32c.c b/util/crc32c.c | ||
231 | index XXXXXXX..XXXXXXX 100644 | ||
232 | --- a/util/crc32c.c | ||
233 | +++ b/util/crc32c.c | ||
234 | @@ -XXX,XX +XXX,XX @@ uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length) | ||
235 | return crc^0xffffffff; | ||
236 | } | ||
237 | |||
238 | +uint32_t iov_crc32c(uint32_t crc, const struct iovec *iov, size_t iov_cnt) | ||
239 | +{ | ||
240 | + while (iov_cnt--) { | ||
241 | + crc = crc32c(crc, iov->iov_base, iov->iov_len) ^ 0xffffffff; | ||
242 | + iov++; | ||
243 | + } | ||
244 | + return crc ^ 0xffffffff; | ||
245 | +} | ||
246 | -- | ||
247 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
6 | --- | ||
7 | hw/net/igb_core.c | 12 +++++++----- | ||
8 | hw/net/net_tx_pkt.c | 18 ++++++++++++++++++ | ||
9 | hw/net/net_tx_pkt.h | 8 ++++++++ | ||
10 | 3 files changed, 33 insertions(+), 5 deletions(-) | ||
11 | |||
12 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/net/igb_core.c | ||
15 | +++ b/hw/net/igb_core.c | ||
16 | @@ -XXX,XX +XXX,XX @@ igb_tx_insert_vlan(IGBCore *core, uint16_t qn, struct igb_tx *tx, | ||
17 | static bool | ||
18 | igb_setup_tx_offloads(IGBCore *core, struct igb_tx *tx) | ||
19 | { | ||
20 | + uint32_t idx = (tx->first_olinfo_status >> 4) & 1; | ||
21 | + | ||
22 | if (tx->first_cmd_type_len & E1000_ADVTXD_DCMD_TSE) { | ||
23 | - uint32_t idx = (tx->first_olinfo_status >> 4) & 1; | ||
24 | uint32_t mss = tx->ctx[idx].mss_l4len_idx >> E1000_ADVTXD_MSS_SHIFT; | ||
25 | if (!net_tx_pkt_build_vheader(tx->tx_pkt, true, true, mss)) { | ||
26 | return false; | ||
27 | @@ -XXX,XX +XXX,XX @@ igb_setup_tx_offloads(IGBCore *core, struct igb_tx *tx) | ||
28 | return true; | ||
29 | } | ||
30 | |||
31 | - if (tx->first_olinfo_status & E1000_ADVTXD_POTS_TXSM) { | ||
32 | - if (!net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0)) { | ||
33 | - return false; | ||
34 | - } | ||
35 | + if ((tx->first_olinfo_status & E1000_ADVTXD_POTS_TXSM) && | ||
36 | + !((tx->ctx[idx].type_tucmd_mlhl & E1000_ADVTXD_TUCMD_L4T_SCTP) ? | ||
37 | + net_tx_pkt_update_sctp_checksum(tx->tx_pkt) : | ||
38 | + net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0))) { | ||
39 | + return false; | ||
40 | } | ||
41 | |||
42 | if (tx->first_olinfo_status & E1000_ADVTXD_POTS_IXSM) { | ||
43 | diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/hw/net/net_tx_pkt.c | ||
46 | +++ b/hw/net/net_tx_pkt.c | ||
47 | @@ -XXX,XX +XXX,XX @@ | ||
48 | */ | ||
49 | |||
50 | #include "qemu/osdep.h" | ||
51 | +#include "qemu/crc32c.h" | ||
52 | #include "net/eth.h" | ||
53 | #include "net/checksum.h" | ||
54 | #include "net/tap.h" | ||
55 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_update_ip_checksums(struct NetTxPkt *pkt) | ||
56 | pkt->virt_hdr.csum_offset, &csum, sizeof(csum)); | ||
57 | } | ||
58 | |||
59 | +bool net_tx_pkt_update_sctp_checksum(struct NetTxPkt *pkt) | ||
60 | +{ | ||
61 | + uint32_t csum = 0; | ||
62 | + struct iovec *pl_start_frag = pkt->vec + NET_TX_PKT_PL_START_FRAG; | ||
63 | + | ||
64 | + if (iov_from_buf(pl_start_frag, pkt->payload_frags, 8, &csum, sizeof(csum)) < sizeof(csum)) { | ||
65 | + return false; | ||
66 | + } | ||
67 | + | ||
68 | + csum = cpu_to_le32(iov_crc32c(0xffffffff, pl_start_frag, pkt->payload_frags)); | ||
69 | + if (iov_from_buf(pl_start_frag, pkt->payload_frags, 8, &csum, sizeof(csum)) < sizeof(csum)) { | ||
70 | + return false; | ||
71 | + } | ||
72 | + | ||
73 | + return true; | ||
74 | +} | ||
75 | + | ||
76 | static void net_tx_pkt_calculate_hdr_len(struct NetTxPkt *pkt) | ||
77 | { | ||
78 | pkt->hdr_len = pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len + | ||
79 | diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h | ||
80 | index XXXXXXX..XXXXXXX 100644 | ||
81 | --- a/hw/net/net_tx_pkt.h | ||
82 | +++ b/hw/net/net_tx_pkt.h | ||
83 | @@ -XXX,XX +XXX,XX @@ void net_tx_pkt_update_ip_checksums(struct NetTxPkt *pkt); | ||
84 | void net_tx_pkt_update_ip_hdr_checksum(struct NetTxPkt *pkt); | ||
85 | |||
86 | /** | ||
87 | + * Calculate the SCTP checksum. | ||
88 | + * | ||
89 | + * @pkt: packet | ||
90 | + * | ||
91 | + */ | ||
92 | +bool net_tx_pkt_update_sctp_checksum(struct NetTxPkt *pkt); | ||
93 | + | ||
94 | +/** | ||
95 | * get length of all populated data. | ||
96 | * | ||
97 | * @pkt: packet | ||
98 | -- | ||
99 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
5 | --- | ||
6 | hw/net/e1000e_core.c | 3 ++- | ||
7 | hw/net/igb_core.c | 14 ++++++++++++-- | ||
8 | hw/net/net_rx_pkt.c | 15 ++++++--------- | ||
9 | hw/net/net_rx_pkt.h | 19 ++++++++++--------- | ||
10 | include/net/eth.h | 4 ++-- | ||
11 | net/eth.c | 52 +++++++++++++++++++++++++++++++++------------------- | ||
12 | 6 files changed, 65 insertions(+), 42 deletions(-) | ||
13 | |||
14 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/net/e1000e_core.c | ||
17 | +++ b/hw/net/e1000e_core.c | ||
18 | @@ -XXX,XX +XXX,XX @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt, | ||
19 | } | ||
20 | |||
21 | net_rx_pkt_attach_iovec_ex(core->rx_pkt, iov, iovcnt, iov_ofs, | ||
22 | - e1000x_vlan_enabled(core->mac), core->mac[VET]); | ||
23 | + e1000x_vlan_enabled(core->mac) ? 0 : -1, | ||
24 | + core->mac[VET], 0); | ||
25 | |||
26 | e1000e_rss_parse_packet(core, core->rx_pkt, &rss_info); | ||
27 | e1000e_rx_ring_init(core, &rxr, rss_info.queue); | ||
28 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/hw/net/igb_core.c | ||
31 | +++ b/hw/net/igb_core.c | ||
32 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
33 | E1000E_RxRing rxr; | ||
34 | E1000E_RSSInfo rss_info; | ||
35 | size_t total_size; | ||
36 | + int strip_vlan_index; | ||
37 | int i; | ||
38 | |||
39 | trace_e1000e_rx_receive_iov(iovcnt); | ||
40 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
41 | |||
42 | igb_rx_ring_init(core, &rxr, i); | ||
43 | |||
44 | + if (!igb_rx_strip_vlan(core, rxr.i)) { | ||
45 | + strip_vlan_index = -1; | ||
46 | + } else if (core->mac[CTRL_EXT] & BIT(26)) { | ||
47 | + strip_vlan_index = 1; | ||
48 | + } else { | ||
49 | + strip_vlan_index = 0; | ||
50 | + } | ||
51 | + | ||
52 | net_rx_pkt_attach_iovec_ex(core->rx_pkt, iov, iovcnt, iov_ofs, | ||
53 | - igb_rx_strip_vlan(core, rxr.i), | ||
54 | - core->mac[VET] & 0xffff); | ||
55 | + strip_vlan_index, | ||
56 | + core->mac[VET] & 0xffff, | ||
57 | + core->mac[VET] >> 16); | ||
58 | |||
59 | total_size = net_rx_pkt_get_total_len(core->rx_pkt) + | ||
60 | e1000x_fcs_len(core->mac); | ||
61 | diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c | ||
62 | index XXXXXXX..XXXXXXX 100644 | ||
63 | --- a/hw/net/net_rx_pkt.c | ||
64 | +++ b/hw/net/net_rx_pkt.c | ||
65 | @@ -XXX,XX +XXX,XX @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt, | ||
66 | |||
67 | void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt, | ||
68 | const struct iovec *iov, int iovcnt, | ||
69 | - size_t iovoff, bool strip_vlan, | ||
70 | - uint16_t vet) | ||
71 | + size_t iovoff, int strip_vlan_index, | ||
72 | + uint16_t vet, uint16_t vet_ext) | ||
73 | { | ||
74 | uint16_t tci = 0; | ||
75 | uint16_t ploff = iovoff; | ||
76 | assert(pkt); | ||
77 | |||
78 | - if (strip_vlan) { | ||
79 | - pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet, | ||
80 | - &pkt->ehdr_buf, | ||
81 | - &ploff, &tci); | ||
82 | - } else { | ||
83 | - pkt->ehdr_buf_len = 0; | ||
84 | - } | ||
85 | + pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, | ||
86 | + strip_vlan_index, vet, vet_ext, | ||
87 | + &pkt->ehdr_buf, | ||
88 | + &ploff, &tci); | ||
89 | |||
90 | pkt->tci = tci; | ||
91 | |||
92 | diff --git a/hw/net/net_rx_pkt.h b/hw/net/net_rx_pkt.h | ||
93 | index XXXXXXX..XXXXXXX 100644 | ||
94 | --- a/hw/net/net_rx_pkt.h | ||
95 | +++ b/hw/net/net_rx_pkt.h | ||
96 | @@ -XXX,XX +XXX,XX @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt, | ||
97 | /** | ||
98 | * attach scatter-gather data to rx packet | ||
99 | * | ||
100 | -* @pkt: packet | ||
101 | -* @iov: received data scatter-gather list | ||
102 | -* @iovcnt number of elements in iov | ||
103 | -* @iovoff data start offset in the iov | ||
104 | -* @strip_vlan: should the module strip vlan from data | ||
105 | -* @vet: VLAN tag Ethernet type | ||
106 | +* @pkt: packet | ||
107 | +* @iov: received data scatter-gather list | ||
108 | +* @iovcnt: number of elements in iov | ||
109 | +* @iovoff: data start offset in the iov | ||
110 | +* @strip_vlan_index: index of Q tag if it is to be stripped. negative otherwise. | ||
111 | +* @vet: VLAN tag Ethernet type | ||
112 | +* @vet_ext: outer VLAN tag Ethernet type | ||
113 | * | ||
114 | */ | ||
115 | void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt, | ||
116 | - const struct iovec *iov, int iovcnt, | ||
117 | - size_t iovoff, bool strip_vlan, | ||
118 | - uint16_t vet); | ||
119 | + const struct iovec *iov, int iovcnt, | ||
120 | + size_t iovoff, int strip_vlan_index, | ||
121 | + uint16_t vet, uint16_t vet_ext); | ||
122 | |||
123 | /** | ||
124 | * attach data to rx packet | ||
125 | diff --git a/include/net/eth.h b/include/net/eth.h | ||
126 | index XXXXXXX..XXXXXXX 100644 | ||
127 | --- a/include/net/eth.h | ||
128 | +++ b/include/net/eth.h | ||
129 | @@ -XXX,XX +XXX,XX @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
130 | uint16_t *payload_offset, uint16_t *tci); | ||
131 | |||
132 | size_t | ||
133 | -eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
134 | - uint16_t vet, void *new_ehdr_buf, | ||
135 | +eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, int index, | ||
136 | + uint16_t vet, uint16_t vet_ext, void *new_ehdr_buf, | ||
137 | uint16_t *payload_offset, uint16_t *tci); | ||
138 | |||
139 | uint16_t | ||
140 | diff --git a/net/eth.c b/net/eth.c | ||
141 | index XXXXXXX..XXXXXXX 100644 | ||
142 | --- a/net/eth.c | ||
143 | +++ b/net/eth.c | ||
144 | @@ -XXX,XX +XXX,XX @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
145 | } | ||
146 | |||
147 | size_t | ||
148 | -eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, | ||
149 | - uint16_t vet, void *new_ehdr_buf, | ||
150 | +eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, int index, | ||
151 | + uint16_t vet, uint16_t vet_ext, void *new_ehdr_buf, | ||
152 | uint16_t *payload_offset, uint16_t *tci) | ||
153 | { | ||
154 | struct vlan_header vlan_hdr; | ||
155 | - struct eth_header *new_ehdr = (struct eth_header *) new_ehdr_buf; | ||
156 | - | ||
157 | - size_t copied = iov_to_buf(iov, iovcnt, iovoff, | ||
158 | - new_ehdr, sizeof(*new_ehdr)); | ||
159 | - | ||
160 | - if (copied < sizeof(*new_ehdr)) { | ||
161 | - return 0; | ||
162 | - } | ||
163 | + uint16_t *new_ehdr_proto; | ||
164 | + size_t new_ehdr_size; | ||
165 | + size_t copied; | ||
166 | |||
167 | - if (be16_to_cpu(new_ehdr->h_proto) == vet) { | ||
168 | - copied = iov_to_buf(iov, iovcnt, iovoff + sizeof(*new_ehdr), | ||
169 | - &vlan_hdr, sizeof(vlan_hdr)); | ||
170 | + switch (index) { | ||
171 | + case 0: | ||
172 | + new_ehdr_proto = &PKT_GET_ETH_HDR(new_ehdr_buf)->h_proto; | ||
173 | + new_ehdr_size = sizeof(struct eth_header); | ||
174 | + copied = iov_to_buf(iov, iovcnt, iovoff, new_ehdr_buf, new_ehdr_size); | ||
175 | + break; | ||
176 | |||
177 | - if (copied < sizeof(vlan_hdr)) { | ||
178 | + case 1: | ||
179 | + new_ehdr_proto = &PKT_GET_VLAN_HDR(new_ehdr_buf)->h_proto; | ||
180 | + new_ehdr_size = sizeof(struct eth_header) + sizeof(struct vlan_header); | ||
181 | + copied = iov_to_buf(iov, iovcnt, iovoff, new_ehdr_buf, new_ehdr_size); | ||
182 | + if (be16_to_cpu(PKT_GET_ETH_HDR(new_ehdr_buf)->h_proto) != vet_ext) { | ||
183 | return 0; | ||
184 | } | ||
185 | + break; | ||
186 | |||
187 | - new_ehdr->h_proto = vlan_hdr.h_proto; | ||
188 | + default: | ||
189 | + return 0; | ||
190 | + } | ||
191 | |||
192 | - *tci = be16_to_cpu(vlan_hdr.h_tci); | ||
193 | - *payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr); | ||
194 | - return sizeof(struct eth_header); | ||
195 | + if (copied < new_ehdr_size || be16_to_cpu(*new_ehdr_proto) != vet) { | ||
196 | + return 0; | ||
197 | + } | ||
198 | + | ||
199 | + copied = iov_to_buf(iov, iovcnt, iovoff + new_ehdr_size, | ||
200 | + &vlan_hdr, sizeof(vlan_hdr)); | ||
201 | + if (copied < sizeof(vlan_hdr)) { | ||
202 | + return 0; | ||
203 | } | ||
204 | |||
205 | - return 0; | ||
206 | + *new_ehdr_proto = vlan_hdr.h_proto; | ||
207 | + *payload_offset = iovoff + new_ehdr_size + sizeof(vlan_hdr); | ||
208 | + *tci = be16_to_cpu(vlan_hdr.h_tci); | ||
209 | + | ||
210 | + return new_ehdr_size; | ||
211 | } | ||
212 | |||
213 | void | ||
214 | -- | ||
215 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
5 | --- | ||
6 | hw/net/igb_core.c | 23 ++++++++++++++++++----- | ||
7 | 1 file changed, 18 insertions(+), 5 deletions(-) | ||
8 | |||
9 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
10 | index XXXXXXX..XXXXXXX 100644 | ||
11 | --- a/hw/net/igb_core.c | ||
12 | +++ b/hw/net/igb_core.c | ||
13 | @@ -XXX,XX +XXX,XX @@ typedef struct IGBTxPktVmdqCallbackContext { | ||
14 | |||
15 | typedef struct L2Header { | ||
16 | struct eth_header eth; | ||
17 | - struct vlan_header vlan; | ||
18 | + struct vlan_header vlan[2]; | ||
19 | } L2Header; | ||
20 | |||
21 | static ssize_t | ||
22 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
23 | uint32_t f, ra[2], *macp, rctl = core->mac[RCTL]; | ||
24 | uint16_t queues = 0; | ||
25 | uint16_t oversized = 0; | ||
26 | - uint16_t vid = be16_to_cpu(l2_header->vlan.h_tci) & VLAN_VID_MASK; | ||
27 | + size_t vlan_num = 0; | ||
28 | int i; | ||
29 | |||
30 | memset(rss_info, 0, sizeof(E1000E_RSSInfo)); | ||
31 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
32 | *external_tx = true; | ||
33 | } | ||
34 | |||
35 | - if (e1000x_is_vlan_packet(ehdr, core->mac[VET] & 0xffff) && | ||
36 | - !e1000x_rx_vlan_filter(core->mac, PKT_GET_VLAN_HDR(ehdr))) { | ||
37 | + if (core->mac[CTRL_EXT] & BIT(26)) { | ||
38 | + if (be16_to_cpu(ehdr->h_proto) == core->mac[VET] >> 16 && | ||
39 | + be16_to_cpu(l2_header->vlan[0].h_proto) == (core->mac[VET] & 0xffff)) { | ||
40 | + vlan_num = 2; | ||
41 | + } | ||
42 | + } else { | ||
43 | + if (be16_to_cpu(ehdr->h_proto) == (core->mac[VET] & 0xffff)) { | ||
44 | + vlan_num = 1; | ||
45 | + } | ||
46 | + } | ||
47 | + | ||
48 | + if (vlan_num && | ||
49 | + !e1000x_rx_vlan_filter(core->mac, l2_header->vlan + vlan_num - 1)) { | ||
50 | return queues; | ||
51 | } | ||
52 | |||
53 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
54 | if (e1000x_vlan_rx_filter_enabled(core->mac)) { | ||
55 | uint16_t mask = 0; | ||
56 | |||
57 | - if (e1000x_is_vlan_packet(ehdr, core->mac[VET] & 0xffff)) { | ||
58 | + if (vlan_num) { | ||
59 | + uint16_t vid = be16_to_cpu(l2_header->vlan[vlan_num - 1].h_tci) & VLAN_VID_MASK; | ||
60 | + | ||
61 | for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { | ||
62 | if ((core->mac[VLVF0 + i] & E1000_VLVF_VLANID_MASK) == vid && | ||
63 | (core->mac[VLVF0 + i] & E1000_VLVF_VLANID_ENABLE)) { | ||
64 | -- | ||
65 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | igb has a configurable size limit for LPE, and uses different limits | ||
4 | depending on whether the packet is treated as a VLAN packet. | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
8 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
9 | --- | ||
10 | hw/net/igb_core.c | 36 +++++++++++++++++++++--------------- | ||
11 | 1 file changed, 21 insertions(+), 15 deletions(-) | ||
12 | |||
13 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/hw/net/igb_core.c | ||
16 | +++ b/hw/net/igb_core.c | ||
17 | @@ -XXX,XX +XXX,XX @@ igb_rx_l4_cso_enabled(IGBCore *core) | ||
18 | return !!(core->mac[RXCSUM] & E1000_RXCSUM_TUOFLD); | ||
19 | } | ||
20 | |||
21 | -static bool | ||
22 | -igb_rx_is_oversized(IGBCore *core, uint16_t qn, size_t size) | ||
23 | +static bool igb_rx_is_oversized(IGBCore *core, const struct eth_header *ehdr, | ||
24 | + size_t size, size_t vlan_num, | ||
25 | + bool lpe, uint16_t rlpml) | ||
26 | { | ||
27 | - uint16_t pool = qn % IGB_NUM_VM_POOLS; | ||
28 | - bool lpe = !!(core->mac[VMOLR0 + pool] & E1000_VMOLR_LPE); | ||
29 | - int max_ethernet_lpe_size = | ||
30 | - core->mac[VMOLR0 + pool] & E1000_VMOLR_RLPML_MASK; | ||
31 | - int max_ethernet_vlan_size = 1522; | ||
32 | - | ||
33 | - return size > (lpe ? max_ethernet_lpe_size : max_ethernet_vlan_size); | ||
34 | + size_t vlan_header_size = sizeof(struct vlan_header) * vlan_num; | ||
35 | + size_t header_size = sizeof(struct eth_header) + vlan_header_size; | ||
36 | + return lpe ? size + ETH_FCS_LEN > rlpml : size > header_size + ETH_MTU; | ||
37 | } | ||
38 | |||
39 | static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
40 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
41 | uint16_t queues = 0; | ||
42 | uint16_t oversized = 0; | ||
43 | size_t vlan_num = 0; | ||
44 | + bool lpe; | ||
45 | + uint16_t rlpml; | ||
46 | int i; | ||
47 | |||
48 | memset(rss_info, 0, sizeof(E1000E_RSSInfo)); | ||
49 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
50 | } | ||
51 | } | ||
52 | |||
53 | + lpe = !!(core->mac[RCTL] & E1000_RCTL_LPE); | ||
54 | + rlpml = core->mac[RLPML]; | ||
55 | + if (!(core->mac[RCTL] & E1000_RCTL_SBP) && | ||
56 | + igb_rx_is_oversized(core, ehdr, size, vlan_num, lpe, rlpml)) { | ||
57 | + trace_e1000x_rx_oversized(size); | ||
58 | + return queues; | ||
59 | + } | ||
60 | + | ||
61 | if (vlan_num && | ||
62 | !e1000x_rx_vlan_filter(core->mac, l2_header->vlan + vlan_num - 1)) { | ||
63 | return queues; | ||
64 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
65 | queues &= core->mac[VFRE]; | ||
66 | if (queues) { | ||
67 | for (i = 0; i < IGB_NUM_VM_POOLS; i++) { | ||
68 | - if ((queues & BIT(i)) && igb_rx_is_oversized(core, i, size)) { | ||
69 | + lpe = !!(core->mac[VMOLR0 + i] & E1000_VMOLR_LPE); | ||
70 | + rlpml = core->mac[VMOLR0 + i] & E1000_VMOLR_RLPML_MASK; | ||
71 | + if ((queues & BIT(i)) && | ||
72 | + igb_rx_is_oversized(core, ehdr, size, vlan_num, | ||
73 | + lpe, rlpml)) { | ||
74 | oversized |= BIT(i); | ||
75 | } | ||
76 | } | ||
77 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
78 | iov_to_buf(iov, iovcnt, iov_ofs, &buf, sizeof(buf.l2_header)); | ||
79 | } | ||
80 | |||
81 | - /* Discard oversized packets if !LPE and !SBP. */ | ||
82 | - if (e1000x_is_oversized(core->mac, size)) { | ||
83 | - return orig_size; | ||
84 | - } | ||
85 | - | ||
86 | net_rx_pkt_set_packet_type(core->rx_pkt, | ||
87 | get_eth_packet_type(&buf.l2_header.eth)); | ||
88 | net_rx_pkt_set_protocols(core->rx_pkt, iov, iovcnt, iov_ofs); | ||
89 | -- | ||
90 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
5 | --- | ||
6 | hw/net/igb_common.h | 16 ++++--- | ||
7 | hw/net/igb_core.c | 129 ++++++++++++++++++++++++++++++++++++++-------------- | ||
8 | hw/net/igb_regs.h | 23 ++++++++++ | ||
9 | 3 files changed, 127 insertions(+), 41 deletions(-) | ||
10 | |||
11 | diff --git a/hw/net/igb_common.h b/hw/net/igb_common.h | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/hw/net/igb_common.h | ||
14 | +++ b/hw/net/igb_common.h | ||
15 | @@ -XXX,XX +XXX,XX @@ | ||
16 | defreg_indexeda(x, 0), defreg_indexeda(x, 1), \ | ||
17 | defreg_indexeda(x, 2), defreg_indexeda(x, 3) | ||
18 | |||
19 | -#define defregv(x) defreg_indexed(x, 0), defreg_indexed(x, 1), \ | ||
20 | +#define defreg8(x) defreg_indexed(x, 0), defreg_indexed(x, 1), \ | ||
21 | defreg_indexed(x, 2), defreg_indexed(x, 3), \ | ||
22 | defreg_indexed(x, 4), defreg_indexed(x, 5), \ | ||
23 | defreg_indexed(x, 6), defreg_indexed(x, 7) | ||
24 | @@ -XXX,XX +XXX,XX @@ enum { | ||
25 | defreg(EICS), defreg(EIMS), defreg(EIMC), defreg(EIAM), | ||
26 | defreg(EICR), defreg(IVAR_MISC), defreg(GPIE), | ||
27 | |||
28 | + defreg(TSYNCRXCFG), defreg8(ETQF), | ||
29 | + | ||
30 | defreg(RXPBS), defregd(RDBAL), defregd(RDBAH), defregd(RDLEN), | ||
31 | defregd(SRRCTL), defregd(RDH), defregd(RDT), | ||
32 | defregd(RXDCTL), defregd(RXCTL), defregd(RQDPC), defreg(RA2), | ||
33 | @@ -XXX,XX +XXX,XX @@ enum { | ||
34 | |||
35 | defreg(VT_CTL), | ||
36 | |||
37 | - defregv(P2VMAILBOX), defregv(V2PMAILBOX), defreg(MBVFICR), defreg(MBVFIMR), | ||
38 | + defreg8(P2VMAILBOX), defreg8(V2PMAILBOX), defreg(MBVFICR), defreg(MBVFIMR), | ||
39 | defreg(VFLRE), defreg(VFRE), defreg(VFTE), defreg(WVBR), | ||
40 | defreg(QDE), defreg(DTXSWC), defreg_indexed(VLVF, 0), | ||
41 | - defregv(VMOLR), defreg(RPLOLR), defregv(VMBMEM), defregv(VMVIR), | ||
42 | + defreg8(VMOLR), defreg(RPLOLR), defreg8(VMBMEM), defreg8(VMVIR), | ||
43 | |||
44 | - defregv(PVTCTRL), defregv(PVTEICS), defregv(PVTEIMS), defregv(PVTEIMC), | ||
45 | - defregv(PVTEIAC), defregv(PVTEIAM), defregv(PVTEICR), defregv(PVFGPRC), | ||
46 | - defregv(PVFGPTC), defregv(PVFGORC), defregv(PVFGOTC), defregv(PVFMPRC), | ||
47 | - defregv(PVFGPRLBC), defregv(PVFGPTLBC), defregv(PVFGORLBC), defregv(PVFGOTLBC), | ||
48 | + defreg8(PVTCTRL), defreg8(PVTEICS), defreg8(PVTEIMS), defreg8(PVTEIMC), | ||
49 | + defreg8(PVTEIAC), defreg8(PVTEIAM), defreg8(PVTEICR), defreg8(PVFGPRC), | ||
50 | + defreg8(PVFGPTC), defreg8(PVFGORC), defreg8(PVFGOTC), defreg8(PVFMPRC), | ||
51 | + defreg8(PVFGPRLBC), defreg8(PVFGPTLBC), defreg8(PVFGORLBC), defreg8(PVFGOTLBC), | ||
52 | |||
53 | defreg(MTA_A), | ||
54 | |||
55 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
56 | index XXXXXXX..XXXXXXX 100644 | ||
57 | --- a/hw/net/igb_core.c | ||
58 | +++ b/hw/net/igb_core.c | ||
59 | @@ -XXX,XX +XXX,XX @@ typedef struct L2Header { | ||
60 | struct vlan_header vlan[2]; | ||
61 | } L2Header; | ||
62 | |||
63 | +typedef struct PTP2 { | ||
64 | + uint8_t message_id_transport_specific; | ||
65 | + uint8_t version_ptp; | ||
66 | + uint16_t message_length; | ||
67 | + uint8_t subdomain_number; | ||
68 | + uint8_t reserved0; | ||
69 | + uint16_t flags; | ||
70 | + uint64_t correction; | ||
71 | + uint8_t reserved1[5]; | ||
72 | + uint8_t source_communication_technology; | ||
73 | + uint32_t source_uuid_lo; | ||
74 | + uint16_t source_uuid_hi; | ||
75 | + uint16_t source_port_id; | ||
76 | + uint16_t sequence_id; | ||
77 | + uint8_t control; | ||
78 | + uint8_t log_message_period; | ||
79 | +} PTP2; | ||
80 | + | ||
81 | static ssize_t | ||
82 | igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
83 | bool has_vnet, bool *external_tx); | ||
84 | @@ -XXX,XX +XXX,XX @@ static bool igb_rx_is_oversized(IGBCore *core, const struct eth_header *ehdr, | ||
85 | return lpe ? size + ETH_FCS_LEN > rlpml : size > header_size + ETH_MTU; | ||
86 | } | ||
87 | |||
88 | -static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
89 | - size_t size, E1000E_RSSInfo *rss_info, | ||
90 | - bool *external_tx) | ||
91 | +static uint16_t igb_receive_assign(IGBCore *core, const struct iovec *iov, | ||
92 | + size_t iovcnt, size_t iov_ofs, | ||
93 | + const L2Header *l2_header, size_t size, | ||
94 | + E1000E_RSSInfo *rss_info, | ||
95 | + uint16_t *etqf, bool *ts, bool *external_tx) | ||
96 | { | ||
97 | static const int ta_shift[] = { 4, 3, 2, 0 }; | ||
98 | const struct eth_header *ehdr = &l2_header->eth; | ||
99 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
100 | uint16_t queues = 0; | ||
101 | uint16_t oversized = 0; | ||
102 | size_t vlan_num = 0; | ||
103 | + PTP2 ptp2; | ||
104 | bool lpe; | ||
105 | uint16_t rlpml; | ||
106 | int i; | ||
107 | |||
108 | memset(rss_info, 0, sizeof(E1000E_RSSInfo)); | ||
109 | + *ts = false; | ||
110 | |||
111 | if (external_tx) { | ||
112 | *external_tx = true; | ||
113 | @@ -XXX,XX +XXX,XX @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header, | ||
114 | return queues; | ||
115 | } | ||
116 | |||
117 | + for (*etqf = 0; *etqf < 8; (*etqf)++) { | ||
118 | + if ((core->mac[ETQF0 + *etqf] & E1000_ETQF_FILTER_ENABLE) && | ||
119 | + be16_to_cpu(ehdr->h_proto) == (core->mac[ETQF0 + *etqf] & E1000_ETQF_ETYPE_MASK)) { | ||
120 | + if ((core->mac[ETQF0 + *etqf] & E1000_ETQF_1588) && | ||
121 | + (core->mac[TSYNCRXCTL] & E1000_TSYNCRXCTL_ENABLED) && | ||
122 | + !(core->mac[TSYNCRXCTL] & E1000_TSYNCRXCTL_VALID) && | ||
123 | + iov_to_buf(iov, iovcnt, iov_ofs + ETH_HLEN, &ptp2, sizeof(ptp2)) >= sizeof(ptp2) && | ||
124 | + (ptp2.version_ptp & 15) == 2 && | ||
125 | + ptp2.message_id_transport_specific == ((core->mac[TSYNCRXCFG] >> 8) & 255)) { | ||
126 | + e1000x_timestamp(core->mac, core->timadj, RXSTMPL, RXSTMPH); | ||
127 | + *ts = true; | ||
128 | + core->mac[TSYNCRXCTL] |= E1000_TSYNCRXCTL_VALID; | ||
129 | + core->mac[RXSATRL] = le32_to_cpu(ptp2.source_uuid_lo); | ||
130 | + core->mac[RXSATRH] = le16_to_cpu(ptp2.source_uuid_hi) | | ||
131 | + (le16_to_cpu(ptp2.sequence_id) << 16); | ||
132 | + } | ||
133 | + break; | ||
134 | + } | ||
135 | + } | ||
136 | + | ||
137 | if (vlan_num && | ||
138 | !e1000x_rx_vlan_filter(core->mac, l2_header->vlan + vlan_num - 1)) { | ||
139 | return queues; | ||
140 | @@ -XXX,XX +XXX,XX @@ static void | ||
141 | igb_build_rx_metadata(IGBCore *core, | ||
142 | struct NetRxPkt *pkt, | ||
143 | bool is_eop, | ||
144 | - const E1000E_RSSInfo *rss_info, | ||
145 | + const E1000E_RSSInfo *rss_info, uint16_t etqf, bool ts, | ||
146 | uint16_t *pkt_info, uint16_t *hdr_info, | ||
147 | uint32_t *rss, | ||
148 | uint32_t *status_flags, | ||
149 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
150 | if (pkt_info) { | ||
151 | *pkt_info = rss_info->enabled ? rss_info->type : 0; | ||
152 | |||
153 | - if (hasip4) { | ||
154 | - *pkt_info |= E1000_ADVRXD_PKT_IP4; | ||
155 | - } | ||
156 | + if (etqf < 8) { | ||
157 | + *pkt_info |= (BIT(11) | etqf) << 4; | ||
158 | + } else { | ||
159 | + if (hasip4) { | ||
160 | + *pkt_info |= E1000_ADVRXD_PKT_IP4; | ||
161 | + } | ||
162 | |||
163 | - if (hasip6) { | ||
164 | - *pkt_info |= E1000_ADVRXD_PKT_IP6; | ||
165 | - } | ||
166 | + if (hasip6) { | ||
167 | + *pkt_info |= E1000_ADVRXD_PKT_IP6; | ||
168 | + } | ||
169 | |||
170 | - switch (l4hdr_proto) { | ||
171 | - case ETH_L4_HDR_PROTO_TCP: | ||
172 | - *pkt_info |= E1000_ADVRXD_PKT_TCP; | ||
173 | - break; | ||
174 | + switch (l4hdr_proto) { | ||
175 | + case ETH_L4_HDR_PROTO_TCP: | ||
176 | + *pkt_info |= E1000_ADVRXD_PKT_TCP; | ||
177 | + break; | ||
178 | |||
179 | - case ETH_L4_HDR_PROTO_UDP: | ||
180 | - *pkt_info |= E1000_ADVRXD_PKT_UDP; | ||
181 | - break; | ||
182 | + case ETH_L4_HDR_PROTO_UDP: | ||
183 | + *pkt_info |= E1000_ADVRXD_PKT_UDP; | ||
184 | + break; | ||
185 | |||
186 | - case ETH_L4_HDR_PROTO_SCTP: | ||
187 | - *pkt_info |= E1000_ADVRXD_PKT_SCTP; | ||
188 | - break; | ||
189 | + case ETH_L4_HDR_PROTO_SCTP: | ||
190 | + *pkt_info |= E1000_ADVRXD_PKT_SCTP; | ||
191 | + break; | ||
192 | |||
193 | - default: | ||
194 | - break; | ||
195 | + default: | ||
196 | + break; | ||
197 | + } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | @@ -XXX,XX +XXX,XX @@ igb_build_rx_metadata(IGBCore *core, | ||
202 | *hdr_info = 0; | ||
203 | } | ||
204 | |||
205 | + if (ts) { | ||
206 | + *status_flags |= BIT(16); | ||
207 | + } | ||
208 | + | ||
209 | /* RX CSO information */ | ||
210 | if (hasip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_XSUM_DIS)) { | ||
211 | trace_e1000e_rx_metadata_ipv6_sum_disabled(); | ||
212 | @@ -XXX,XX +XXX,XX @@ func_exit: | ||
213 | static inline void | ||
214 | igb_write_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc, | ||
215 | struct NetRxPkt *pkt, | ||
216 | - const E1000E_RSSInfo *rss_info, | ||
217 | + const E1000E_RSSInfo *rss_info, uint16_t etqf, bool ts, | ||
218 | uint16_t length) | ||
219 | { | ||
220 | uint32_t status_flags, rss; | ||
221 | @@ -XXX,XX +XXX,XX @@ igb_write_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc, | ||
222 | desc->csum = 0; | ||
223 | |||
224 | igb_build_rx_metadata(core, pkt, pkt != NULL, | ||
225 | - rss_info, | ||
226 | + rss_info, etqf, ts, | ||
227 | NULL, NULL, &rss, | ||
228 | &status_flags, &ip_id, | ||
229 | &desc->special); | ||
230 | @@ -XXX,XX +XXX,XX @@ igb_write_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc, | ||
231 | static inline void | ||
232 | igb_write_adv_rx_descr(IGBCore *core, union e1000_adv_rx_desc *desc, | ||
233 | struct NetRxPkt *pkt, | ||
234 | - const E1000E_RSSInfo *rss_info, | ||
235 | + const E1000E_RSSInfo *rss_info, uint16_t etqf, bool ts, | ||
236 | uint16_t length) | ||
237 | { | ||
238 | memset(&desc->wb, 0, sizeof(desc->wb)); | ||
239 | @@ -XXX,XX +XXX,XX @@ igb_write_adv_rx_descr(IGBCore *core, union e1000_adv_rx_desc *desc, | ||
240 | desc->wb.upper.length = cpu_to_le16(length); | ||
241 | |||
242 | igb_build_rx_metadata(core, pkt, pkt != NULL, | ||
243 | - rss_info, | ||
244 | + rss_info, etqf, ts, | ||
245 | &desc->wb.lower.lo_dword.pkt_info, | ||
246 | &desc->wb.lower.lo_dword.hdr_info, | ||
247 | &desc->wb.lower.hi_dword.rss, | ||
248 | @@ -XXX,XX +XXX,XX @@ igb_write_adv_rx_descr(IGBCore *core, union e1000_adv_rx_desc *desc, | ||
249 | |||
250 | static inline void | ||
251 | igb_write_rx_descr(IGBCore *core, union e1000_rx_desc_union *desc, | ||
252 | -struct NetRxPkt *pkt, const E1000E_RSSInfo *rss_info, uint16_t length) | ||
253 | + struct NetRxPkt *pkt, const E1000E_RSSInfo *rss_info, | ||
254 | + uint16_t etqf, bool ts, uint16_t length) | ||
255 | { | ||
256 | if (igb_rx_use_legacy_descriptor(core)) { | ||
257 | - igb_write_lgcy_rx_descr(core, &desc->legacy, pkt, rss_info, length); | ||
258 | + igb_write_lgcy_rx_descr(core, &desc->legacy, pkt, rss_info, | ||
259 | + etqf, ts, length); | ||
260 | } else { | ||
261 | - igb_write_adv_rx_descr(core, &desc->adv, pkt, rss_info, length); | ||
262 | + igb_write_adv_rx_descr(core, &desc->adv, pkt, rss_info, | ||
263 | + etqf, ts, length); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | @@ -XXX,XX +XXX,XX @@ igb_rx_descr_threshold_hit(IGBCore *core, const E1000E_RingInfo *rxi) | ||
268 | static void | ||
269 | igb_write_packet_to_guest(IGBCore *core, struct NetRxPkt *pkt, | ||
270 | const E1000E_RxRing *rxr, | ||
271 | - const E1000E_RSSInfo *rss_info) | ||
272 | + const E1000E_RSSInfo *rss_info, | ||
273 | + uint16_t etqf, bool ts) | ||
274 | { | ||
275 | PCIDevice *d; | ||
276 | dma_addr_t base; | ||
277 | @@ -XXX,XX +XXX,XX @@ igb_write_packet_to_guest(IGBCore *core, struct NetRxPkt *pkt, | ||
278 | } | ||
279 | |||
280 | igb_write_rx_descr(core, &desc, is_last ? core->rx_pkt : NULL, | ||
281 | - rss_info, written); | ||
282 | + rss_info, etqf, ts, written); | ||
283 | igb_pci_dma_write_rx_desc(core, d, base, &desc, core->rx_desc_len); | ||
284 | |||
285 | igb_ring_advance(core, rxi, core->rx_desc_len / E1000_MIN_RX_DESC_LEN); | ||
286 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
287 | size_t iov_ofs = 0; | ||
288 | E1000E_RxRing rxr; | ||
289 | E1000E_RSSInfo rss_info; | ||
290 | + uint16_t etqf; | ||
291 | + bool ts; | ||
292 | size_t total_size; | ||
293 | int strip_vlan_index; | ||
294 | int i; | ||
295 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
296 | get_eth_packet_type(&buf.l2_header.eth)); | ||
297 | net_rx_pkt_set_protocols(core->rx_pkt, iov, iovcnt, iov_ofs); | ||
298 | |||
299 | - queues = igb_receive_assign(core, &buf.l2_header, size, | ||
300 | - &rss_info, external_tx); | ||
301 | + queues = igb_receive_assign(core, iov, iovcnt, iov_ofs, | ||
302 | + &buf.l2_header, size, | ||
303 | + &rss_info, &etqf, &ts, external_tx); | ||
304 | if (!queues) { | ||
305 | trace_e1000e_rx_flt_dropped(); | ||
306 | return orig_size; | ||
307 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
308 | causes |= E1000_ICR_RXDW; | ||
309 | |||
310 | igb_rx_fix_l4_csum(core, core->rx_pkt); | ||
311 | - igb_write_packet_to_guest(core, core->rx_pkt, &rxr, &rss_info); | ||
312 | + igb_write_packet_to_guest(core, core->rx_pkt, &rxr, &rss_info, etqf, ts); | ||
313 | |||
314 | /* Check if receive descriptor minimum threshold hit */ | ||
315 | if (igb_rx_descr_threshold_hit(core, rxr.i)) { | ||
316 | @@ -XXX,XX +XXX,XX @@ static const readops igb_macreg_readops[] = { | ||
317 | [EIAM] = igb_mac_readreg, | ||
318 | [IVAR0 ... IVAR0 + 7] = igb_mac_readreg, | ||
319 | igb_getreg(IVAR_MISC), | ||
320 | + igb_getreg(TSYNCRXCFG), | ||
321 | + [ETQF0 ... ETQF0 + 7] = igb_mac_readreg, | ||
322 | igb_getreg(VT_CTL), | ||
323 | [P2VMAILBOX0 ... P2VMAILBOX7] = igb_mac_readreg, | ||
324 | [V2PMAILBOX0 ... V2PMAILBOX7] = igb_mac_vfmailbox_read, | ||
325 | @@ -XXX,XX +XXX,XX @@ static const writeops igb_macreg_writeops[] = { | ||
326 | [EIMS] = igb_set_eims, | ||
327 | [IVAR0 ... IVAR0 + 7] = igb_mac_writereg, | ||
328 | igb_putreg(IVAR_MISC), | ||
329 | + igb_putreg(TSYNCRXCFG), | ||
330 | + [ETQF0 ... ETQF0 + 7] = igb_mac_writereg, | ||
331 | igb_putreg(VT_CTL), | ||
332 | [P2VMAILBOX0 ... P2VMAILBOX7] = igb_set_pfmailbox, | ||
333 | [V2PMAILBOX0 ... V2PMAILBOX7] = igb_set_vfmailbox, | ||
334 | diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h | ||
335 | index XXXXXXX..XXXXXXX 100644 | ||
336 | --- a/hw/net/igb_regs.h | ||
337 | +++ b/hw/net/igb_regs.h | ||
338 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
339 | #define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */ | ||
340 | #define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */ | ||
341 | |||
342 | +/* ETQF register bit definitions */ | ||
343 | +#define E1000_ETQF_FILTER_ENABLE BIT(26) | ||
344 | +#define E1000_ETQF_1588 BIT(30) | ||
345 | +#define E1000_ETQF_IMM_INT BIT(29) | ||
346 | +#define E1000_ETQF_QUEUE_ENABLE BIT(31) | ||
347 | +#define E1000_ETQF_QUEUE_SHIFT 16 | ||
348 | +#define E1000_ETQF_QUEUE_MASK 0x00070000 | ||
349 | +#define E1000_ETQF_ETYPE_MASK 0x0000FFFF | ||
350 | + | ||
351 | #define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */ | ||
352 | #define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */ | ||
353 | #define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ | ||
354 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
355 | #define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ | ||
356 | #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ | ||
357 | |||
358 | +#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */ | ||
359 | + | ||
360 | +/* Filtering Registers */ | ||
361 | +#define E1000_SAQF(_n) (0x5980 + 4 * (_n)) | ||
362 | +#define E1000_DAQF(_n) (0x59A0 + 4 * (_n)) | ||
363 | +#define E1000_SPQF(_n) (0x59C0 + 4 * (_n)) | ||
364 | +#define E1000_FTQF(_n) (0x59E0 + 4 * (_n)) | ||
365 | +#define E1000_SAQF0 E1000_SAQF(0) | ||
366 | +#define E1000_DAQF0 E1000_DAQF(0) | ||
367 | +#define E1000_SPQF0 E1000_SPQF(0) | ||
368 | +#define E1000_FTQF0 E1000_FTQF(0) | ||
369 | +#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ | ||
370 | +#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ | ||
371 | + | ||
372 | #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) | ||
373 | |||
374 | #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ | ||
375 | -- | ||
376 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
6 | --- | ||
7 | hw/net/igb_core.c | 7 +++++++ | ||
8 | hw/net/igb_regs.h | 3 +++ | ||
9 | 2 files changed, 10 insertions(+) | ||
10 | |||
11 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/hw/net/igb_core.c | ||
14 | +++ b/hw/net/igb_core.c | ||
15 | @@ -XXX,XX +XXX,XX @@ igb_process_tx_desc(IGBCore *core, | ||
16 | tx->ctx[idx].vlan_macip_lens >> IGB_TX_FLAGS_VLAN_SHIFT, | ||
17 | !!(tx->first_cmd_type_len & E1000_TXD_CMD_VLE)); | ||
18 | |||
19 | + if ((tx->first_cmd_type_len & E1000_ADVTXD_MAC_TSTAMP) && | ||
20 | + (core->mac[TSYNCTXCTL] & E1000_TSYNCTXCTL_ENABLED) && | ||
21 | + !(core->mac[TSYNCTXCTL] & E1000_TSYNCTXCTL_VALID)) { | ||
22 | + core->mac[TSYNCTXCTL] |= E1000_TSYNCTXCTL_VALID; | ||
23 | + e1000x_timestamp(core->mac, core->timadj, TXSTMPL, TXSTMPH); | ||
24 | + } | ||
25 | + | ||
26 | if (igb_tx_pkt_send(core, tx, queue_index)) { | ||
27 | igb_on_tx_done_update_stats(core, tx->tx_pkt, queue_index); | ||
28 | } | ||
29 | diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/hw/net/igb_regs.h | ||
32 | +++ b/hw/net/igb_regs.h | ||
33 | @@ -XXX,XX +XXX,XX @@ union e1000_adv_rx_desc { | ||
34 | /* E1000_EITR_CNT_IGNR is only for 82576 and newer */ | ||
35 | #define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */ | ||
36 | |||
37 | +#define E1000_TSYNCTXCTL_VALID 0x00000001 /* tx timestamp valid */ | ||
38 | +#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable tx timestampping */ | ||
39 | + | ||
40 | /* PCI Express Control */ | ||
41 | #define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 | ||
42 | #define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 | ||
43 | -- | ||
44 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | |
2 | |||
3 | In MSI-X mode, if there are interrupts already notified but not cleared | ||
4 | and a new interrupt arrives, e1000e incorrectly notifies the notified | ||
5 | ones again along with the new one. | ||
6 | |||
7 | To fix this issue, replace e1000e_update_interrupt_state() with | ||
8 | two new functions: e1000e_raise_interrupts() and | ||
9 | e1000e_lower_interrupts(). These functions don't only raise or lower | ||
10 | interrupts, but it also performs register writes which updates the | ||
11 | interrupt state. Before it performs a register write, these function | ||
12 | determines the interrupts already raised, and compares with the | ||
13 | interrupts raised after the register write to determine the interrupts | ||
14 | to notify. | ||
15 | |||
16 | The introduction of these functions made tracepoints which assumes that | ||
17 | the caller of e1000e_update_interrupt_state() performs register writes | ||
18 | obsolete. These tracepoints are now removed, and alternative ones are | ||
19 | added to the new functions. | ||
20 | |||
21 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
22 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
23 | --- | ||
24 | hw/net/e1000e_core.c | 153 ++++++++++++++++++++++----------------------------- | ||
25 | hw/net/e1000e_core.h | 2 - | ||
26 | hw/net/trace-events | 2 + | ||
27 | 3 files changed, 69 insertions(+), 88 deletions(-) | ||
28 | |||
29 | diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/hw/net/e1000e_core.c | ||
32 | +++ b/hw/net/e1000e_core.c | ||
33 | @@ -XXX,XX +XXX,XX @@ e1000e_intrmgr_on_throttling_timer(void *opaque) | ||
34 | |||
35 | timer->running = false; | ||
36 | |||
37 | - if (msi_enabled(timer->core->owner)) { | ||
38 | - trace_e1000e_irq_msi_notify_postponed(); | ||
39 | - /* Clear msi_causes_pending to fire MSI eventually */ | ||
40 | - timer->core->msi_causes_pending = 0; | ||
41 | - e1000e_set_interrupt_cause(timer->core, 0); | ||
42 | - } else { | ||
43 | - trace_e1000e_irq_legacy_notify_postponed(); | ||
44 | - e1000e_set_interrupt_cause(timer->core, 0); | ||
45 | + if (timer->core->mac[IMS] & timer->core->mac[ICR]) { | ||
46 | + if (msi_enabled(timer->core->owner)) { | ||
47 | + trace_e1000e_irq_msi_notify_postponed(); | ||
48 | + msi_notify(timer->core->owner, 0); | ||
49 | + } else { | ||
50 | + trace_e1000e_irq_legacy_notify_postponed(); | ||
51 | + e1000e_raise_legacy_irq(timer->core); | ||
52 | + } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | @@ -XXX,XX +XXX,XX @@ static void | ||
57 | e1000e_intrmgr_fire_all_timers(E1000ECore *core) | ||
58 | { | ||
59 | int i; | ||
60 | - uint32_t val = e1000e_intmgr_collect_delayed_causes(core); | ||
61 | - | ||
62 | - trace_e1000e_irq_adding_delayed_causes(val, core->mac[ICR]); | ||
63 | - core->mac[ICR] |= val; | ||
64 | |||
65 | if (core->itr.running) { | ||
66 | timer_del(core->itr.timer); | ||
67 | @@ -XXX,XX +XXX,XX @@ void(*e1000e_phyreg_writeops[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE]) | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | -static inline void | ||
72 | -e1000e_clear_ims_bits(E1000ECore *core, uint32_t bits) | ||
73 | -{ | ||
74 | - trace_e1000e_irq_clear_ims(bits, core->mac[IMS], core->mac[IMS] & ~bits); | ||
75 | - core->mac[IMS] &= ~bits; | ||
76 | -} | ||
77 | - | ||
78 | static inline bool | ||
79 | e1000e_postpone_interrupt(E1000IntrDelayTimer *timer) | ||
80 | { | ||
81 | @@ -XXX,XX +XXX,XX @@ e1000e_msix_notify_one(E1000ECore *core, uint32_t cause, uint32_t int_cfg) | ||
82 | effective_eiac = core->mac[EIAC] & cause; | ||
83 | |||
84 | core->mac[ICR] &= ~effective_eiac; | ||
85 | - core->msi_causes_pending &= ~effective_eiac; | ||
86 | |||
87 | if (!(core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) { | ||
88 | core->mac[IMS] &= ~effective_eiac; | ||
89 | @@ -XXX,XX +XXX,XX @@ e1000e_fix_icr_asserted(E1000ECore *core) | ||
90 | trace_e1000e_irq_fix_icr_asserted(core->mac[ICR]); | ||
91 | } | ||
92 | |||
93 | -static void | ||
94 | -e1000e_send_msi(E1000ECore *core, bool msix) | ||
95 | +static void e1000e_raise_interrupts(E1000ECore *core, | ||
96 | + size_t index, uint32_t causes) | ||
97 | { | ||
98 | - uint32_t causes = core->mac[ICR] & core->mac[IMS] & ~E1000_ICR_ASSERTED; | ||
99 | - | ||
100 | - core->msi_causes_pending &= causes; | ||
101 | - causes ^= core->msi_causes_pending; | ||
102 | - if (causes == 0) { | ||
103 | - return; | ||
104 | - } | ||
105 | - core->msi_causes_pending |= causes; | ||
106 | + bool is_msix = msix_enabled(core->owner); | ||
107 | + uint32_t old_causes = core->mac[IMS] & core->mac[ICR]; | ||
108 | + uint32_t raised_causes; | ||
109 | |||
110 | - if (msix) { | ||
111 | - e1000e_msix_notify(core, causes); | ||
112 | - } else { | ||
113 | - if (!e1000e_itr_should_postpone(core)) { | ||
114 | - trace_e1000e_irq_msi_notify(causes); | ||
115 | - msi_notify(core->owner, 0); | ||
116 | - } | ||
117 | - } | ||
118 | -} | ||
119 | + trace_e1000e_irq_set(index << 2, | ||
120 | + core->mac[index], core->mac[index] | causes); | ||
121 | |||
122 | -static void | ||
123 | -e1000e_update_interrupt_state(E1000ECore *core) | ||
124 | -{ | ||
125 | - bool interrupts_pending; | ||
126 | - bool is_msix = msix_enabled(core->owner); | ||
127 | + core->mac[index] |= causes; | ||
128 | |||
129 | /* Set ICR[OTHER] for MSI-X */ | ||
130 | if (is_msix) { | ||
131 | @@ -XXX,XX +XXX,XX @@ e1000e_update_interrupt_state(E1000ECore *core) | ||
132 | */ | ||
133 | core->mac[ICS] = core->mac[ICR]; | ||
134 | |||
135 | - interrupts_pending = (core->mac[IMS] & core->mac[ICR]) ? true : false; | ||
136 | - if (!interrupts_pending) { | ||
137 | - core->msi_causes_pending = 0; | ||
138 | - } | ||
139 | - | ||
140 | trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS], | ||
141 | core->mac[ICR], core->mac[IMS]); | ||
142 | |||
143 | - if (is_msix || msi_enabled(core->owner)) { | ||
144 | - if (interrupts_pending) { | ||
145 | - e1000e_send_msi(core, is_msix); | ||
146 | - } | ||
147 | - } else { | ||
148 | - if (interrupts_pending) { | ||
149 | - if (!e1000e_itr_should_postpone(core)) { | ||
150 | - e1000e_raise_legacy_irq(core); | ||
151 | - } | ||
152 | + raised_causes = core->mac[IMS] & core->mac[ICR] & ~old_causes; | ||
153 | + if (!raised_causes) { | ||
154 | + return; | ||
155 | + } | ||
156 | + | ||
157 | + if (is_msix) { | ||
158 | + e1000e_msix_notify(core, raised_causes & ~E1000_ICR_ASSERTED); | ||
159 | + } else if (!e1000e_itr_should_postpone(core)) { | ||
160 | + if (msi_enabled(core->owner)) { | ||
161 | + trace_e1000e_irq_msi_notify(raised_causes); | ||
162 | + msi_notify(core->owner, 0); | ||
163 | } else { | ||
164 | - e1000e_lower_legacy_irq(core); | ||
165 | + e1000e_raise_legacy_irq(core); | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | -static void | ||
171 | -e1000e_set_interrupt_cause(E1000ECore *core, uint32_t val) | ||
172 | +static void e1000e_lower_interrupts(E1000ECore *core, | ||
173 | + size_t index, uint32_t causes) | ||
174 | { | ||
175 | - trace_e1000e_irq_set_cause_entry(val, core->mac[ICR]); | ||
176 | + trace_e1000e_irq_clear(index << 2, | ||
177 | + core->mac[index], core->mac[index] & ~causes); | ||
178 | |||
179 | - val |= e1000e_intmgr_collect_delayed_causes(core); | ||
180 | - core->mac[ICR] |= val; | ||
181 | + core->mac[index] &= ~causes; | ||
182 | |||
183 | - trace_e1000e_irq_set_cause_exit(val, core->mac[ICR]); | ||
184 | + /* | ||
185 | + * Make sure ICR and ICS registers have the same value. | ||
186 | + * The spec says that the ICS register is write-only. However in practice, | ||
187 | + * on real hardware ICS is readable, and for reads it has the same value as | ||
188 | + * ICR (except that ICS does not have the clear on read behaviour of ICR). | ||
189 | + * | ||
190 | + * The VxWorks PRO/1000 driver uses this behaviour. | ||
191 | + */ | ||
192 | + core->mac[ICS] = core->mac[ICR]; | ||
193 | + | ||
194 | + trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS], | ||
195 | + core->mac[ICR], core->mac[IMS]); | ||
196 | |||
197 | - e1000e_update_interrupt_state(core); | ||
198 | + if (!(core->mac[IMS] & core->mac[ICR]) && | ||
199 | + !msix_enabled(core->owner) && !msi_enabled(core->owner)) { | ||
200 | + e1000e_lower_legacy_irq(core); | ||
201 | + } | ||
202 | +} | ||
203 | + | ||
204 | +static void | ||
205 | +e1000e_set_interrupt_cause(E1000ECore *core, uint32_t val) | ||
206 | +{ | ||
207 | + val |= e1000e_intmgr_collect_delayed_causes(core); | ||
208 | + e1000e_raise_interrupts(core, ICR, val); | ||
209 | } | ||
210 | |||
211 | static inline void | ||
212 | @@ -XXX,XX +XXX,XX @@ e1000e_set_ics(E1000ECore *core, int index, uint32_t val) | ||
213 | static void | ||
214 | e1000e_set_icr(E1000ECore *core, int index, uint32_t val) | ||
215 | { | ||
216 | - uint32_t icr = 0; | ||
217 | if ((core->mac[ICR] & E1000_ICR_ASSERTED) && | ||
218 | (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) { | ||
219 | trace_e1000e_irq_icr_process_iame(); | ||
220 | - e1000e_clear_ims_bits(core, core->mac[IAM]); | ||
221 | + e1000e_lower_interrupts(core, IMS, core->mac[IAM]); | ||
222 | } | ||
223 | |||
224 | - icr = core->mac[ICR] & ~val; | ||
225 | /* | ||
226 | * Windows driver expects that the "receive overrun" bit and other | ||
227 | * ones to be cleared when the "Other" bit (#24) is cleared. | ||
228 | */ | ||
229 | - icr = (val & E1000_ICR_OTHER) ? (icr & ~E1000_ICR_OTHER_CAUSES) : icr; | ||
230 | - trace_e1000e_irq_icr_write(val, core->mac[ICR], icr); | ||
231 | - core->mac[ICR] = icr; | ||
232 | - e1000e_update_interrupt_state(core); | ||
233 | + if (val & E1000_ICR_OTHER) { | ||
234 | + val |= E1000_ICR_OTHER_CAUSES; | ||
235 | + } | ||
236 | + e1000e_lower_interrupts(core, ICR, val); | ||
237 | } | ||
238 | |||
239 | static void | ||
240 | e1000e_set_imc(E1000ECore *core, int index, uint32_t val) | ||
241 | { | ||
242 | trace_e1000e_irq_ims_clear_set_imc(val); | ||
243 | - e1000e_clear_ims_bits(core, val); | ||
244 | - e1000e_update_interrupt_state(core); | ||
245 | + e1000e_lower_interrupts(core, IMS, val); | ||
246 | } | ||
247 | |||
248 | static void | ||
249 | @@ -XXX,XX +XXX,XX @@ e1000e_set_ims(E1000ECore *core, int index, uint32_t val) | ||
250 | |||
251 | uint32_t valid_val = val & ims_valid_mask; | ||
252 | |||
253 | - trace_e1000e_irq_set_ims(val, core->mac[IMS], core->mac[IMS] | valid_val); | ||
254 | - core->mac[IMS] |= valid_val; | ||
255 | - | ||
256 | if ((valid_val & ims_ext_mask) && | ||
257 | (core->mac[CTRL_EXT] & E1000_CTRL_EXT_PBA_CLR) && | ||
258 | msix_enabled(core->owner)) { | ||
259 | @@ -XXX,XX +XXX,XX @@ e1000e_set_ims(E1000ECore *core, int index, uint32_t val) | ||
260 | e1000e_intrmgr_fire_all_timers(core); | ||
261 | } | ||
262 | |||
263 | - e1000e_update_interrupt_state(core); | ||
264 | + e1000e_raise_interrupts(core, IMS, valid_val); | ||
265 | } | ||
266 | |||
267 | static void | ||
268 | @@ -XXX,XX +XXX,XX @@ static uint32_t | ||
269 | e1000e_mac_icr_read(E1000ECore *core, int index) | ||
270 | { | ||
271 | uint32_t ret = core->mac[ICR]; | ||
272 | - trace_e1000e_irq_icr_read_entry(ret); | ||
273 | |||
274 | if (core->mac[IMS] == 0) { | ||
275 | trace_e1000e_irq_icr_clear_zero_ims(); | ||
276 | - core->mac[ICR] = 0; | ||
277 | + e1000e_lower_interrupts(core, ICR, 0xffffffff); | ||
278 | } | ||
279 | |||
280 | if (!msix_enabled(core->owner)) { | ||
281 | trace_e1000e_irq_icr_clear_nonmsix_icr_read(); | ||
282 | - core->mac[ICR] = 0; | ||
283 | + e1000e_lower_interrupts(core, ICR, 0xffffffff); | ||
284 | } | ||
285 | |||
286 | if ((core->mac[ICR] & E1000_ICR_ASSERTED) && | ||
287 | (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) { | ||
288 | trace_e1000e_irq_icr_clear_iame(); | ||
289 | - core->mac[ICR] = 0; | ||
290 | + e1000e_lower_interrupts(core, ICR, 0xffffffff); | ||
291 | trace_e1000e_irq_icr_process_iame(); | ||
292 | - e1000e_clear_ims_bits(core, core->mac[IAM]); | ||
293 | + e1000e_lower_interrupts(core, IMS, core->mac[IAM]); | ||
294 | } | ||
295 | |||
296 | - trace_e1000e_irq_icr_read_exit(core->mac[ICR]); | ||
297 | - e1000e_update_interrupt_state(core); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h | ||
302 | index XXXXXXX..XXXXXXX 100644 | ||
303 | --- a/hw/net/e1000e_core.h | ||
304 | +++ b/hw/net/e1000e_core.h | ||
305 | @@ -XXX,XX +XXX,XX @@ struct E1000Core { | ||
306 | PCIDevice *owner; | ||
307 | void (*owner_start_recv)(PCIDevice *d); | ||
308 | |||
309 | - uint32_t msi_causes_pending; | ||
310 | - | ||
311 | int64_t timadj; | ||
312 | }; | ||
313 | |||
314 | diff --git a/hw/net/trace-events b/hw/net/trace-events | ||
315 | index XXXXXXX..XXXXXXX 100644 | ||
316 | --- a/hw/net/trace-events | ||
317 | +++ b/hw/net/trace-events | ||
318 | @@ -XXX,XX +XXX,XX @@ e1000e_irq_msix_notify_postponed_vec(int idx) "Sending MSI-X postponed by EITR[% | ||
319 | e1000e_irq_legacy_notify(bool level) "IRQ line state: %d" | ||
320 | e1000e_irq_msix_notify_vec(uint32_t vector) "MSI-X notify vector 0x%x" | ||
321 | e1000e_irq_postponed_by_xitr(uint32_t reg) "Interrupt postponed by [E]ITR register 0x%x" | ||
322 | +e1000e_irq_clear(uint32_t offset, uint32_t old, uint32_t new) "Clearing interrupt register 0x%x: 0x%x --> 0x%x" | ||
323 | +e1000e_irq_set(uint32_t offset, uint32_t old, uint32_t new) "Setting interrupt register 0x%x: 0x%x --> 0x%x" | ||
324 | e1000e_irq_clear_ims(uint32_t bits, uint32_t old_ims, uint32_t new_ims) "Clearing IMS bits 0x%x: 0x%x --> 0x%x" | ||
325 | e1000e_irq_set_ims(uint32_t bits, uint32_t old_ims, uint32_t new_ims) "Setting IMS bits 0x%x: 0x%x --> 0x%x" | ||
326 | e1000e_irq_fix_icr_asserted(uint32_t new_val) "ICR_ASSERTED bit fixed: 0x%x" | ||
327 | -- | ||
328 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | This follows the corresponding change for e1000e. This fixes: | ||
4 | tests/avocado/netdev-ethtool.py:NetDevEthtool.test_igb | ||
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
8 | --- | ||
9 | hw/net/igb_core.c | 201 +++++++++------------ | ||
10 | hw/net/trace-events | 11 +- | ||
11 | scripts/ci/org.centos/stream/8/x86_64/test-avocado | 1 + | ||
12 | tests/avocado/netdev-ethtool.py | 4 - | ||
13 | 4 files changed, 87 insertions(+), 130 deletions(-) | ||
14 | |||
15 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/net/igb_core.c | ||
18 | +++ b/hw/net/igb_core.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static ssize_t | ||
20 | igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
21 | bool has_vnet, bool *external_tx); | ||
22 | |||
23 | -static inline void | ||
24 | -igb_set_interrupt_cause(IGBCore *core, uint32_t val); | ||
25 | - | ||
26 | -static void igb_update_interrupt_state(IGBCore *core); | ||
27 | +static void igb_raise_interrupts(IGBCore *core, size_t index, uint32_t causes); | ||
28 | static void igb_reset(IGBCore *core, bool sw); | ||
29 | |||
30 | static inline void | ||
31 | @@ -XXX,XX +XXX,XX @@ igb_start_xmit(IGBCore *core, const IGB_TxRing *txr) | ||
32 | } | ||
33 | |||
34 | if (eic) { | ||
35 | - core->mac[EICR] |= eic; | ||
36 | - igb_set_interrupt_cause(core, E1000_ICR_TXDW); | ||
37 | + igb_raise_interrupts(core, EICR, eic); | ||
38 | + igb_raise_interrupts(core, ICR, E1000_ICR_TXDW); | ||
39 | } | ||
40 | |||
41 | net_tx_pkt_reset(txr->tx->tx_pkt, net_tx_pkt_unmap_frag_pci, d); | ||
42 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
43 | { | ||
44 | uint16_t queues = 0; | ||
45 | uint32_t causes = 0; | ||
46 | + uint32_t ecauses = 0; | ||
47 | union { | ||
48 | L2Header l2_header; | ||
49 | uint8_t octets[ETH_ZLEN]; | ||
50 | @@ -XXX,XX +XXX,XX @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt, | ||
51 | causes |= E1000_ICS_RXDMT0; | ||
52 | } | ||
53 | |||
54 | - core->mac[EICR] |= igb_rx_wb_eic(core, rxr.i->idx); | ||
55 | + ecauses |= igb_rx_wb_eic(core, rxr.i->idx); | ||
56 | |||
57 | trace_e1000e_rx_written_to_guest(rxr.i->idx); | ||
58 | } | ||
59 | |||
60 | trace_e1000e_rx_interrupt_set(causes); | ||
61 | - igb_set_interrupt_cause(core, causes); | ||
62 | + igb_raise_interrupts(core, EICR, ecauses); | ||
63 | + igb_raise_interrupts(core, ICR, causes); | ||
64 | |||
65 | return orig_size; | ||
66 | } | ||
67 | @@ -XXX,XX +XXX,XX @@ void igb_core_set_link_status(IGBCore *core) | ||
68 | } | ||
69 | |||
70 | if (core->mac[STATUS] != old_status) { | ||
71 | - igb_set_interrupt_cause(core, E1000_ICR_LSC); | ||
72 | + igb_raise_interrupts(core, ICR, E1000_ICR_LSC); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | @@ -XXX,XX +XXX,XX @@ igb_set_rx_control(IGBCore *core, int index, uint32_t val) | ||
77 | } | ||
78 | } | ||
79 | |||
80 | -static inline void | ||
81 | -igb_clear_ims_bits(IGBCore *core, uint32_t bits) | ||
82 | -{ | ||
83 | - trace_e1000e_irq_clear_ims(bits, core->mac[IMS], core->mac[IMS] & ~bits); | ||
84 | - core->mac[IMS] &= ~bits; | ||
85 | -} | ||
86 | - | ||
87 | static inline bool | ||
88 | igb_postpone_interrupt(IGBIntrDelayTimer *timer) | ||
89 | { | ||
90 | @@ -XXX,XX +XXX,XX @@ igb_eitr_should_postpone(IGBCore *core, int idx) | ||
91 | return igb_postpone_interrupt(&core->eitr[idx]); | ||
92 | } | ||
93 | |||
94 | -static void igb_send_msix(IGBCore *core) | ||
95 | +static void igb_send_msix(IGBCore *core, uint32_t causes) | ||
96 | { | ||
97 | - uint32_t causes = core->mac[EICR] & core->mac[EIMS]; | ||
98 | int vector; | ||
99 | |||
100 | for (vector = 0; vector < IGB_INTR_NUM; ++vector) { | ||
101 | @@ -XXX,XX +XXX,XX @@ igb_fix_icr_asserted(IGBCore *core) | ||
102 | trace_e1000e_irq_fix_icr_asserted(core->mac[ICR]); | ||
103 | } | ||
104 | |||
105 | -static void | ||
106 | -igb_update_interrupt_state(IGBCore *core) | ||
107 | +static void igb_raise_interrupts(IGBCore *core, size_t index, uint32_t causes) | ||
108 | { | ||
109 | - uint32_t icr; | ||
110 | - uint32_t causes; | ||
111 | + uint32_t old_causes = core->mac[ICR] & core->mac[IMS]; | ||
112 | + uint32_t old_ecauses = core->mac[EICR] & core->mac[EIMS]; | ||
113 | + uint32_t raised_causes; | ||
114 | + uint32_t raised_ecauses; | ||
115 | uint32_t int_alloc; | ||
116 | |||
117 | - icr = core->mac[ICR] & core->mac[IMS]; | ||
118 | + trace_e1000e_irq_set(index << 2, | ||
119 | + core->mac[index], core->mac[index] | causes); | ||
120 | + | ||
121 | + core->mac[index] |= causes; | ||
122 | |||
123 | if (core->mac[GPIE] & E1000_GPIE_MSIX_MODE) { | ||
124 | - if (icr) { | ||
125 | - causes = 0; | ||
126 | - if (icr & E1000_ICR_DRSTA) { | ||
127 | - int_alloc = core->mac[IVAR_MISC] & 0xff; | ||
128 | - if (int_alloc & E1000_IVAR_VALID) { | ||
129 | - causes |= BIT(int_alloc & 0x1f); | ||
130 | - } | ||
131 | + raised_causes = core->mac[ICR] & core->mac[IMS] & ~old_causes; | ||
132 | + | ||
133 | + if (raised_causes & E1000_ICR_DRSTA) { | ||
134 | + int_alloc = core->mac[IVAR_MISC] & 0xff; | ||
135 | + if (int_alloc & E1000_IVAR_VALID) { | ||
136 | + core->mac[EICR] |= BIT(int_alloc & 0x1f); | ||
137 | } | ||
138 | - /* Check if other bits (excluding the TCP Timer) are enabled. */ | ||
139 | - if (icr & ~E1000_ICR_DRSTA) { | ||
140 | - int_alloc = (core->mac[IVAR_MISC] >> 8) & 0xff; | ||
141 | - if (int_alloc & E1000_IVAR_VALID) { | ||
142 | - causes |= BIT(int_alloc & 0x1f); | ||
143 | - } | ||
144 | - trace_e1000e_irq_add_msi_other(core->mac[EICR]); | ||
145 | + } | ||
146 | + /* Check if other bits (excluding the TCP Timer) are enabled. */ | ||
147 | + if (raised_causes & ~E1000_ICR_DRSTA) { | ||
148 | + int_alloc = (core->mac[IVAR_MISC] >> 8) & 0xff; | ||
149 | + if (int_alloc & E1000_IVAR_VALID) { | ||
150 | + core->mac[EICR] |= BIT(int_alloc & 0x1f); | ||
151 | } | ||
152 | - core->mac[EICR] |= causes; | ||
153 | } | ||
154 | |||
155 | - if ((core->mac[EICR] & core->mac[EIMS])) { | ||
156 | - igb_send_msix(core); | ||
157 | + raised_ecauses = core->mac[EICR] & core->mac[EIMS] & ~old_ecauses; | ||
158 | + if (!raised_ecauses) { | ||
159 | + return; | ||
160 | } | ||
161 | + | ||
162 | + igb_send_msix(core, raised_ecauses); | ||
163 | } else { | ||
164 | igb_fix_icr_asserted(core); | ||
165 | |||
166 | - if (icr) { | ||
167 | - core->mac[EICR] |= (icr & E1000_ICR_DRSTA) | E1000_EICR_OTHER; | ||
168 | - } else { | ||
169 | - core->mac[EICR] &= ~E1000_EICR_OTHER; | ||
170 | + raised_causes = core->mac[ICR] & core->mac[IMS] & ~old_causes; | ||
171 | + if (!raised_causes) { | ||
172 | + return; | ||
173 | } | ||
174 | |||
175 | - trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS], | ||
176 | - core->mac[ICR], core->mac[IMS]); | ||
177 | + core->mac[EICR] |= (raised_causes & E1000_ICR_DRSTA) | E1000_EICR_OTHER; | ||
178 | |||
179 | if (msix_enabled(core->owner)) { | ||
180 | - if (icr) { | ||
181 | - trace_e1000e_irq_msix_notify_vec(0); | ||
182 | - msix_notify(core->owner, 0); | ||
183 | - } | ||
184 | + trace_e1000e_irq_msix_notify_vec(0); | ||
185 | + msix_notify(core->owner, 0); | ||
186 | } else if (msi_enabled(core->owner)) { | ||
187 | - if (icr) { | ||
188 | - msi_notify(core->owner, 0); | ||
189 | - } | ||
190 | + trace_e1000e_irq_msi_notify(raised_causes); | ||
191 | + msi_notify(core->owner, 0); | ||
192 | } else { | ||
193 | - if (icr) { | ||
194 | - igb_raise_legacy_irq(core); | ||
195 | - } else { | ||
196 | - igb_lower_legacy_irq(core); | ||
197 | - } | ||
198 | + igb_raise_legacy_irq(core); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | |||
203 | -static void | ||
204 | -igb_set_interrupt_cause(IGBCore *core, uint32_t val) | ||
205 | +static void igb_lower_interrupts(IGBCore *core, size_t index, uint32_t causes) | ||
206 | { | ||
207 | - trace_e1000e_irq_set_cause_entry(val, core->mac[ICR]); | ||
208 | + trace_e1000e_irq_clear(index << 2, | ||
209 | + core->mac[index], core->mac[index] & ~causes); | ||
210 | + | ||
211 | + core->mac[index] &= ~causes; | ||
212 | |||
213 | - core->mac[ICR] |= val; | ||
214 | + trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS], | ||
215 | + core->mac[ICR], core->mac[IMS]); | ||
216 | |||
217 | - trace_e1000e_irq_set_cause_exit(val, core->mac[ICR]); | ||
218 | + if (!(core->mac[ICR] & core->mac[IMS]) && | ||
219 | + !(core->mac[GPIE] & E1000_GPIE_MSIX_MODE)) { | ||
220 | + core->mac[EICR] &= ~E1000_EICR_OTHER; | ||
221 | |||
222 | - igb_update_interrupt_state(core); | ||
223 | + if (!msix_enabled(core->owner) && !msi_enabled(core->owner)) { | ||
224 | + igb_lower_legacy_irq(core); | ||
225 | + } | ||
226 | + } | ||
227 | } | ||
228 | |||
229 | static void igb_set_eics(IGBCore *core, int index, uint32_t val) | ||
230 | { | ||
231 | bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE); | ||
232 | + uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK; | ||
233 | |||
234 | trace_igb_irq_write_eics(val, msix); | ||
235 | - | ||
236 | - core->mac[EICS] |= | ||
237 | - val & (msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK); | ||
238 | - | ||
239 | - /* | ||
240 | - * TODO: Move to igb_update_interrupt_state if EICS is modified in other | ||
241 | - * places. | ||
242 | - */ | ||
243 | - core->mac[EICR] = core->mac[EICS]; | ||
244 | - | ||
245 | - igb_update_interrupt_state(core); | ||
246 | + igb_raise_interrupts(core, EICR, val & mask); | ||
247 | } | ||
248 | |||
249 | static void igb_set_eims(IGBCore *core, int index, uint32_t val) | ||
250 | { | ||
251 | bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE); | ||
252 | + uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK; | ||
253 | |||
254 | trace_igb_irq_write_eims(val, msix); | ||
255 | - | ||
256 | - core->mac[EIMS] |= | ||
257 | - val & (msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK); | ||
258 | - | ||
259 | - igb_update_interrupt_state(core); | ||
260 | + igb_raise_interrupts(core, EIMS, val & mask); | ||
261 | } | ||
262 | |||
263 | static void mailbox_interrupt_to_vf(IGBCore *core, uint16_t vfn) | ||
264 | { | ||
265 | uint32_t ent = core->mac[VTIVAR_MISC + vfn]; | ||
266 | + uint32_t causes; | ||
267 | |||
268 | if ((ent & E1000_IVAR_VALID)) { | ||
269 | - core->mac[EICR] |= (ent & 0x3) << (22 - vfn * IGBVF_MSIX_VEC_NUM); | ||
270 | - igb_update_interrupt_state(core); | ||
271 | + causes = (ent & 0x3) << (22 - vfn * IGBVF_MSIX_VEC_NUM); | ||
272 | + igb_raise_interrupts(core, EICR, causes); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static void mailbox_interrupt_to_pf(IGBCore *core) | ||
277 | { | ||
278 | - igb_set_interrupt_cause(core, E1000_ICR_VMMB); | ||
279 | + igb_raise_interrupts(core, ICR, E1000_ICR_VMMB); | ||
280 | } | ||
281 | |||
282 | static void igb_set_pfmailbox(IGBCore *core, int index, uint32_t val) | ||
283 | @@ -XXX,XX +XXX,XX @@ static void igb_w1c(IGBCore *core, int index, uint32_t val) | ||
284 | static void igb_set_eimc(IGBCore *core, int index, uint32_t val) | ||
285 | { | ||
286 | bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE); | ||
287 | + uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK; | ||
288 | |||
289 | - /* Interrupts are disabled via a write to EIMC and reflected in EIMS. */ | ||
290 | - core->mac[EIMS] &= | ||
291 | - ~(val & (msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK)); | ||
292 | + trace_igb_irq_write_eimc(val, msix); | ||
293 | |||
294 | - trace_igb_irq_write_eimc(val, core->mac[EIMS], msix); | ||
295 | - igb_update_interrupt_state(core); | ||
296 | + /* Interrupts are disabled via a write to EIMC and reflected in EIMS. */ | ||
297 | + igb_lower_interrupts(core, EIMS, val & mask); | ||
298 | } | ||
299 | |||
300 | static void igb_set_eiac(IGBCore *core, int index, uint32_t val) | ||
301 | @@ -XXX,XX +XXX,XX @@ static void igb_set_eicr(IGBCore *core, int index, uint32_t val) | ||
302 | * TODO: In IOV mode, only bit zero of this vector is available for the PF | ||
303 | * function. | ||
304 | */ | ||
305 | - core->mac[EICR] &= | ||
306 | - ~(val & (msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK)); | ||
307 | + uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK; | ||
308 | |||
309 | trace_igb_irq_write_eicr(val, msix); | ||
310 | - igb_update_interrupt_state(core); | ||
311 | + igb_lower_interrupts(core, EICR, val & mask); | ||
312 | } | ||
313 | |||
314 | static void igb_set_vtctrl(IGBCore *core, int index, uint32_t val) | ||
315 | @@ -XXX,XX +XXX,XX @@ igb_autoneg_timer(void *opaque) | ||
316 | |||
317 | igb_update_flowctl_status(core); | ||
318 | /* signal link status change to the guest */ | ||
319 | - igb_set_interrupt_cause(core, E1000_ICR_LSC); | ||
320 | + igb_raise_interrupts(core, ICR, E1000_ICR_LSC); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | @@ -XXX,XX +XXX,XX @@ igb_set_mdic(IGBCore *core, int index, uint32_t val) | ||
325 | core->mac[MDIC] = val | E1000_MDIC_READY; | ||
326 | |||
327 | if (val & E1000_MDIC_INT_EN) { | ||
328 | - igb_set_interrupt_cause(core, E1000_ICR_MDAC); | ||
329 | + igb_raise_interrupts(core, ICR, E1000_ICR_MDAC); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | @@ -XXX,XX +XXX,XX @@ static void | ||
334 | igb_set_ics(IGBCore *core, int index, uint32_t val) | ||
335 | { | ||
336 | trace_e1000e_irq_write_ics(val); | ||
337 | - igb_set_interrupt_cause(core, val); | ||
338 | + igb_raise_interrupts(core, ICR, val); | ||
339 | } | ||
340 | |||
341 | static void | ||
342 | igb_set_imc(IGBCore *core, int index, uint32_t val) | ||
343 | { | ||
344 | trace_e1000e_irq_ims_clear_set_imc(val); | ||
345 | - igb_clear_ims_bits(core, val); | ||
346 | - igb_update_interrupt_state(core); | ||
347 | + igb_lower_interrupts(core, IMS, val); | ||
348 | } | ||
349 | |||
350 | static void | ||
351 | igb_set_ims(IGBCore *core, int index, uint32_t val) | ||
352 | { | ||
353 | - uint32_t valid_val = val & 0x77D4FBFD; | ||
354 | - | ||
355 | - trace_e1000e_irq_set_ims(val, core->mac[IMS], core->mac[IMS] | valid_val); | ||
356 | - core->mac[IMS] |= valid_val; | ||
357 | - igb_update_interrupt_state(core); | ||
358 | + igb_raise_interrupts(core, IMS, val & 0x77D4FBFD); | ||
359 | } | ||
360 | |||
361 | -static void igb_commit_icr(IGBCore *core) | ||
362 | +static void igb_nsicr(IGBCore *core) | ||
363 | { | ||
364 | /* | ||
365 | * If GPIE.NSICR = 0, then the clear of IMS will occur only if at | ||
366 | @@ -XXX,XX +XXX,XX @@ static void igb_commit_icr(IGBCore *core) | ||
367 | */ | ||
368 | if ((core->mac[GPIE] & E1000_GPIE_NSICR) || | ||
369 | (core->mac[IMS] && (core->mac[ICR] & E1000_ICR_INT_ASSERTED))) { | ||
370 | - igb_clear_ims_bits(core, core->mac[IAM]); | ||
371 | + igb_lower_interrupts(core, IMS, core->mac[IAM]); | ||
372 | } | ||
373 | - | ||
374 | - igb_update_interrupt_state(core); | ||
375 | } | ||
376 | |||
377 | static void igb_set_icr(IGBCore *core, int index, uint32_t val) | ||
378 | { | ||
379 | - uint32_t icr = core->mac[ICR] & ~val; | ||
380 | - | ||
381 | - trace_igb_irq_icr_write(val, core->mac[ICR], icr); | ||
382 | - core->mac[ICR] = icr; | ||
383 | - igb_commit_icr(core); | ||
384 | + igb_nsicr(core); | ||
385 | + igb_lower_interrupts(core, ICR, val); | ||
386 | } | ||
387 | |||
388 | static uint32_t | ||
389 | @@ -XXX,XX +XXX,XX @@ static uint32_t | ||
390 | igb_mac_icr_read(IGBCore *core, int index) | ||
391 | { | ||
392 | uint32_t ret = core->mac[ICR]; | ||
393 | - trace_e1000e_irq_icr_read_entry(ret); | ||
394 | |||
395 | if (core->mac[GPIE] & E1000_GPIE_NSICR) { | ||
396 | trace_igb_irq_icr_clear_gpie_nsicr(); | ||
397 | - core->mac[ICR] = 0; | ||
398 | + igb_lower_interrupts(core, ICR, 0xffffffff); | ||
399 | } else if (core->mac[IMS] == 0) { | ||
400 | trace_e1000e_irq_icr_clear_zero_ims(); | ||
401 | - core->mac[ICR] = 0; | ||
402 | + igb_lower_interrupts(core, ICR, 0xffffffff); | ||
403 | } else if (!msix_enabled(core->owner)) { | ||
404 | trace_e1000e_irq_icr_clear_nonmsix_icr_read(); | ||
405 | - core->mac[ICR] = 0; | ||
406 | + igb_lower_interrupts(core, ICR, 0xffffffff); | ||
407 | } | ||
408 | |||
409 | - trace_e1000e_irq_icr_read_exit(core->mac[ICR]); | ||
410 | - igb_commit_icr(core); | ||
411 | + igb_nsicr(core); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | diff --git a/hw/net/trace-events b/hw/net/trace-events | ||
416 | index XXXXXXX..XXXXXXX 100644 | ||
417 | --- a/hw/net/trace-events | ||
418 | +++ b/hw/net/trace-events | ||
419 | @@ -XXX,XX +XXX,XX @@ e1000e_irq_msix_notify_vec(uint32_t vector) "MSI-X notify vector 0x%x" | ||
420 | e1000e_irq_postponed_by_xitr(uint32_t reg) "Interrupt postponed by [E]ITR register 0x%x" | ||
421 | e1000e_irq_clear(uint32_t offset, uint32_t old, uint32_t new) "Clearing interrupt register 0x%x: 0x%x --> 0x%x" | ||
422 | e1000e_irq_set(uint32_t offset, uint32_t old, uint32_t new) "Setting interrupt register 0x%x: 0x%x --> 0x%x" | ||
423 | -e1000e_irq_clear_ims(uint32_t bits, uint32_t old_ims, uint32_t new_ims) "Clearing IMS bits 0x%x: 0x%x --> 0x%x" | ||
424 | -e1000e_irq_set_ims(uint32_t bits, uint32_t old_ims, uint32_t new_ims) "Setting IMS bits 0x%x: 0x%x --> 0x%x" | ||
425 | e1000e_irq_fix_icr_asserted(uint32_t new_val) "ICR_ASSERTED bit fixed: 0x%x" | ||
426 | e1000e_irq_add_msi_other(uint32_t new_val) "ICR_OTHER bit added: 0x%x" | ||
427 | e1000e_irq_pending_interrupts(uint32_t pending, uint32_t icr, uint32_t ims) "ICR PENDING: 0x%x (ICR: 0x%x, IMS: 0x%x)" | ||
428 | -e1000e_irq_set_cause_entry(uint32_t val, uint32_t icr) "Going to set IRQ cause 0x%x, ICR: 0x%x" | ||
429 | -e1000e_irq_set_cause_exit(uint32_t val, uint32_t icr) "Set IRQ cause 0x%x, ICR: 0x%x" | ||
430 | -e1000e_irq_icr_write(uint32_t bits, uint32_t old_icr, uint32_t new_icr) "Clearing ICR bits 0x%x: 0x%x --> 0x%x" | ||
431 | e1000e_irq_write_ics(uint32_t val) "Adding ICR bits 0x%x" | ||
432 | e1000e_irq_icr_process_iame(void) "Clearing IMS bits due to IAME" | ||
433 | e1000e_irq_read_ics(uint32_t ics) "Current ICS: 0x%x" | ||
434 | e1000e_irq_read_ims(uint32_t ims) "Current IMS: 0x%x" | ||
435 | e1000e_irq_icr_clear_nonmsix_icr_read(void) "Clearing ICR on read due to non MSI-X int" | ||
436 | -e1000e_irq_icr_read_entry(uint32_t icr) "Starting ICR read. Current ICR: 0x%x" | ||
437 | -e1000e_irq_icr_read_exit(uint32_t icr) "Ending ICR read. Current ICR: 0x%x" | ||
438 | e1000e_irq_icr_clear_zero_ims(void) "Clearing ICR on read due to zero IMS" | ||
439 | e1000e_irq_icr_clear_iame(void) "Clearing ICR on read due to IAME" | ||
440 | e1000e_irq_iam_clear_eiame(uint32_t iam, uint32_t cause) "Clearing IMS due to EIAME, IAM: 0x%X, cause: 0x%X" | ||
441 | @@ -XXX,XX +XXX,XX @@ e1000e_irq_tidv_fpd_not_running(void) "FPD written while TIDV was not running" | ||
442 | e1000e_irq_eitr_set(uint32_t eitr_num, uint32_t val) "EITR[%u] = %u" | ||
443 | e1000e_irq_itr_set(uint32_t val) "ITR = %u" | ||
444 | e1000e_irq_fire_all_timers(uint32_t val) "Firing all delay/throttling timers on all interrupts enable (0x%X written to IMS)" | ||
445 | -e1000e_irq_adding_delayed_causes(uint32_t val, uint32_t icr) "Merging delayed causes 0x%X to ICR 0x%X" | ||
446 | e1000e_irq_msix_pending_clearing(uint32_t cause, uint32_t int_cfg, uint32_t vec) "Clearing MSI-X pending bit for cause 0x%x, IVAR config 0x%x, vector %u" | ||
447 | |||
448 | e1000e_wrn_msix_vec_wrong(uint32_t cause, uint32_t cfg) "Invalid configuration for cause 0x%x: 0x%x" | ||
449 | @@ -XXX,XX +XXX,XX @@ igb_rx_desc_buff_write(uint64_t addr, uint16_t offset, const void* source, uint3 | ||
450 | igb_rx_metadata_rss(uint32_t rss) "RSS data: 0x%X" | ||
451 | |||
452 | igb_irq_icr_clear_gpie_nsicr(void) "Clearing ICR on read due to GPIE.NSICR enabled" | ||
453 | -igb_irq_icr_write(uint32_t bits, uint32_t old_icr, uint32_t new_icr) "Clearing ICR bits 0x%x: 0x%x --> 0x%x" | ||
454 | igb_irq_set_iam(uint32_t icr) "Update IAM: 0x%x" | ||
455 | igb_irq_read_iam(uint32_t icr) "Current IAM: 0x%x" | ||
456 | igb_irq_write_eics(uint32_t val, bool msix) "Update EICS: 0x%x MSI-X: %d" | ||
457 | igb_irq_write_eims(uint32_t val, bool msix) "Update EIMS: 0x%x MSI-X: %d" | ||
458 | -igb_irq_write_eimc(uint32_t val, uint32_t eims, bool msix) "Update EIMC: 0x%x EIMS: 0x%x MSI-X: %d" | ||
459 | +igb_irq_write_eimc(uint32_t val, bool msix) "Update EIMC: 0x%x MSI-X: %d" | ||
460 | igb_irq_write_eiac(uint32_t val) "Update EIAC: 0x%x" | ||
461 | igb_irq_write_eiam(uint32_t val, bool msix) "Update EIAM: 0x%x MSI-X: %d" | ||
462 | igb_irq_write_eicr(uint32_t val, bool msix) "Update EICR: 0x%x MSI-X: %d" | ||
463 | diff --git a/scripts/ci/org.centos/stream/8/x86_64/test-avocado b/scripts/ci/org.centos/stream/8/x86_64/test-avocado | ||
464 | index XXXXXXX..XXXXXXX 100755 | ||
465 | --- a/scripts/ci/org.centos/stream/8/x86_64/test-avocado | ||
466 | +++ b/scripts/ci/org.centos/stream/8/x86_64/test-avocado | ||
467 | @@ -XXX,XX +XXX,XX @@ make get-vm-images | ||
468 | tests/avocado/cpu_queries.py:QueryCPUModelExpansion.test \ | ||
469 | tests/avocado/empty_cpu_model.py:EmptyCPUModel.test \ | ||
470 | tests/avocado/hotplug_cpu.py:HotPlugCPU.test \ | ||
471 | + tests/avocado/netdev-ethtool.py:NetDevEthtool.test_igb \ | ||
472 | tests/avocado/netdev-ethtool.py:NetDevEthtool.test_igb_nomsi \ | ||
473 | tests/avocado/info_usernet.py:InfoUsernet.test_hostfwd \ | ||
474 | tests/avocado/intel_iommu.py:IntelIOMMU.test_intel_iommu \ | ||
475 | diff --git a/tests/avocado/netdev-ethtool.py b/tests/avocado/netdev-ethtool.py | ||
476 | index XXXXXXX..XXXXXXX 100644 | ||
477 | --- a/tests/avocado/netdev-ethtool.py | ||
478 | +++ b/tests/avocado/netdev-ethtool.py | ||
479 | @@ -XXX,XX +XXX,XX @@ def common_test_code(self, netdev, extra_args=None): | ||
480 | # no need to gracefully shutdown, just finish | ||
481 | self.vm.kill() | ||
482 | |||
483 | - # Skip testing for MSI for now. Allegedly it was fixed by: | ||
484 | - # 28e96556ba (igb: Allocate MSI-X vector when testing) | ||
485 | - # but I'm seeing oops in the kernel | ||
486 | - @skip("Kernel bug with MSI enabled") | ||
487 | def test_igb(self): | ||
488 | """ | ||
489 | :avocado: tags=device:igb | ||
490 | -- | ||
491 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | For GPIE.NSICR, Section 7.3.2.1.2 says: | ||
4 | > ICR bits are cleared on register read. If GPIE.NSICR = 0b, then the | ||
5 | > clear on read occurs only if no bit is set in the IMS or at least one | ||
6 | > bit is set in the IMS and there is a true interrupt as reflected in | ||
7 | > ICR.INTA. | ||
8 | |||
9 | e1000e does similar though it checks for CTRL_EXT.IAME, which does not | ||
10 | exist on igb. | ||
11 | |||
12 | Suggested-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> | ||
13 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
14 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
15 | --- | ||
16 | hw/net/igb_core.c | 2 ++ | ||
17 | 1 file changed, 2 insertions(+) | ||
18 | |||
19 | diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/hw/net/igb_core.c | ||
22 | +++ b/hw/net/igb_core.c | ||
23 | @@ -XXX,XX +XXX,XX @@ igb_mac_icr_read(IGBCore *core, int index) | ||
24 | } else if (core->mac[IMS] == 0) { | ||
25 | trace_e1000e_irq_icr_clear_zero_ims(); | ||
26 | igb_lower_interrupts(core, ICR, 0xffffffff); | ||
27 | + } else if (core->mac[ICR] & E1000_ICR_INT_ASSERTED) { | ||
28 | + igb_lower_interrupts(core, ICR, 0xffffffff); | ||
29 | } else if (!msix_enabled(core->owner)) { | ||
30 | trace_e1000e_irq_icr_clear_nonmsix_icr_read(); | ||
31 | igb_lower_interrupts(core, ICR, 0xffffffff); | ||
32 | -- | ||
33 | 2.7.4 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | vmxnet3 has no dependency on PC, and VMware Fusion actually makes it | ||
4 | available on Apple Silicon according to: | ||
5 | https://kb.vmware.com/s/article/90364 | ||
6 | |||
7 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
9 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
10 | --- | ||
11 | hw/net/Kconfig | 2 +- | ||
12 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/hw/net/Kconfig b/hw/net/Kconfig | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/net/Kconfig | ||
17 | +++ b/hw/net/Kconfig | ||
18 | @@ -XXX,XX +XXX,XX @@ config RTL8139_PCI | ||
19 | |||
20 | config VMXNET3_PCI | ||
21 | bool | ||
22 | - default y if PCI_DEVICES && PC_PCI | ||
23 | + default y if PCI_DEVICES | ||
24 | depends on PCI | ||
25 | |||
26 | config SMC91C111 | ||
27 | -- | ||
28 | 2.7.4 | ||
29 | |||
30 | diff view generated by jsdifflib |
1 | From: Keqian Zhu <zhukeqian1@huawei.com> | 1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> |
---|---|---|---|
2 | 2 | ||
3 | Fixes: 63c4db4c2e6d (net: relocate paths to helpers and scripts) | 3 | I have made significant changes for network packet abstractions so add |
4 | Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com> | 4 | me as a reviewer. |
5 | |||
6 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
7 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
5 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 8 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
6 | --- | 9 | --- |
7 | net/tap.c | 3 ++- | 10 | MAINTAINERS | 1 + |
8 | 1 file changed, 2 insertions(+), 1 deletion(-) | 11 | 1 file changed, 1 insertion(+) |
9 | 12 | ||
10 | diff --git a/net/tap.c b/net/tap.c | 13 | diff --git a/MAINTAINERS b/MAINTAINERS |
11 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
12 | --- a/net/tap.c | 15 | --- a/MAINTAINERS |
13 | +++ b/net/tap.c | 16 | +++ b/MAINTAINERS |
14 | @@ -XXX,XX +XXX,XX @@ free_fail: | 17 | @@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-megasas-test.c |
15 | script = default_script = get_relocated_path(DEFAULT_NETWORK_SCRIPT); | 18 | |
16 | } | 19 | Network packet abstractions |
17 | if (!downscript) { | 20 | M: Dmitry Fleytman <dmitry.fleytman@gmail.com> |
18 | - downscript = default_downscript = get_relocated_path(DEFAULT_NETWORK_SCRIPT); | 21 | +R: Akihiko Odaki <akihiko.odaki@daynix.com> |
19 | + downscript = default_downscript = | 22 | S: Maintained |
20 | + get_relocated_path(DEFAULT_NETWORK_DOWN_SCRIPT); | 23 | F: include/net/eth.h |
21 | } | 24 | F: net/eth.c |
22 | |||
23 | if (tap->has_ifname) { | ||
24 | -- | 25 | -- |
25 | 2.7.4 | 26 | 2.7.4 |
26 | 27 | ||
27 | 28 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
1 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
4 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
5 | --- | ||
6 | docs/system/devices/igb.rst | 12 +++++++----- | ||
7 | 1 file changed, 7 insertions(+), 5 deletions(-) | ||
8 | |||
9 | diff --git a/docs/system/devices/igb.rst b/docs/system/devices/igb.rst | ||
10 | index XXXXXXX..XXXXXXX 100644 | ||
11 | --- a/docs/system/devices/igb.rst | ||
12 | +++ b/docs/system/devices/igb.rst | ||
13 | @@ -XXX,XX +XXX,XX @@ Limitations | ||
14 | =========== | ||
15 | |||
16 | This igb implementation was tested with Linux Test Project [2]_ and Windows HLK | ||
17 | -[3]_ during the initial development. The command used when testing with LTP is: | ||
18 | +[3]_ during the initial development. Later it was also tested with DPDK Test | ||
19 | +Suite [4]_. The command used when testing with LTP is: | ||
20 | |||
21 | .. code-block:: shell | ||
22 | |||
23 | @@ -XXX,XX +XXX,XX @@ This igb implementation was tested with Linux Test Project [2]_ and Windows HLK | ||
24 | |||
25 | Be aware that this implementation lacks many functionalities available with the | ||
26 | actual hardware, and you may experience various failures if you try to use it | ||
27 | -with a different operating system other than Linux and Windows or if you try | ||
28 | -functionalities not covered by the tests. | ||
29 | +with a different operating system other than DPDK, Linux, and Windows or if you | ||
30 | +try functionalities not covered by the tests. | ||
31 | |||
32 | Using igb | ||
33 | ========= | ||
34 | @@ -XXX,XX +XXX,XX @@ Using igb should be nothing different from using another network device. See | ||
35 | :ref:`Network_emulation` in general. | ||
36 | |||
37 | However, you may also need to perform additional steps to activate SR-IOV | ||
38 | -feature on your guest. For Linux, refer to [4]_. | ||
39 | +feature on your guest. For Linux, refer to [5]_. | ||
40 | |||
41 | Developing igb | ||
42 | ============== | ||
43 | @@ -XXX,XX +XXX,XX @@ References | ||
44 | .. [1] https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eb-gigabit-ethernet-controller-datasheet.pdf | ||
45 | .. [2] https://github.com/linux-test-project/ltp | ||
46 | .. [3] https://learn.microsoft.com/en-us/windows-hardware/test/hlk/ | ||
47 | -.. [4] https://docs.kernel.org/PCI/pci-iov-howto.html | ||
48 | +.. [4] https://doc.dpdk.org/dts/gsg/ | ||
49 | +.. [5] https://docs.kernel.org/PCI/pci-iov-howto.html | ||
50 | -- | ||
51 | 2.7.4 | diff view generated by jsdifflib |
1 | From: yuanjungong <ruc_gongyuanjun@163.com> | 1 | From: Stefan Hajnoczi <stefanha@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Close fd before returning. | 3 | If the driver sets large_send_mss to 0 then a divide-by-zero occurs. |
4 | Even if the division wasn't a problem, the for loop that emits MSS-sized | ||
5 | packets would never terminate. | ||
4 | 6 | ||
5 | Buglink: https://bugs.launchpad.net/qemu/+bug/1904486 | 7 | Solve these issues by skipping offloading when large_send_mss=0. |
6 | 8 | ||
7 | Signed-off-by: yuanjungong <ruc_gongyuanjun@163.com> | 9 | This issue was found by OSS-Fuzz as part of Alexander Bulekov's device |
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 10 | fuzzing work. The reproducer is: |
11 | |||
12 | $ cat << EOF | ./qemu-system-i386 -display none -machine accel=qtest, -m \ | ||
13 | 512M,slots=1,maxmem=0xffff000000000000 -machine q35 -nodefaults -device \ | ||
14 | rtl8139,netdev=net0 -netdev user,id=net0 -device \ | ||
15 | pc-dimm,id=nv1,memdev=mem1,addr=0xb800a64602800000 -object \ | ||
16 | memory-backend-ram,id=mem1,size=2M -qtest stdio | ||
17 | outl 0xcf8 0x80000814 | ||
18 | outl 0xcfc 0xe0000000 | ||
19 | outl 0xcf8 0x80000804 | ||
20 | outw 0xcfc 0x06 | ||
21 | write 0xe0000037 0x1 0x04 | ||
22 | write 0xe00000e0 0x2 0x01 | ||
23 | write 0x1 0x1 0x04 | ||
24 | write 0x3 0x1 0x98 | ||
25 | write 0xa 0x1 0x8c | ||
26 | write 0xb 0x1 0x02 | ||
27 | write 0xc 0x1 0x46 | ||
28 | write 0xd 0x1 0xa6 | ||
29 | write 0xf 0x1 0xb8 | ||
30 | write 0xb800a646028c000c 0x1 0x08 | ||
31 | write 0xb800a646028c000e 0x1 0x47 | ||
32 | write 0xb800a646028c0010 0x1 0x02 | ||
33 | write 0xb800a646028c0017 0x1 0x06 | ||
34 | write 0xb800a646028c0036 0x1 0x80 | ||
35 | write 0xe00000d9 0x1 0x40 | ||
36 | EOF | ||
37 | |||
38 | Buglink: https://gitlab.com/qemu-project/qemu/-/issues/1582 | ||
39 | Closes: https://gitlab.com/qemu-project/qemu/-/issues/1582 | ||
40 | Cc: qemu-stable@nongnu.org | ||
41 | Cc: Peter Maydell <peter.maydell@linaro.org> | ||
42 | Fixes: 6d71357a3b65 ("rtl8139: honor large send MSS value") | ||
43 | Reported-by: Alexander Bulekov <alxndr@bu.edu> | ||
44 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
45 | Tested-by: Alexander Bulekov <alxndr@bu.edu> | ||
46 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
9 | Signed-off-by: Jason Wang <jasowang@redhat.com> | 47 | Signed-off-by: Jason Wang <jasowang@redhat.com> |
10 | --- | 48 | --- |
11 | net/tap.c | 2 ++ | 49 | hw/net/rtl8139.c | 3 +++ |
12 | 1 file changed, 2 insertions(+) | 50 | 1 file changed, 3 insertions(+) |
13 | 51 | ||
14 | diff --git a/net/tap.c b/net/tap.c | 52 | diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c |
15 | index XXXXXXX..XXXXXXX 100644 | 53 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/net/tap.c | 54 | --- a/hw/net/rtl8139.c |
17 | +++ b/net/tap.c | 55 | +++ b/hw/net/rtl8139.c |
18 | @@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name, | 56 | @@ -XXX,XX +XXX,XX @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) |
19 | if (ret < 0) { | 57 | |
20 | error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", | 58 | int large_send_mss = (txdw0 >> CP_TC_LGSEN_MSS_SHIFT) & |
21 | name, fd); | 59 | CP_TC_LGSEN_MSS_MASK; |
22 | + close(fd); | 60 | + if (large_send_mss == 0) { |
23 | return -1; | 61 | + goto skip_offload; |
24 | } | 62 | + } |
25 | 63 | ||
26 | @@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name, | 64 | DPRINTF("+++ C+ mode offloaded task TSO IP data %d " |
27 | vhostfdname, vnet_hdr, fd, &err); | 65 | "frame data %d specified MSS=%d\n", |
28 | if (err) { | ||
29 | error_propagate(errp, err); | ||
30 | + close(fd); | ||
31 | return -1; | ||
32 | } | ||
33 | } else if (tap->has_fds) { | ||
34 | -- | 66 | -- |
35 | 2.7.4 | 67 | 2.7.4 |
36 | 68 | ||
37 | 69 | diff view generated by jsdifflib |