vlib: fix trace number accounting

When using classifier to filter traces, not all packets will be traced.
In that case, we should only count traced packets.

Type: fix

Change-Id: I87d1e217b580ebff8c6ade7860eb43950420ae78
Signed-off-by: Benoît Ganne <bganne@cisco.com>
diff --git a/src/plugins/af_xdp/input.c b/src/plugins/af_xdp/input.c
index c164c25..2cf121f 100644
--- a/src/plugins/af_xdp/input.c
+++ b/src/plugins/af_xdp/input.c
@@ -46,23 +46,23 @@
 			   u32 n_left, const u32 * bi, u32 next_index,
 			   u32 hw_if_index)
 {
-  u32 n_trace;
+  u32 n_trace = vlib_get_trace_count (vm, node);
 
-  if (PREDICT_TRUE (0 == (n_trace = vlib_get_trace_count (vm, node))))
+  if (PREDICT_TRUE (0 == n_trace))
     return;
 
   while (n_trace && n_left)
     {
-      vlib_buffer_t *b;
-      af_xdp_input_trace_t *tr;
-      b = vlib_get_buffer (vm, bi[0]);
-      vlib_trace_buffer (vm, node, next_index, b,
-			 /* follow_chain */ 0);
-      tr = vlib_add_trace (vm, node, b, sizeof (*tr));
-      tr->next_index = next_index;
-      tr->hw_if_index = hw_if_index;
-
-      n_trace--;
+      vlib_buffer_t *b = vlib_get_buffer (vm, bi[0]);
+      if (PREDICT_TRUE
+	  (vlib_trace_buffer (vm, node, next_index, b, /* follow_chain */ 0)))
+	{
+	  af_xdp_input_trace_t *tr =
+	    vlib_add_trace (vm, node, b, sizeof (*tr));
+	  tr->next_index = next_index;
+	  tr->hw_if_index = hw_if_index;
+	  n_trace--;
+	}
       n_left--;
       bi++;
     }
diff --git a/src/plugins/avf/input.c b/src/plugins/avf/input.c
index 9d677ab..4e4f116 100644
--- a/src/plugins/avf/input.c
+++ b/src/plugins/avf/input.c
@@ -383,20 +383,24 @@
 
       while (n_trace && n_left)
 	{
-	  vlib_buffer_t *b;
-	  avf_input_trace_t *tr;
-	  b = vlib_get_buffer (vm, bi[0]);
-	  vlib_trace_buffer (vm, node, next_index, b, /* follow_chain */ 0);
-	  tr = vlib_add_trace (vm, node, b, sizeof (*tr));
-	  tr->next_index = next_index;
-	  tr->qid = qid;
-	  tr->hw_if_index = ad->hw_if_index;
-	  tr->qw1s[0] = ptd->qw1s[i];
-	  for (j = 1; j < AVF_RX_MAX_DESC_IN_CHAIN; j++)
-	    tr->qw1s[j] = ptd->tails[i].qw1s[j - 1];
+	  vlib_buffer_t *b = vlib_get_buffer (vm, bi[0]);
+	  if (PREDICT_TRUE
+	      (vlib_trace_buffer
+	       (vm, node, next_index, b, /* follow_chain */ 0)))
+	    {
+	      avf_input_trace_t *tr =
+		vlib_add_trace (vm, node, b, sizeof (*tr));
+	      tr->next_index = next_index;
+	      tr->qid = qid;
+	      tr->hw_if_index = ad->hw_if_index;
+	      tr->qw1s[0] = ptd->qw1s[i];
+	      for (j = 1; j < AVF_RX_MAX_DESC_IN_CHAIN; j++)
+		tr->qw1s[j] = ptd->tails[i].qw1s[j - 1];
+
+	      n_trace--;
+	    }
 
 	  /* next */
-	  n_trace--;
 	  n_left--;
 	  bi++;
 	  i++;
diff --git a/src/plugins/dpdk/device/node.c b/src/plugins/dpdk/device/node.c
index 256c399..e7d836f 100644
--- a/src/plugins/dpdk/device/node.c
+++ b/src/plugins/dpdk/device/node.c
@@ -417,21 +417,28 @@
 	  b0 = vlib_get_buffer (vm, buffers[0]);
 	  if (single_next == 0)
 	    next_index = next[0];
-	  vlib_trace_buffer (vm, node, next_index, b0, /* follow_chain */ 0);
 
-	  dpdk_rx_trace_t *t0 = vlib_add_trace (vm, node, b0, sizeof t0[0]);
-	  t0->queue_index = queue_id;
-	  t0->device_index = xd->device_index;
-	  t0->buffer_index = vlib_get_buffer_index (vm, b0);
+	  if (PREDICT_TRUE
+	      (vlib_trace_buffer
+	       (vm, node, next_index, b0, /* follow_chain */ 0)))
+	    {
 
-	  clib_memcpy_fast (&t0->mb, mb[0], sizeof t0->mb);
-	  clib_memcpy_fast (&t0->buffer, b0,
-			    sizeof b0[0] - sizeof b0->pre_data);
-	  clib_memcpy_fast (t0->buffer.pre_data, b0->data,
-			    sizeof t0->buffer.pre_data);
-	  clib_memcpy_fast (&t0->data, mb[0]->buf_addr + mb[0]->data_off,
-			    sizeof t0->data);
-	  n_trace--;
+	      dpdk_rx_trace_t *t0 =
+		vlib_add_trace (vm, node, b0, sizeof t0[0]);
+	      t0->queue_index = queue_id;
+	      t0->device_index = xd->device_index;
+	      t0->buffer_index = vlib_get_buffer_index (vm, b0);
+
+	      clib_memcpy_fast (&t0->mb, mb[0], sizeof t0->mb);
+	      clib_memcpy_fast (&t0->buffer, b0,
+				sizeof b0[0] - sizeof b0->pre_data);
+	      clib_memcpy_fast (t0->buffer.pre_data, b0->data,
+				sizeof t0->buffer.pre_data);
+	      clib_memcpy_fast (&t0->data, mb[0]->buf_addr + mb[0]->data_off,
+				sizeof t0->data);
+	      n_trace--;
+	    }
+
 	  n_left--;
 	  buffers++;
 	  mb++;
diff --git a/src/plugins/dpdk/ipsec/crypto_node.c b/src/plugins/dpdk/ipsec/crypto_node.c
index 76e57a3..893848c 100644
--- a/src/plugins/dpdk/ipsec/crypto_node.c
+++ b/src/plugins/dpdk/ipsec/crypto_node.c
@@ -106,14 +106,16 @@
 
 	  b0 = vlib_get_buffer (vm, bi);
 
-	  vlib_trace_buffer (vm, node, next, b0, /* follow_chain */ 0);
+	  if (PREDICT_TRUE
+	      (vlib_trace_buffer (vm, node, next, b0, /* follow_chain */ 0)))
+	    {
+	      dpdk_crypto_input_trace_t *tr =
+		vlib_add_trace (vm, node, b0, sizeof (*tr));
+	      tr->dev_id = dev_id;
+	      tr->next_index = next;
+	      n_trace--;
+	    }
 
-	  dpdk_crypto_input_trace_t *tr =
-	    vlib_add_trace (vm, node, b0, sizeof (*tr));
-	  tr->dev_id = dev_id;
-	  tr->next_index = next;
-
-	  n_trace--;
 	  n_left--;
 	  nexts++;
 	  bis++;
diff --git a/src/plugins/memif/node.c b/src/plugins/memif/node.c
index 82a7cbc..506d88a 100644
--- a/src/plugins/memif/node.c
+++ b/src/plugins/memif/node.c
@@ -92,10 +92,10 @@
 {
   VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
 
-  if (PREDICT_TRUE (b != 0))
+  if (PREDICT_TRUE
+      (b != 0 && vlib_trace_buffer (vm, node, next, b, /* follow_chain */ 0)))
     {
       memif_input_trace_t *tr;
-      vlib_trace_buffer (vm, node, next, b, /* follow_chain */ 0);
       vlib_set_trace_count (vm, node, --(*n_tracep));
       tr = vlib_add_trace (vm, node, b, sizeof (*tr));
       tr->next_index = next;
@@ -484,14 +484,17 @@
 	  if (mode != MEMIF_INTERFACE_MODE_ETHERNET)
 	    ni = next[0];
 	  b = vlib_get_buffer (vm, bi[0]);
-	  vlib_trace_buffer (vm, node, ni, b, /* follow_chain */ 0);
-	  tr = vlib_add_trace (vm, node, b, sizeof (*tr));
-	  tr->next_index = ni;
-	  tr->hw_if_index = mif->hw_if_index;
-	  tr->ring = qid;
+	  if (PREDICT_TRUE
+	      (vlib_trace_buffer (vm, node, ni, b, /* follow_chain */ 0)))
+	    {
+	      tr = vlib_add_trace (vm, node, b, sizeof (*tr));
+	      tr->next_index = ni;
+	      tr->hw_if_index = mif->hw_if_index;
+	      tr->ring = qid;
+	      n_trace--;
+	    }
 
 	  /* next */
-	  n_trace--;
 	  n_left--;
 	  bi++;
 	  next++;
diff --git a/src/plugins/rdma/input.c b/src/plugins/rdma/input.c
index 1d267ad..52e921d 100644
--- a/src/plugins/rdma/input.c
+++ b/src/plugins/rdma/input.c
@@ -225,30 +225,27 @@
 			 const u32 * bi, u32 next_index, u16 * cqe_flags,
 			 int is_mlx5dv)
 {
-  u32 n_trace, i;
+  u32 n_trace = vlib_get_trace_count (vm, node);
 
-  if (PREDICT_TRUE (0 == (n_trace = vlib_get_trace_count (vm, node))))
+  if (PREDICT_TRUE (0 == n_trace))
     return;
 
-  i = 0;
   while (n_trace && n_left)
     {
-      vlib_buffer_t *b;
-      rdma_input_trace_t *tr;
-      b = vlib_get_buffer (vm, bi[0]);
-      vlib_trace_buffer (vm, node, next_index, b,
-			 /* follow_chain */ 0);
-      tr = vlib_add_trace (vm, node, b, sizeof (*tr));
-      tr->next_index = next_index;
-      tr->hw_if_index = rd->hw_if_index;
-      tr->cqe_flags = is_mlx5dv ? clib_net_to_host_u16 (cqe_flags[0]) : 0;
-
+      vlib_buffer_t *b = vlib_get_buffer (vm, bi[0]);
+      if (PREDICT_TRUE
+	  (vlib_trace_buffer (vm, node, next_index, b, /* follow_chain */ 0)))
+	{
+	  rdma_input_trace_t *tr = vlib_add_trace (vm, node, b, sizeof (*tr));
+	  tr->next_index = next_index;
+	  tr->hw_if_index = rd->hw_if_index;
+	  tr->cqe_flags = is_mlx5dv ? clib_net_to_host_u16 (cqe_flags[0]) : 0;
+	  n_trace--;
+	}
       /* next */
-      n_trace--;
       n_left--;
       cqe_flags++;
       bi++;
-      i++;
     }
   vlib_set_trace_count (vm, node, n_trace);
 }
diff --git a/src/plugins/vmxnet3/input.c b/src/plugins/vmxnet3/input.c
index f182409..bed4c1e 100644
--- a/src/plugins/vmxnet3/input.c
+++ b/src/plugins/vmxnet3/input.c
@@ -418,17 +418,18 @@
       next = nexts;
       while (n_trace && n_left)
 	{
-	  vlib_buffer_t *b;
-	  vmxnet3_input_trace_t *tr;
-
-	  b = vlib_get_buffer (vm, bi[0]);
-	  vlib_trace_buffer (vm, node, next[0], b, /* follow_chain */ 0);
-	  tr = vlib_add_trace (vm, node, b, sizeof (*tr));
-	  tr->next_index = next[0];
-	  tr->hw_if_index = vd->hw_if_index;
-	  tr->buffer = *b;
-
-	  n_trace--;
+	  vlib_buffer_t *b = vlib_get_buffer (vm, bi[0]);
+	  if (PREDICT_TRUE
+	      (vlib_trace_buffer
+	       (vm, node, next[0], b, /* follow_chain */ 0)))
+	    {
+	      vmxnet3_input_trace_t *tr =
+		vlib_add_trace (vm, node, b, sizeof (*tr));
+	      tr->next_index = next[0];
+	      tr->hw_if_index = vd->hw_if_index;
+	      tr->buffer = *b;
+	      n_trace--;
+	    }
 	  n_left--;
 	  bi++;
 	  next++;
diff --git a/src/vlib/handoff_trace.c b/src/vlib/handoff_trace.c
index d268b56..964c095 100644
--- a/src/vlib/handoff_trace.c
+++ b/src/vlib/handoff_trace.c
@@ -96,7 +96,7 @@
 };
 /* *INDENT-ON* */
 
-void
+int
 vlib_add_handoff_trace (vlib_main_t * vm, vlib_buffer_t * b)
 {
   u32 prev_thread = vlib_buffer_get_trace_thread (b);
@@ -105,13 +105,15 @@
   vlib_node_runtime_t *node
     = vlib_node_get_runtime (vm, handoff_trace_node.index);
 
-  vlib_trace_buffer (vm, node, 0 /* fake next frame index */ ,
-		     b, 1 /* folllow chain */ );
+  if (PREDICT_FALSE
+      (!vlib_trace_buffer
+       (vm, node, 0 /* fake next frame index */ , b, 1 /* follow chain */ )))
+    return 0;
 
   t = vlib_add_trace (vm, node, b, sizeof (*t));
-
   t->prev_thread = prev_thread;
   t->prev_trace_index = prev_trace_index;
+  return 1;
 }
 
 
diff --git a/src/vlib/trace_funcs.h b/src/vlib/trace_funcs.h
index fba55bf..8dd5310 100644
--- a/src/vlib/trace_funcs.h
+++ b/src/vlib/trace_funcs.h
@@ -49,7 +49,7 @@
 			       vlib_buffer_get_trace_index (b)));
 }
 
