aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/specs/rocker.txt4
-rw-r--r--hw/net/rocker/rocker.c6
-rw-r--r--hw/net/rocker/rocker.h2
-rw-r--r--hw/net/rocker/rocker_hw.h1
-rw-r--r--hw/net/rocker/rocker_of_dpa.c5
5 files changed, 15 insertions, 3 deletions
diff --git a/docs/specs/rocker.txt b/docs/specs/rocker.txt
index 0af5c61585..1c743515c1 100644
--- a/docs/specs/rocker.txt
+++ b/docs/specs/rocker.txt
@@ -637,6 +637,7 @@ The TLVs for Rx descriptor buffer are:
(1 << 5): TCP packet
(1 << 6): UDP packet
(1 << 7): TCP/UDP csum good
+ (1 << 8): Offload forward
RX_CSUM 2 IP calculated checksum:
IPv4: IP payload csum
IPv6: header and payload csum
@@ -645,6 +646,9 @@ The TLVs for Rx descriptor buffer are:
RX_FRAG_MAX_LEN 2 Packet maximum fragment length
RX_FRAG_LEN 2 Actual packet fragment length after receive
+Offload forward RX_FLAG indicates the device has already forwarded the packet
+so the host CPU should not also forward the packet.
+
Possible status return codes in descriptor on completion are:
DESC_COMP_ERR reason
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 6e3d35ae84..47d080fd33 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -603,7 +603,7 @@ static DescRing *rocker_get_rx_ring_by_pport(Rocker *r,
}
int rx_produce(World *world, uint32_t pport,
- const struct iovec *iov, int iovcnt)
+ const struct iovec *iov, int iovcnt, uint8_t copy_to_cpu)
{
Rocker *r = world_rocker(world);
PCIDevice *dev = (PCIDevice *)r;
@@ -646,6 +646,10 @@ int rx_produce(World *world, uint32_t pport,
goto out;
}
+ if (copy_to_cpu) {
+ rx_flags |= ROCKER_RX_FLAGS_FWD_OFFLOAD;
+ }
+
/* XXX calc rx flags/csum */
tlv_size = rocker_tlv_total_size(sizeof(uint16_t)) + /* flags */
diff --git a/hw/net/rocker/rocker.h b/hw/net/rocker/rocker.h
index b3310b61eb..f9c80f8013 100644
--- a/hw/net/rocker/rocker.h
+++ b/hw/net/rocker/rocker.h
@@ -77,7 +77,7 @@ int rocker_event_link_changed(Rocker *r, uint32_t pport, bool link_up);
int rocker_event_mac_vlan_seen(Rocker *r, uint32_t pport, uint8_t *addr,
uint16_t vlan_id);
int rx_produce(World *world, uint32_t pport,
- const struct iovec *iov, int iovcnt);
+ const struct iovec *iov, int iovcnt, uint8_t copy_to_cpu);
int rocker_port_eg(Rocker *r, uint32_t pport,
const struct iovec *iov, int iovcnt);
diff --git a/hw/net/rocker/rocker_hw.h b/hw/net/rocker/rocker_hw.h
index fe639badd4..8c50830325 100644
--- a/hw/net/rocker/rocker_hw.h
+++ b/hw/net/rocker/rocker_hw.h
@@ -250,6 +250,7 @@ enum {
#define ROCKER_RX_FLAGS_TCP (1 << 5)
#define ROCKER_RX_FLAGS_UDP (1 << 6)
#define ROCKER_RX_FLAGS_TCP_UDP_CSUM_GOOD (1 << 7)
+#define ROCKER_RX_FLAGS_FWD_OFFLOAD (1 << 8)
/* Tx msg */
enum {
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 02b3896a76..874fb01d69 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -825,6 +825,8 @@ static OfDpaGroup *of_dpa_group_alloc(uint32_t id)
static void of_dpa_output_l2_interface(OfDpaFlowContext *fc,
OfDpaGroup *group)
{
+ uint8_t copy_to_cpu = fc->action_set.apply.copy_to_cpu;
+
if (group->l2_interface.pop_vlan) {
of_dpa_flow_pkt_strip_vlan(fc);
}
@@ -837,7 +839,8 @@ static void of_dpa_output_l2_interface(OfDpaFlowContext *fc,
*/
if (group->l2_interface.out_pport == 0) {
- rx_produce(fc->of_dpa->world, fc->in_pport, fc->iov, fc->iovcnt);
+ rx_produce(fc->of_dpa->world, fc->in_pport, fc->iov, fc->iovcnt,
+ copy_to_cpu);
} else if (group->l2_interface.out_pport != fc->in_pport) {
rocker_port_eg(world_rocker(fc->of_dpa->world),
group->l2_interface.out_pport,