- if (do_segmentation)
- {
- if (PREDICT_FALSE (b[0]->flags & VNET_BUFFER_F_GSO))
- {
- /*
- * Undo the enqueue of the b0 - it is not going anywhere,
- * and will be freed either after it's segmented or
- * when dropped, if there is no buffers to segment into.
- */
- to_tx -= 1;
- n_left_to_tx += 1;
- /* undo the counting. */
- n_bytes -= n_bytes_b0;
- n_packets -= 1;
-
- u32 n_tx_bytes = 0;
-
- n_tx_bytes =
- tso_segment_buffer (vm, ptd, do_tx_offloads, bi0, b[0],
- n_bytes_b0);
-
- if (PREDICT_FALSE (n_tx_bytes == 0))
- {
- drop_one_buffer_and_count (vm, vnm, node, from - 1,
- VNET_INTERFACE_OUTPUT_ERROR_NO_BUFFERS_FOR_GSO);
- b += 1;
- continue;
- }
-
- u16 n_tx_bufs = vec_len (ptd->split_buffers);
- u32 *from_tx_seg = ptd->split_buffers;
-
- while (n_tx_bufs > 0)
- {
- if (n_tx_bufs >= n_left_to_tx)
- {
- while (n_left_to_tx > 0)
- {
- to_tx[0] = from_tx_seg[0];
- to_tx += 1;
- from_tx_seg += 1;
- n_left_to_tx -= 1;
- n_tx_bufs -= 1;
- n_packets += 1;
- }
- vlib_put_next_frame (vm, node, next_index,
- n_left_to_tx);
- vlib_get_new_next_frame (vm, node, next_index,
- to_tx, n_left_to_tx);
- }
- while (n_tx_bufs > 0)
- {
- to_tx[0] = from_tx_seg[0];
- to_tx += 1;
- from_tx_seg += 1;
- n_left_to_tx -= 1;
- n_tx_bufs -= 1;
- n_packets += 1;
- }
- }
- n_bytes += n_tx_bytes;
- if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
- {
-
- vlib_increment_combined_counter
- (im->combined_sw_if_counters +
- VNET_INTERFACE_COUNTER_TX, thread_index, tx_swif0,
- _vec_len (ptd->split_buffers), n_tx_bytes);
- }
- /* The buffers were enqueued. Reset the length */
- _vec_len (ptd->split_buffers) = 0;
- /* Free the now segmented buffer */
- vlib_buffer_free_one (vm, bi0);
- b += 1;
- continue;
- }
- }