misc: do not capture tx packets twice 58/33158/4
authorBenoît Ganne <bganne@cisco.com>
Thu, 15 Jul 2021 17:21:31 +0000 (19:21 +0200)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Tue, 10 Aug 2021 15:03:13 +0000 (15:03 +0000)
When a packet goes through interface-output, whether it should be
captured or not will be evaluated twice: in interface-output and in
interface-output-template (<interface_name>-out) node.
interface-output should only capture packets if there is an interface
filter, otherwise it should defer evaluation to
interface-output-template.

Type: fix

Change-Id: Ia720c5d184a236335e1d7d44d8c04caf87af5630
Signed-off-by: Benoît Ganne <bganne@cisco.com>
src/vnet/interface_output.c

index 0de2714..cc4997a 100644 (file)
@@ -285,25 +285,33 @@ vnet_interface_output_node_inline (vlib_main_t *vm, u32 sw_if_index,
   return n_bytes;
 }
 
-static_always_inline void vnet_interface_pcap_tx_trace
-  (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
-   int sw_if_index_from_buffer)
+static_always_inline void
+vnet_interface_pcap_tx_trace (vlib_main_t *vm, vlib_node_runtime_t *node,
+                             vlib_frame_t *frame, int in_interface_ouput)
 {
   vnet_main_t *vnm = vnet_get_main ();
   u32 n_left_from, *from;
-  u32 sw_if_index;
+  u32 sw_if_index = ~0, hw_if_index = ~0;
   vnet_pcap_t *pp = &vnm->pcap;
 
   if (PREDICT_TRUE (pp->pcap_tx_enable == 0))
     return;
 
-  if (sw_if_index_from_buffer == 0)
+  if (in_interface_ouput)
+    {
+      /* interface-output is called right before interface-output-template.
+       * We only want to capture packets here if there is a per-interface
+       * filter, in case it matches the sub-interface sw_if_index.
+       * If there is no per-interface filter configured, let the
+       * interface-output-template node deal with it */
+      if (pp->pcap_sw_if_index == 0)
+       return;
+    }
+  else
     {
       vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
       sw_if_index = rt->sw_if_index;
     }
-  else
-    sw_if_index = ~0;
 
   n_left_from = frame->n_vectors;
   from = vlib_frame_vector_args (frame);
@@ -315,8 +323,19 @@ static_always_inline void vnet_interface_pcap_tx_trace
       from++;
       n_left_from--;
 
-      if (sw_if_index_from_buffer)
-       sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
+      if (in_interface_ouput)
+       {
+         const u32 sii = vnet_buffer (b0)->sw_if_index[VLIB_TX];
+         if (PREDICT_FALSE (sii != sw_if_index))
+           {
+             const vnet_hw_interface_t *hi =
+               vnet_get_sup_hw_interface (vnm, sii);
+             hw_if_index = hi->sw_if_index;
+             sw_if_index = sii;
+           }
+         if (hw_if_index == sw_if_index)
+           continue; /* defer to interface-output-template */
+       }
 
       if (vnet_is_packet_pcaped (pp, b0, sw_if_index))
        pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
@@ -420,8 +439,7 @@ VLIB_NODE_FN (vnet_interface_output_node)
       /* buffer stride */ 1, n_buffers, VNET_INTERFACE_OUTPUT_NEXT_DROP,
       node->node_index, VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DELETED);
 
-  vnet_interface_pcap_tx_trace (vm, node, frame,
-                               0 /* sw_if_index_from_buffer */ );
+  vnet_interface_pcap_tx_trace (vm, node, frame, 0 /* in_interface_ouput */);
 
   vlib_get_buffers (vm, from, bufs, n_buffers);
 
@@ -504,8 +522,7 @@ VLIB_NODE_FN (vnet_per_buffer_interface_output_node) (vlib_main_t * vm,
   u32 n_left_to_next, *from, *to_next;
   u32 n_left_from, next_index;
 
-  vnet_interface_pcap_tx_trace (vm, node, frame,
-                               1 /* sw_if_index_from_buffer */ );
+  vnet_interface_pcap_tx_trace (vm, node, frame, 1 /* in_interface_ouput */);
 
   n_left_from = frame->n_vectors;