rte_ring_reset(txq->ring);
}
+static uint16_t
+sfc_repr_rx_burst(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ struct sfc_repr_rxq *rxq = rx_queue;
+ void **objs = (void *)&rx_pkts[0];
+
+ /* mbufs port is already filled correctly by representors proxy */
+ return rte_ring_sc_dequeue_burst(rxq->ring, objs, nb_pkts, NULL);
+}
+
+static uint16_t
+sfc_repr_tx_burst(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ struct sfc_repr_txq *txq = tx_queue;
+ unsigned int n_tx;
+ void **objs;
+ uint16_t i;
+
+ /*
+ * mbuf is likely cache-hot. Set flag and egress m-port here instead of
+ * doing that in representors proxy. Also, it should help to avoid
+ * cache bounce. Moreover, potentially, it allows to use one
+ * multi-producer single-consumer ring for all representors.
+ *
+ * The only potential problem is doing so many times if enqueue
+ * fails and sender retries.
+ */
+ for (i = 0; i < nb_pkts; ++i) {
+ struct rte_mbuf *m = tx_pkts[i];
+
+ m->ol_flags |= sfc_dp_mport_override;
+ *RTE_MBUF_DYNFIELD(m, sfc_dp_mport_offset,
+ efx_mport_id_t *) = txq->egress_mport;
+ }
+
+ objs = (void *)&tx_pkts[0];
+ n_tx = rte_ring_sp_enqueue_burst(txq->ring, objs, nb_pkts, NULL);
+
+ /*
+ * Remove m-port override flag from packets that were not enqueued
+ * Setting the flag only for enqueued packets after the burst is
+ * not possible since the ownership of enqueued packets is
+ * transferred to representor proxy.
+ */
+ for (i = n_tx; i < nb_pkts; ++i) {
+ struct rte_mbuf *m = tx_pkts[i];
+
+ m->ol_flags &= ~sfc_dp_mport_override;
+ }
+
+ return n_tx;
+}
+
static int
sfc_repr_start(struct rte_eth_dev *dev)
{
(void)sfc_repr_proxy_del_port(srs->pf_port_id, srs->repr_id);
+ dev->rx_pkt_burst = NULL;
+ dev->tx_pkt_burst = NULL;
dev->dev_ops = NULL;
sfc_repr_unlock(sr);
goto fail_mac_addrs;
}
+ dev->rx_pkt_burst = sfc_repr_rx_burst;
+ dev->tx_pkt_burst = sfc_repr_tx_burst;
dev->dev_ops = &sfc_repr_dev_ops;
sr->state = SFC_ETHDEV_INITIALIZED;
struct sfc_repr_init_data repr_data;
char name[RTE_ETH_NAME_MAX_LEN];
int ret;
+ struct rte_eth_dev *dev;
if (snprintf(name, sizeof(name), "net_%s_representor_%u",
parent->device->name, representor_id) >=
return -ENAMETOOLONG;
}
- memset(&repr_data, 0, sizeof(repr_data));
- repr_data.pf_port_id = parent->data->port_id;
- repr_data.repr_id = representor_id;
- repr_data.switch_domain_id = switch_domain_id;
- repr_data.mport_sel = *mport_sel;
-
- ret = rte_eth_dev_create(parent->device, name,
- sizeof(struct sfc_repr_shared),
- NULL, NULL,
- sfc_repr_eth_dev_init, &repr_data);
- if (ret != 0)
- SFC_GENERIC_LOG(ERR, "%s() failed to create device", __func__);
-
- SFC_GENERIC_LOG(INFO, "%s() done: %s", __func__, rte_strerror(-ret));
+ dev = rte_eth_dev_allocated(name);
+ if (dev == NULL) {
+ memset(&repr_data, 0, sizeof(repr_data));
+ repr_data.pf_port_id = parent->data->port_id;
+ repr_data.repr_id = representor_id;
+ repr_data.switch_domain_id = switch_domain_id;
+ repr_data.mport_sel = *mport_sel;
+
+ ret = rte_eth_dev_create(parent->device, name,
+ sizeof(struct sfc_repr_shared),
+ NULL, NULL,
+ sfc_repr_eth_dev_init, &repr_data);
+ if (ret != 0) {
+ SFC_GENERIC_LOG(ERR, "%s() failed to create device",
+ __func__);
+ return ret;
+ }
+ }
- return ret;
+ return 0;
}