diff options
Diffstat (limited to 'vnet/vnet/devices/dpdk/device.c')
-rw-r--r-- | vnet/vnet/devices/dpdk/device.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/vnet/vnet/devices/dpdk/device.c b/vnet/vnet/devices/dpdk/device.c index 011ec75e..20c8b8f7 100644 --- a/vnet/vnet/devices/dpdk/device.c +++ b/vnet/vnet/devices/dpdk/device.c @@ -77,7 +77,7 @@ dpdk_set_mc_filter (vnet_hw_interface_t * hi, } } -static struct rte_mbuf * dpdk_replicate_packet_mb (vlib_buffer_t * b) +struct rte_mbuf * dpdk_replicate_packet_mb (vlib_buffer_t * b) { vlib_main_t * vm = vlib_get_main(); vlib_buffer_main_t * bm = vm->buffer_main; @@ -147,6 +147,74 @@ static struct rte_mbuf * dpdk_replicate_packet_mb (vlib_buffer_t * b) return first_mb; } +struct rte_mbuf * dpdk_zerocopy_replicate_packet_mb (vlib_buffer_t * b) +{ + vlib_main_t * vm = vlib_get_main(); + vlib_buffer_main_t * bm = vm->buffer_main; + struct rte_mbuf * first_mb = 0, * new_mb, * pkt_mb, ** prev_mb_next = 0; + u8 nb_segs, nb_segs_left; + unsigned socket_id = rte_socket_id(); + + ASSERT (bm->pktmbuf_pools[socket_id]); + pkt_mb = rte_mbuf_from_vlib_buffer(b); + nb_segs = pkt_mb->nb_segs; + for (nb_segs_left = nb_segs; nb_segs_left; nb_segs_left--) + { + if (PREDICT_FALSE(pkt_mb == 0)) + { + clib_warning ("Missing %d mbuf chain segment(s): " + "(nb_segs = %d, nb_segs_left = %d)!", + nb_segs - nb_segs_left, nb_segs, nb_segs_left); + if (first_mb) + rte_pktmbuf_free(first_mb); + return NULL; + } + new_mb = rte_pktmbuf_clone(pkt_mb, bm->pktmbuf_pools[socket_id]); + if (PREDICT_FALSE(new_mb == 0)) + { + if (first_mb) + rte_pktmbuf_free(first_mb); + return NULL; + } + + /* + * Copy packet info into 1st segment. + */ + if (first_mb == 0) + { + first_mb = new_mb; + rte_pktmbuf_pkt_len (first_mb) = pkt_mb->pkt_len; + first_mb->nb_segs = pkt_mb->nb_segs; + first_mb->port = pkt_mb->port; +#ifdef DAW_FIXME // TX Offload support TBD + first_mb->vlan_macip = pkt_mb->vlan_macip; + first_mb->hash = pkt_mb->hash; + first_mb->ol_flags = pkt_mb->ol_flags +#endif + } + else + { + ASSERT(prev_mb_next != 0); + *prev_mb_next = new_mb; + } + + /* + * Copy packet segment data into new mbuf segment. + */ + rte_pktmbuf_data_len (new_mb) = pkt_mb->data_len; + + prev_mb_next = &new_mb->next; + pkt_mb = pkt_mb->next; + } + + ASSERT(pkt_mb == 0); + __rte_mbuf_sanity_check(first_mb, 1); + + return first_mb; + + +} + static void dpdk_tx_trace_buffer (dpdk_main_t * dm, vlib_node_runtime_t * node, @@ -686,7 +754,7 @@ dpdk_interface_tx (vlib_main_t * vm, i++; } } - + n_left -= 2; } while (n_left > 0) |