From 571ce47d2afc1e138010dc62c21d10367555b2eb Mon Sep 17 00:00:00 2001 From: Michal Mazur Date: Thu, 11 Jan 2018 18:32:32 +0100 Subject: plugins: odp: Add support for buffer recycling Buffers with VLIB_BUFFER_RECYCLE flag set should not be freed. They are replicated on send and sent back to vlib for processing. Change-Id: If381884fa7c898253f35dc3a39feeb4eb1529286 Signed-off-by: Michal Mazur --- src/plugins/odp/device.c | 66 ++++++++++++++++++++++++++++++++++++++---------- src/plugins/odp/node.c | 1 + 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/plugins/odp/device.c b/src/plugins/odp/device.c index 4f809836..27a05949 100755 --- a/src/plugins/odp/device.c +++ b/src/plugins/odp/device.c @@ -76,6 +76,27 @@ format_odp_packet_tx_trace (u8 * s, va_list * args) n_left--; \ } +static_always_inline int +odp_buffer_recycle (vlib_main_t * vm, odp_packet_main_t * om, + odp_packet_t * pkt, vlib_buffer_t * b, u32 bi, + u32 ** recycle) +{ + if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_RECYCLE) == 0)) + return 1; + + odp_packet_t new = odp_packet_copy (*pkt, om->pool); + vec_add1 (*recycle, bi); + + if (PREDICT_FALSE (new == ODP_PACKET_INVALID)) + { + b->flags |= VLIB_BUFFER_REPL_FAIL; + return 0; + } + + *pkt = new; + return 1; +} + static uword odp_packet_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -97,12 +118,13 @@ odp_packet_interface_tx (vlib_main_t * vm, vlib_buffer_t *b0, *b1, *b2, *b3; u32 bi[4]; u32 sent, count = 0, todo = 0; + u32 *recycle = NULL; while (n_left > 0 || todo > 0) { int ret; - for (; todo < 4 && todo < n_left; todo++, n_left--) + for (; (todo < 4) && (n_left > 0); todo++, n_left--) bi[todo] = *buffers++; while ((todo == 4) && (count + 3 < burst_size)) @@ -126,17 +148,25 @@ odp_packet_interface_tx (vlib_main_t * vm, if (mode == APPL_MODE_PKT_QUEUE) { - tbl.evt[count++] = odp_packet_to_event (pkt0); - tbl.evt[count++] = odp_packet_to_event (pkt1); - tbl.evt[count++] = odp_packet_to_event (pkt2); - tbl.evt[count++] = odp_packet_to_event (pkt3); + if (odp_buffer_recycle (vm, om, &pkt0, b0, bi[0], &recycle)) + tbl.evt[count++] = odp_packet_to_event (pkt0); + if (odp_buffer_recycle (vm, om, &pkt1, b1, bi[1], &recycle)) + tbl.evt[count++] = odp_packet_to_event (pkt1); + if (odp_buffer_recycle (vm, om, &pkt2, b2, bi[2], &recycle)) + tbl.evt[count++] = odp_packet_to_event (pkt2); + if (odp_buffer_recycle (vm, om, &pkt3, b3, bi[3], &recycle)) + tbl.evt[count++] = odp_packet_to_event (pkt3); } else { - tbl.pkt[count++] = pkt0; - tbl.pkt[count++] = pkt1; - tbl.pkt[count++] = pkt2; - tbl.pkt[count++] = pkt3; + if (odp_buffer_recycle (vm, om, &pkt0, b0, bi[0], &recycle)) + tbl.pkt[count++] = pkt0; + if (odp_buffer_recycle (vm, om, &pkt1, b1, bi[1], &recycle)) + tbl.pkt[count++] = pkt1; + if (odp_buffer_recycle (vm, om, &pkt2, b2, bi[2], &recycle)) + tbl.pkt[count++] = pkt2; + if (odp_buffer_recycle (vm, om, &pkt3, b3, bi[3], &recycle)) + tbl.pkt[count++] = pkt3; } todo = 0; @@ -156,10 +186,13 @@ odp_packet_interface_tx (vlib_main_t * vm, odp_adjust_data_pointers (b0, pkt); - if (mode == APPL_MODE_PKT_QUEUE) - tbl.evt[count++] = odp_packet_to_event (pkt); - else - tbl.pkt[count++] = pkt; + if (odp_buffer_recycle (vm, om, &pkt, b0, bi[todo - 1], &recycle)) + { + if (mode == APPL_MODE_PKT_QUEUE) + tbl.evt[count++] = odp_packet_to_event (pkt); + else + tbl.pkt[count++] = pkt; + } if (b0->flags & VLIB_BUFFER_NEXT_PRESENT) bi[todo - 1] = b0->next_buffer; @@ -206,6 +239,13 @@ odp_packet_interface_tx (vlib_main_t * vm, } } + /* Recycle replicated buffers */ + if (PREDICT_FALSE (recycle != NULL)) + { + vlib_buffer_free (vm, recycle, vec_len (recycle)); + vec_free (recycle); + } + return (frame->n_vectors - n_left); } diff --git a/src/plugins/odp/node.c b/src/plugins/odp/node.c index fea8bf6a..e0b468a2 100755 --- a/src/plugins/odp/node.c +++ b/src/plugins/odp/node.c @@ -179,6 +179,7 @@ odp_adjust_buffer (vlib_buffer_t * buf, odp_packet_t pkt, buf->current_data = 0; buf->total_length_not_including_first_buffer = 0; buf->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID; + buf->free_list_index = VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX; vnet_buffer (buf)->sw_if_index[VLIB_RX] = oif->sw_if_index; vnet_buffer (buf)->sw_if_index[VLIB_TX] = (u32) ~ 0; } -- cgit 1.2.3-korg