aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincenzo Maffione <vmaffione@FreeBSD.org>2021-01-24 21:12:41 +0000
committerVincenzo Maffione <vmaffione@FreeBSD.org>2021-01-31 08:52:45 +0000
commite0e00874a3c30a8d418417d5901c065f15b5896e (patch)
treea94b5c84614c6b80d44f4ce171767d4fdbfa2d63
parent7754ef5a37245271c2a6832ad0a1289e25abff09 (diff)
downloadsrc-e0e00874a3c30a8d418417d5901c065f15b5896e.tar.gz
src-e0e00874a3c30a8d418417d5901c065f15b5896e.zip
iflib: netmap: add support for NS_MOREFRAG
The NS_MOREFRAG flag can be set in a netmap slot to represent a multi-fragment packet. Only the last fragment of a packet does not have the flag set. On TX rings, the flag may be set by the userspace application. The kernel will look at the flag and use it to properly set up the NIC TX descriptors. On RX rings, the kernel may set the flag if the packet received was split across multiple netmap buffers. The userspace application should look at the flag to know when the packet is complete. Submitted by: rajesh1.kumar_amd.com Reviewed by: vmaffione MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D27799 (cherry picked from commit aceaccab659c9eb846fb21ff99be34434a9616c7)
-rw-r--r--sys/net/iflib.c82
1 files changed, 58 insertions, 24 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index ea2c5789a7b5..0d4124599419 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -1005,6 +1005,8 @@ iflib_netmap_txsync(struct netmap_kring *kring, int flags)
nm_i = kring->nr_hwcur;
if (nm_i != head) { /* we have new packets to send */
+ uint32_t pkt_len = 0, seg_idx = 0;
+ int nic_i_start = -1, flags = 0;
pkt_info_zero(&pi);
pi.ipi_segs = txq->ift_segs;
pi.ipi_qsidx = kring->ring_id;
@@ -1019,22 +1021,40 @@ iflib_netmap_txsync(struct netmap_kring *kring, int flags)
u_int len = slot->len;
uint64_t paddr;
void *addr = PNMB(na, slot, &paddr);
- int flags = (slot->flags & NS_REPORT ||
+
+ flags |= (slot->flags & NS_REPORT ||
nic_i == 0 || nic_i == report_frequency) ?
IPI_TX_INTR : 0;
- /* device-specific */
- pi.ipi_len = len;
- pi.ipi_segs[0].ds_addr = paddr;
- pi.ipi_segs[0].ds_len = len;
- pi.ipi_nsegs = 1;
- pi.ipi_ndescs = 0;
- pi.ipi_pidx = nic_i;
- pi.ipi_flags = flags;
+ /*
+ * If this is the first packet fragment, save the
+ * index of the first NIC slot for later.
+ */
+ if (nic_i_start < 0)
+ nic_i_start = nic_i;
+
+ pi.ipi_segs[seg_idx].ds_addr = paddr;
+ pi.ipi_segs[seg_idx].ds_len = len;
+ if (len) {
+ pkt_len += len;
+ seg_idx++;
+ }
- /* Fill the slot in the NIC ring. */
- ctx->isc_txd_encap(ctx->ifc_softc, &pi);
- DBG_COUNTER_INC(tx_encap);
+ if (!(slot->flags & NS_MOREFRAG)) {
+ pi.ipi_len = pkt_len;
+ pi.ipi_nsegs = seg_idx;
+ pi.ipi_pidx = nic_i_start;
+ pi.ipi_ndescs = 0;
+ pi.ipi_flags = flags;
+
+ /* Prepare the NIC TX ring. */
+ ctx->isc_txd_encap(ctx->ifc_softc, &pi);
+ DBG_COUNTER_INC(tx_encap);
+
+ /* Reinit per-packet info for the next one. */
+ flags = seg_idx = pkt_len = 0;
+ nic_i_start = -1;
+ }
/* prefetch for next round */
__builtin_prefetch(&ring->slot[nm_i + 1]);
@@ -1053,7 +1073,7 @@ iflib_netmap_txsync(struct netmap_kring *kring, int flags)
txq->ift_sds.ifsd_map[nic_i],
BUS_DMASYNC_PREWRITE);
- slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
+ slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED | NS_MOREFRAG);
nm_i = nm_next(nm_i, lim);
nic_i = nm_next(nic_i, lim);
}
@@ -1116,6 +1136,7 @@ iflib_netmap_rxsync(struct netmap_kring *kring, int flags)
u_int n;
u_int const lim = kring->nkr_num_slots - 1;
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
+ int i = 0;
if_ctx_t ctx = ifp->if_softc;
if_shared_ctx_t sctx = ctx->ifc_sctx;
@@ -1177,17 +1198,30 @@ iflib_netmap_rxsync(struct netmap_kring *kring, int flags)
ri.iri_cidx = *cidxp;
error = ctx->isc_rxd_pkt_get(ctx->ifc_softc, &ri);
- ring->slot[nm_i].len = error ? 0 : ri.iri_len - crclen;
- ring->slot[nm_i].flags = 0;
- if (have_rxcq) {
- *cidxp = ri.iri_cidx;
- while (*cidxp >= scctx->isc_nrxd[0])
- *cidxp -= scctx->isc_nrxd[0];
+ for (i = 0; i < ri.iri_nfrags; i++) {
+ if (error) {
+ ring->slot[nm_i].len = 0;
+ ring->slot[nm_i].flags = 0;
+ } else {
+ ring->slot[nm_i].len = ri.iri_frags[i].irf_len;
+ if (i == (ri.iri_nfrags - 1)) {
+ ring->slot[nm_i].len -= crclen;
+ ring->slot[nm_i].flags = 0;
+ } else
+ ring->slot[nm_i].flags = NS_MOREFRAG;
+ }
+
+ if (have_rxcq) {
+ *cidxp = ri.iri_cidx;
+ while (*cidxp >= scctx->isc_nrxd[0])
+ *cidxp -= scctx->isc_nrxd[0];
+ }
+
+ bus_dmamap_sync(fl->ifl_buf_tag,
+ fl->ifl_sds.ifsd_map[nic_i], BUS_DMASYNC_POSTREAD);
+ nm_i = nm_next(nm_i, lim);
+ fl->ifl_cidx = nic_i = nm_next(nic_i, lim);
}
- bus_dmamap_sync(fl->ifl_buf_tag,
- fl->ifl_sds.ifsd_map[nic_i], BUS_DMASYNC_POSTREAD);
- nm_i = nm_next(nm_i, lim);
- fl->ifl_cidx = nic_i = nm_next(nic_i, lim);
}
if (n) { /* update the state variables */
if (netmap_no_pendintr && !force_update) {
@@ -1234,7 +1268,7 @@ iflib_netmap_attach(if_ctx_t ctx)
bzero(&na, sizeof(na));
na.ifp = ctx->ifc_ifp;
- na.na_flags = NAF_BDG_MAYSLEEP;
+ na.na_flags = NAF_BDG_MAYSLEEP | NAF_MOREFRAG;
MPASS(ctx->ifc_softc_ctx.isc_ntxqsets);
MPASS(ctx->ifc_softc_ctx.isc_nrxqsets);