aboutsummaryrefslogtreecommitdiff
path: root/hw/net/rocker
diff options
context:
space:
mode:
authorScott Feldman <sfeldma@gmail.com>2015-07-01 03:33:11 -0700
committerStefan Hajnoczi <stefanha@redhat.com>2015-07-07 13:13:22 +0100
commitd0d2555852c5e684a97dce787d3c2a65b9a6d64c (patch)
tree32c7e6883aecc7070afecfcd81fd5f41a82bc606 /hw/net/rocker
parent96497af0afd60e57749316f1bc196b417055c585 (diff)
rocker: mark copy-to-cpu pkts as forwarding offloaded
For pkts copied to the CPU (to be processed by guest driver), mark the Rx descriptor with flag "OFFLOAD_FWD" to indicate device has already forwarded pkt. The guest driver will use this indicator to avoid duplicate forwarding in the guest OS. Examples include bcast/mcast/unknown ucast pkts flooded to bridged ports. We want to avoid both the device and the guest bridge driver flooding these pkts, which would result in duplicates pkts on the wire. Packet sampling, such as sFlow, can also use this technique to mark pkts for the guest OS to record but otherwise drop. Signed-off-by: Scott Feldman <sfeldma@gmail.com> Message-id: 1435746792-41278-5-git-send-email-sfeldma@gmail.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/net/rocker')
-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
4 files changed, 11 insertions, 3 deletions
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,