summaryrefslogtreecommitdiffstats
path: root/sys/dev/netmap
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/netmap')
-rw-r--r--sys/dev/netmap/netmap.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c
index e1beeae7..139eb89 100644
--- a/sys/dev/netmap/netmap.c
+++ b/sys/dev/netmap/netmap.c
@@ -188,8 +188,9 @@ static int kern_netmap_regif(struct nmreq *nmr);
/* per-tx-queue entry */
struct nm_bdg_fwd { /* forwarding entry for a bridge */
- void *buf;
- uint32_t ft_dst; /* dst port */
+ void *ft_buf;
+ uint16_t _ft_dst; /* dst port, unused */
+ uint16_t ft_flags; /* flags, e.g. indirect */
uint16_t ft_len; /* src len */
uint16_t ft_next; /* next packet to same destination */
};
@@ -2289,8 +2290,10 @@ bdg_netmap_start(struct ifnet *ifp, struct mbuf *m)
if (!na->na_bdg) /* SWNA is not configured to be attached */
return EBUSY;
m_copydata(m, 0, len, buf);
+ ft->ft_flags = 0; // XXX could be indirect ?
ft->ft_len = len;
- ft->buf = buf;
+ ft->ft_buf = buf;
+ ft->ft_next = NM_BDG_BATCH; // XXX is it needed ?
nm_bdg_flush(ft, 1, na, 0);
/* release the mbuf in either cases of success or failure. As an
@@ -2435,12 +2438,19 @@ nm_bdg_preflush(struct netmap_adapter *na, u_int ring_nr,
for (; likely(j != end); j = unlikely(j == lim) ? 0 : j+1) {
struct netmap_slot *slot = &ring->slot[j];
+ char *buf = NMB(slot);
int len = ft[ft_i].ft_len = slot->len;
- char *buf = ft[ft_i].buf = NMB(slot);
- prefetch(buf);
+ ft[ft_i].ft_flags = slot->flags;
+
+ ND("flags is 0x%x", slot->flags);
+ /* this slot goes into a list so initialize the link field */
+ ft[ft_i].ft_next = NM_BDG_BATCH; /* equivalent to NULL */
if (unlikely(len < 14))
continue;
+ buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ?
+ *((void **)buf) : buf;
+ prefetch(buf);
if (unlikely(++ft_i == netmap_bridge))
ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr);
}
@@ -2935,7 +2945,7 @@ nm_bdg_flush(struct nm_bdg_fwd *ft, int n, struct netmap_adapter *na,
/* first pass: find a destination */
for (i = 0; likely(i < n); i++) {
- uint8_t *buf = ft[i].buf;
+ uint8_t *buf = ft[i].ft_buf;
uint8_t dst_ring = ring_nr;
uint16_t dst_port, d_i;
struct nm_bdg_q *d;
@@ -2960,9 +2970,10 @@ nm_bdg_flush(struct nm_bdg_fwd *ft, int n, struct netmap_adapter *na,
/* remember this position to be scanned later */
if (dst_port != NM_BDG_BROADCAST)
dsts[num_dsts++] = d_i;
+ } else {
+ ft[d->bq_tail].ft_next = i;
+ d->bq_tail = i;
}
- ft[d->bq_tail].ft_next = i;
- d->bq_tail = i;
}
/* if there is a broadcast, set ring 0 of all ports to be scanned
@@ -3043,20 +3054,36 @@ retry:
struct netmap_slot *slot;
struct nm_bdg_fwd *ft_p;
+ /* our 'NULL' is always higher than valid indexes
+ * so we never dereference it if the other list
+ * has packets (and if both are NULL we never
+ * get here).
+ */
if (next < brd_next) {
ft_p = ft + next;
next = ft_p->ft_next;
+ ND("j %d uni %d next %d %d",
+ j, ft_p - ft, next, brd_next);
} else { /* insert broadcast */
ft_p = ft + brd_next;
brd_next = ft_p->ft_next;
+ ND("j %d brd %d next %d %d",
+ j, ft_p - ft, next, brd_next);
}
slot = &ring->slot[j];
ND("send %d %d bytes at %s:%d", i, ft_p->ft_len, dst_ifp->if_xname, j);
- pkt_copy(ft_p->buf, NMB(slot), ft_p->ft_len);
+ if (ft_p->ft_flags & NS_INDIRECT) {
+ ND("copying from INDIRECT source");
+ copyin(ft_p->ft_buf, NMB(slot),
+ (ft_p->ft_len + 63) & ~63);
+ } else {
+ pkt_copy(ft_p->ft_buf, NMB(slot), ft_p->ft_len);
+ }
slot->len = ft_p->ft_len;
- j = (j == lim) ? 0: j + 1; /* XXX to be macro-ed */
+ j = unlikely(j == lim) ? 0: j + 1; /* XXX to be macro-ed */
sent++;
- if (next == d->bq_tail && brd_next == brddst->bq_tail)
+ /* are we done ? */
+ if (next == NM_BDG_BATCH && brd_next == NM_BDG_BATCH)
break;
}
if (netmap_verbose && (howmany < 0))
@@ -3078,6 +3105,7 @@ retry:
goto retry;
dst_na->nm_lock(dst_ifp, NETMAP_TX_UNLOCK, dst_nr);
}
+ /* NM_BDG_BATCH means 'no packet' */
d->bq_head = d->bq_tail = NM_BDG_BATCH; /* cleanup */
}
brddst->bq_head = brddst->bq_tail = NM_BDG_BATCH; /* cleanup */
OpenPOWER on IntegriCloud