aboutsummaryrefslogtreecommitdiff
path: root/hw/net/rocker
diff options
context:
space:
mode:
Diffstat (limited to 'hw/net/rocker')
-rw-r--r--hw/net/rocker/rocker.c11
-rw-r--r--hw/net/rocker/rocker.h2
-rw-r--r--hw/net/rocker/rocker_fp.c18
-rw-r--r--hw/net/rocker/rocker_hw.h1
-rw-r--r--hw/net/rocker/rocker_of_dpa.c7
-rw-r--r--hw/net/rocker/rocker_world.c2
6 files changed, 27 insertions, 14 deletions
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 4d25842509..47d080fd33 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -96,7 +96,7 @@ World *rocker_get_world(Rocker *r, enum rocker_world_type type)
RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
{
- RockerSwitch *rocker = g_malloc0(sizeof(*rocker));
+ RockerSwitch *rocker;
Rocker *r;
r = rocker_find(name);
@@ -106,6 +106,7 @@ RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
return NULL;
}
+ rocker = g_new0(RockerSwitch, 1);
rocker->name = g_strdup(r->name);
rocker->id = r->switch_id;
rocker->ports = r->fp_ports;
@@ -192,11 +193,13 @@ static int tx_consume(Rocker *r, DescInfo *info)
if (!tlvs[ROCKER_TLV_TX_L3_CSUM_OFF]) {
return -ROCKER_EINVAL;
}
+ break;
case ROCKER_TX_OFFLOAD_TSO:
if (!tlvs[ROCKER_TLV_TX_TSO_MSS] ||
!tlvs[ROCKER_TLV_TX_TSO_HDR_LEN]) {
return -ROCKER_EINVAL;
}
+ break;
}
if (tlvs[ROCKER_TLV_TX_L3_CSUM_OFF]) {
@@ -600,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;
@@ -643,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_fp.c b/hw/net/rocker/rocker_fp.c
index d8d934c396..c693ae5081 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -125,18 +125,21 @@ int fp_port_eg(FpPort *port, const struct iovec *iov, int iovcnt)
return ROCKER_OK;
}
-static int fp_port_can_receive(NetClientState *nc)
-{
- FpPort *port = qemu_get_nic_opaque(nc);
-
- return port->enabled;
-}
-
static ssize_t fp_port_receive_iov(NetClientState *nc, const struct iovec *iov,
int iovcnt)
{
FpPort *port = qemu_get_nic_opaque(nc);
+ /* If the port is disabled, we want to drop this pkt
+ * now rather than queing it for later. We don't want
+ * any stale pkts getting into the device when the port
+ * transitions to enabled.
+ */
+
+ if (!port->enabled) {
+ return -1;
+ }
+
return world_ingress(port->world, port->pport, iov, iovcnt);
}
@@ -165,7 +168,6 @@ static void fp_port_set_link_status(NetClientState *nc)
static NetClientInfo fp_port_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
- .can_receive = fp_port_can_receive,
.receive = fp_port_receive,
.receive_iov = fp_port_receive_iov,
.cleanup = fp_port_cleanup,
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 b25a17d6d7..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,
@@ -2525,7 +2528,6 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
ngroup->has_set_vlan_id = true;
ngroup->set_vlan_id = ntohs(group->l2_rewrite.vlan_id);
}
- break;
if (memcmp(group->l2_rewrite.src_mac.a, zero_mac.a, ETH_ALEN)) {
ngroup->has_set_eth_src = true;
ngroup->set_eth_src =
@@ -2536,6 +2538,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
ngroup->set_eth_dst =
qemu_mac_strdup_printf(group->l2_rewrite.dst_mac.a);
}
+ break;
case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD:
case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST:
ngroup->has_vlan_id = true;
diff --git a/hw/net/rocker/rocker_world.c b/hw/net/rocker/rocker_world.c
index b991e871d3..a6b18f1754 100644
--- a/hw/net/rocker/rocker_world.c
+++ b/hw/net/rocker/rocker_world.c
@@ -32,7 +32,7 @@ ssize_t world_ingress(World *world, uint32_t pport,
return world->ops->ig(world, pport, iov, iovcnt);
}
- return iov_size(iov, iovcnt);
+ return -1;
}
int world_do_cmd(World *world, DescInfo *info,