Index: tools/tools/netmap/bridge.c =================================================================== --- tools/tools/netmap/bridge.c +++ tools/tools/netmap/bridge.c @@ -68,6 +68,7 @@ u_int limit, const char *msg) { u_int j, k, m = 0; + u_int pkt_len = 0; /* print a warning if any of the ring flags is set (e.g. NM_REINIT) */ if (rxring->flags || txring->flags) @@ -103,21 +104,32 @@ } ts->len = rs->len; if (zerocopy) { - uint32_t pkt = ts->buf_idx; + uint32_t flags, pkt; + pkt = ts->buf_idx; ts->buf_idx = rs->buf_idx; rs->buf_idx = pkt; /* report the buffer change. */ ts->flags |= NS_BUF_CHANGED; rs->flags |= NS_BUF_CHANGED; /* copy the NS_MOREFRAG */ + flags = rs->flags; rs->flags = (rs->flags & ~NS_MOREFRAG) | (ts->flags & NS_MOREFRAG); + ts->flags = (ts->flags & ~NS_MOREFRAG) | (flags & NS_MOREFRAG); + j = nm_ring_next(rxring, j); + k = nm_ring_next(txring, k); } else { char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); char *txbuf = NETMAP_BUF(txring, ts->buf_idx); - nm_pkt_copy(rxbuf, txbuf, ts->len); + nm_pkt_copy(rxbuf, txbuf + pkt_len, ts->len); + pkt_len += ts->len; + + j = nm_ring_next(rxring, j); + if (!(rs->flags & NS_MOREFRAG)) { + ts->len = pkt_len; + k = nm_ring_next(txring, k); + pkt_len = 0; + } } - j = nm_ring_next(rxring, j); - k = nm_ring_next(txring, k); } rxring->head = rxring->cur = j; txring->head = txring->cur = k;