-void vlib_add_handoff_trace (vlib_main_t * vm, vlib_buffer_t * b);
+int vlib_add_handoff_trace (vlib_main_t * vm, vlib_buffer_t * b);
 
 always_inline void *
 vlib_add_trace_inline (vlib_main_t * vm,
@@ -80,7 +80,8 @@
 
   /* Are we trying to trace a handoff case? */
   if (PREDICT_FALSE (vlib_buffer_get_trace_thread (b) != vm->thread_index))
-    vlib_add_handoff_trace (vm, b);
+    if (PREDICT_FALSE (!vlib_add_handoff_trace (vm, b)))
+      return vnet_trace_placeholder;
 
   vlib_validate_trace (tm, b);
 
@@ -131,8 +132,13 @@
 			   u32 classify_table_index, int func);
 
 
-/* Mark buffer as traced and allocate trace buffer. */
-always_inline void
+/*
+ * Mark buffer as traced and allocate trace buffer.
+ * return 1 if the buffer is successfully traced, 0 if not
+ * A buffer might not be traced if tracing is off or if the packet did not
+ * match the filter.
+ */
+always_inline __clib_warn_unused_result int
 vlib_trace_buffer (vlib_main_t * vm,
 		   vlib_node_runtime_t * r,
 		   u32 next_index, vlib_buffer_t * b, int follow_chain)
@@ -141,7 +147,7 @@
   vlib_trace_header_t **h;
 
   if (PREDICT_FALSE (tm->trace_enable == 0))
-    return;
+    return 0;
 
   /* Classifier filter in use? */
   if (PREDICT_FALSE (vlib_global_main.trace_filter.trace_filter_enable))
@@ -150,7 +156,7 @@
       if (vnet_is_packet_traced
 	  (b, vlib_global_main.trace_filter.trace_classify_table_index,
 	   0 /* full classify */ ) != 1)
-	return;
+	return 0;
     }
 
   /*
@@ -178,6 +184,8 @@
 	(vm->thread_index, h - tm->trace_buffer_pool);
     }
   while (follow_chain && (b = vlib_get_next_buffer (vm, b)));
+
+  return 1;
 }
 
 always_inline void
diff --git a/src/vnet/bonding/device.c b/src/vnet/bonding/device.c
index bc18586..7ce5ad8 100644
--- a/src/vnet/bonding/device.c
+++ b/src/vnet/bonding/device.c
@@ -651,25 +651,28 @@
 
   while (n_trace > 0 && n_left > 0)
     {
-      bond_packet_trace_t *t0;
-      ethernet_header_t *eth;
-      u32 next0 = 0;
+      if (PREDICT_TRUE
+	  (vlib_trace_buffer (vm, node, 0, b[0], 0 /* follow_chain */ )))
+	{
+	  bond_packet_trace_t *t0;
+	  ethernet_header_t *eth;
 
-      vlib_trace_buffer (vm, node, next0, b[0], 0 /* follow_chain */ );
-      vlib_set_trace_count (vm, node, --n_trace);
-      t0 = vlib_add_trace (vm, node, b[0], sizeof (*t0));
-      eth = vlib_buffer_get_current (b[0]);
-      t0->ethernet = *eth;
-      t0->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
-      if (!h)
-	{
-	  t0->bond_sw_if_index = *vec_elt_at_index (bif->active_members, 0);
-	}
-      else
-	{
-	  t0->bond_sw_if_index =
-	    *vec_elt_at_index (bif->active_members, h[0]);
-	  h++;
+	  vlib_set_trace_count (vm, node, --n_trace);
+	  t0 = vlib_add_trace (vm, node, b[0], sizeof (*t0));
+	  eth = vlib_buffer_get_current (b[0]);
+	  t0->ethernet = *eth;
+	  t0->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
+	  if (!h)
+	    {
+	      t0->bond_sw_if_index =
+		*vec_elt_at_index (bif->active_members, 0);
+	    }
+	  else
+	    {
+	      t0->bond_sw_if_index =
+		*vec_elt_at_index (bif->active_members, h[0]);
+	      h++;
+	    }
 	}
       b++;
       n_left--;
diff --git a/src/vnet/devices/af_packet/node.c b/src/vnet/devices/af_packet/node.c
index 196c088..61d4ce2 100644
--- a/src/vnet/devices/af_packet/node.c
+++ b/src/vnet/devices/af_packet/node.c
@@ -310,11 +310,11 @@
 
 	  /* trace */
 	  VLIB_BUFFER_TRACE_TRAJECTORY_INIT (first_b0);
-	  if (PREDICT_FALSE (n_trace > 0))
+	  if (PREDICT_FALSE
+	      (n_trace > 0 && vlib_trace_buffer (vm, node, next0, first_b0,
+						 /* follow_chain */ 0)))
 	    {
 	      af_packet_input_trace_t *tr;
-	      vlib_trace_buffer (vm, node, next0, first_b0,	/* follow_chain */
-				 0);
 	      vlib_set_trace_count (vm, node, --n_trace);
 	      tr = vlib_add_trace (vm, node, first_b0, sizeof (*tr));
 	      tr->next_index = next0;
diff --git a/src/vnet/devices/virtio/node.c b/src/vnet/devices/virtio/node.c
index 94bf097..91e788e 100644
--- a/src/vnet/devices/virtio/node.c
+++ b/src/vnet/devices/virtio/node.c
@@ -388,11 +388,10 @@
 	  /* trace */
 	  VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
 
-	  if (PREDICT_FALSE (n_trace > 0))
+	  if (PREDICT_FALSE (n_trace > 0 && vlib_trace_buffer (vm, node, next0, b0,	/* follow_chain */
+							       1)))
 	    {
 	      virtio_input_trace_t *tr;
-	      vlib_trace_buffer (vm, node, next0, b0,
-				 /* follow_chain */ 1);
 	      vlib_set_trace_count (vm, node, --n_trace);
 	      tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
 	      tr->next_index = next0;
diff --git a/src/vnet/devices/virtio/vhost_user_input.c b/src/vnet/devices/virtio/vhost_user_input.c
index da4937b..53230a6 100644
--- a/src/vnet/devices/virtio/vhost_user_input.c
+++ b/src/vnet/devices/virtio/vhost_user_input.c
@@ -540,10 +540,10 @@
       b_head->total_length_not_including_first_buffer = 0;
       b_head->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
 
-      if (PREDICT_FALSE (n_trace))
+      if (PREDICT_FALSE
+	  (n_trace > 0 && vlib_trace_buffer (vm, node, next_index, b_head,
+					     /* follow_chain */ 0)))
 	{
-	  vlib_trace_buffer (vm, node, next_index, b_head,
-			     /* follow_chain */ 0);
 	  vhost_trace_t *t0 =
 	    vlib_add_trace (vm, node, b_head, sizeof (t0[0]));
 	  vhost_user_rx_trace (t0, vui, qid, b_head, txvq, last_avail_idx);
@@ -1362,17 +1362,19 @@
       b = cpu->rx_buffers_pdesc;
       while (n_trace && left)
 	{
-	  vhost_trace_t *t0;
-
-	  vlib_trace_buffer (vm, node, next_index, b[0],
-			     /* follow_chain */ 0);
-	  t0 = vlib_add_trace (vm, node, b[0], sizeof (t0[0]));
-	  b++;
-	  vhost_user_rx_trace_packed (t0, vui, qid, txvq, last_used_idx);
-	  last_used_idx = (last_used_idx + 1) & mask;
-	  n_trace--;
+	  if (PREDICT_TRUE
+	      (vlib_trace_buffer
+	       (vm, node, next_index, b[0], /* follow_chain */ 0)))
+	    {
+	      vhost_trace_t *t0;
+	      t0 = vlib_add_trace (vm, node, b[0], sizeof (t0[0]));
+	      vhost_user_rx_trace_packed (t0, vui, qid, txvq, last_used_idx);
+	      last_used_idx = (last_used_idx + 1) & mask;
+	      n_trace--;
+	      vlib_set_trace_count (vm, node, n_trace);
+	    }
 	  left--;
-	  vlib_set_trace_count (vm, node, n_trace);
+	  b++;
 	}
     }
 
diff --git a/src/vnet/ethernet/p2p_ethernet_input.c b/src/vnet/ethernet/p2p_ethernet_input.c
index 7e5f7ca..3e9589e 100644
--- a/src/vnet/ethernet/p2p_ethernet_input.c
+++ b/src/vnet/ethernet/p2p_ethernet_input.c
@@ -119,11 +119,12 @@
 	      vnet_buffer (b0)->sw_if_index[VLIB_RX] = rx0;
 	      n_p2p_ethernet_packets += 1;
 
-	      if (PREDICT_FALSE (n_trace > 0))
+	      if (PREDICT_FALSE
+		  (n_trace > 0
+		   && vlib_trace_buffer (vm, node, next_index, b0,
+					 1 /* follow_chain */ )))
 		{
 		  p2p_ethernet_trace_t *t0;
-		  vlib_trace_buffer (vm, node, next_index, b0,
-				     1 /* follow_chain */ );
 		  vlib_set_trace_count (vm, node, --n_trace);
 		  t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
 		  t0->sw_if_index = sw_if_index0;
@@ -140,11 +141,12 @@
 	      vnet_buffer (b1)->sw_if_index[VLIB_RX] = rx1;
 	      n_p2p_ethernet_packets += 1;
 
-	      if (PREDICT_FALSE (n_trace > 0))
+	      if (PREDICT_FALSE
+		  (n_trace > 0
+		   && vlib_trace_buffer (vm, node, next_index, b1,
+					 1 /* follow_chain */ )))
 		{
 		  p2p_ethernet_trace_t *t1;
-		  vlib_trace_buffer (vm, node, next_index, b1,
-				     1 /* follow_chain */ );
 		  vlib_set_trace_count (vm, node, --n_trace);
 		  t1 = vlib_add_trace (vm, node, b1, sizeof (*t1));
 		  t1->sw_if_index = sw_if_index1;
@@ -195,11 +197,12 @@
 	      vnet_buffer (b0)->sw_if_index[VLIB_RX] = rx0;
 	      n_p2p_ethernet_packets += 1;
 
-	      if (PREDICT_FALSE (n_trace > 0))
+	      if (PREDICT_FALSE
+		  (n_trace > 0
+		   && vlib_trace_buffer (vm, node, next_index, b0,
+					 1 /* follow_chain */ )))
 		{
 		  p2p_ethernet_trace_t *t0;
-		  vlib_trace_buffer (vm, node, next_index, b0,
-				     1 /* follow_chain */ );
 		  vlib_set_trace_count (vm, node, --n_trace);
 		  t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
 		  t0->sw_if_index = sw_if_index0;
@@ -228,6 +231,7 @@
 
   vlib_node_increment_counter (vm, p2p_ethernet_input_node.index,
 			       P2PE_ERROR_HITS, n_p2p_ethernet_packets);
+
   return frame->n_vectors;
 }
 
diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c
index 52c07ac..65bc4a4 100644
--- a/src/vnet/interface_output.c
+++ b/src/vnet/interface_output.c
@@ -800,19 +800,21 @@
 	  node->flags |= VLIB_NODE_FLAG_TRACE;
 	  while (n_trace && n_left)
 	    {
-	      vlib_trace_buffer (vm, node, 0 /* next_index */ ,
-				 b[0], 0 /* follow chain */ );
-	      /*
-	       * Here we have a wireshark dissector problem.
-	       * Packets may be well-formed, or not. We
-	       * must not blow chunks in any case.
-	       *
-	       * Try to produce trace records which will help
-	       * folks understand what's going on.
-	       */
-	      drop_catchup_trace (vm, node, b[0]);
-
-	      n_trace--;
+	      if (PREDICT_TRUE
+		  (vlib_trace_buffer (vm, node, 0 /* next_index */ , b[0],
+				      0 /* follow chain */ )))
+		{
+		  /*
+		   * Here we have a wireshark dissector problem.
+		   * Packets may be well-formed, or not. We
+		   * must not blow chunks in any case.
+		   *
+		   * Try to produce trace records which will help
+		   * folks understand what's going on.
+		   */
+		  drop_catchup_trace (vm, node, b[0]);
+		  n_trace--;
+		}
 	      n_left--;
 	      b++;
 	    }
diff --git a/src/vnet/ip/punt_node.c b/src/vnet/ip/punt_node.c
index 23c4cc4..90953e6 100644
--- a/src/vnet/ip/punt_node.c
+++ b/src/vnet/ip/punt_node.c
@@ -573,10 +573,11 @@
       goto error;
     }
 
-  if (PREDICT_FALSE (n_trace > 0))
+  if (PREDICT_FALSE
+      (n_trace > 0
+       && vlib_trace_buffer (vm, node, next_index, b, 1 /* follow_chain */ )))
     {
       punt_trace_t *t;
-      vlib_trace_buffer (vm, node, next_index, b, 1 /* follow_chain */ );
       vlib_set_trace_count (vm, node, --n_trace);
       t = vlib_add_trace (vm, node, b, sizeof (*t));
       t->sw_if_index = packetdesc.sw_if_index;
@@ -590,6 +591,7 @@
   vlib_validate_buffer_enqueue_x1 (vm, node, next, to_next, n_left_to_next,
 				   bi, next_index);
   vlib_put_next_frame (vm, node, next, n_left_to_next);
+
   return 1;
 
 error:
diff --git a/src/vnet/pg/input.c b/src/vnet/pg/input.c
index c8f3d9f..d5cf929 100644
--- a/src/vnet/pg/input.c
+++ b/src/vnet/pg/input.c
@@ -1454,15 +1454,16 @@
   return s;
 }
 
-static void
+static int
 pg_input_trace (pg_main_t * pg,
 		vlib_node_runtime_t * node, u32 stream_index, u32 next_index,
-		u32 * buffers, u32 n_buffers)
+		u32 * buffers, const u32 n_buffers, const u32 n_trace)
 {
   vlib_main_t *vm = vlib_get_main ();
   u32 *b, n_left;
+  u32 n_trace0 = 0, n_trace1 = 0;
 
-  n_left = n_buffers;
+  n_left = clib_min (n_buffers, n_trace);
   b = buffers;
 
   while (n_left >= 2)
@@ -1479,8 +1480,10 @@
       b0 = vlib_get_buffer (vm, bi0);
       b1 = vlib_get_buffer (vm, bi1);
 
-      vlib_trace_buffer (vm, node, next_index, b0, /* follow_chain */ 1);
-      vlib_trace_buffer (vm, node, next_index, b1, /* follow_chain */ 1);
+      n_trace0 +=
+	vlib_trace_buffer (vm, node, next_index, b0, /* follow_chain */ 1);
+      n_trace1 +=
+	vlib_trace_buffer (vm, node, next_index, b1, /* follow_chain */ 1);
 
       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
       t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
@@ -1517,7 +1520,8 @@
 
       b0 = vlib_get_buffer (vm, bi0);
 
-      vlib_trace_buffer (vm, node, next_index, b0, /* follow_chain */ 1);
+      n_trace0 +=
+	vlib_trace_buffer (vm, node, next_index, b0, /* follow_chain */ 1);
       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
 
       t0->stream_index = stream_index;
@@ -1528,6 +1532,8 @@
       clib_memcpy_fast (t0->buffer.pre_data, b0->data,
 			sizeof (t0->buffer.pre_data));
     }
+
+  return n_trace - n_trace0 - n_trace1;
 }
 
 static_always_inline void
@@ -1714,11 +1720,12 @@
 	}
 
       n_trace = vlib_get_trace_count (vm, node);
-      if (n_trace > 0)
+      if (PREDICT_FALSE (n_trace > 0))
 	{
-	  u32 n = clib_min (n_trace, n_this_frame);
-	  pg_input_trace (pg, node, s - pg->streams, next_index, to_next, n);
-	  vlib_set_trace_count (vm, node, n_trace - n);
+	  n_trace =
+	    pg_input_trace (pg, node, s - pg->streams, next_index, to_next,
+			    n_this_frame, n_trace);
+	  vlib_set_trace_count (vm, node, n_trace);
 	}
       n_packets_to_generate -= n_this_frame;
       n_packets_generated += n_this_frame;
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index ec2f936..8a350d4 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -569,19 +569,23 @@
 			u32 next_index, u32 * to_next, u16 n_segs,
 			session_t * s, u32 n_trace)
 {
-  session_queue_trace_t *t;
-  vlib_buffer_t *b;
-  int i;
-
-  for (i = 0; i < clib_min (n_trace, n_segs); i++)
+  while (n_trace && n_segs)
     {
-      b = vlib_get_buffer (vm, to_next[i]);
-      vlib_trace_buffer (vm, node, next_index, b, 1 /* follow_chain */ );
-      t = vlib_add_trace (vm, node, b, sizeof (*t));
-      t->session_index = s->session_index;
-      t->server_thread_index = s->thread_index;
+      vlib_buffer_t *b = vlib_get_buffer (vm, to_next[0]);
+      if (PREDICT_TRUE
+	  (vlib_trace_buffer
+	   (vm, node, next_index, b, 1 /* follow_chain */ )))
+	{
+	  session_queue_trace_t *t =
+	    vlib_add_trace (vm, node, b, sizeof (*t));
+	  t->session_index = s->session_index;
+	  t->server_thread_index = s->thread_index;
+	  n_trace--;
+	}
+      to_next++;
+      n_segs--;
     }
-  vlib_set_trace_count (vm, node, n_trace - i);
+  vlib_set_trace_count (vm, node, n_trace);
 }
 
 always_inline void
diff --git a/src/vnet/unix/tuntap.c b/src/vnet/unix/tuntap.c
index 72c4f73..6834ee8 100644
--- a/src/vnet/unix/tuntap.c
+++ b/src/vnet/unix/tuntap.c
@@ -378,11 +378,9 @@
 
     vlib_set_next_frame_buffer (vm, node, next_index, bi);
 
-    if (n_trace > 0)
-      {
-	vlib_trace_buffer (vm, node, next_index, b, /* follow_chain */ 1);
-	vlib_set_trace_count (vm, node, n_trace - 1);
-      }
+    if (PREDICT_FALSE (n_trace > 0 && vlib_trace_buffer (vm, node, next_index, b,	/* follow_chain */
+							 1)))
+      vlib_set_trace_count (vm, node, n_trace - 1);
   }
 
   return 1;