misc: add vnet classify filter set support
[vpp.git] / src / vnet / ethernet / node.c
index 286ec3c..63ce0ce 100755 (executable)
@@ -44,6 +44,7 @@
 #include <vnet/devices/pipe/pipe.h>
 #include <vppinfra/sparse_vec.h>
 #include <vnet/l2/l2_bvi.h>
+#include <vnet/classify/trace_classify.h>
 
 #define foreach_ethernet_input_next            \
   _ (PUNT, "error-punt")                       \
@@ -607,6 +608,68 @@ eth_input_tag_lookup (vlib_main_t * vm, vnet_main_t * vnm,
   l->n_bytes += vlib_buffer_length_in_chain (vm, b);
 }
 
+static_always_inline void
+eth_input_process_frame_dmac_check (vnet_hw_interface_t * hi,
+                                   u64 * dmacs, u8 * dmacs_bad,
+                                   u32 n_packets)
+{
+  u64 mask = clib_net_to_host_u64 (0xFFFFFFFFFFFF0000);
+  u64 igbit = clib_net_to_host_u64 (0x0100000000000000);
+  u64 hwaddr = (*(u64 *) hi->hw_address) & mask;
+  u64 *dmac = dmacs;
+  u8 *dmac_bad = dmacs_bad;
+
+  i32 n_left = n_packets;
+
+#ifdef CLIB_HAVE_VEC256
+  u64x4 igbit4 = u64x4_splat (igbit);
+  u64x4 mask4 = u64x4_splat (mask);
+  u64x4 hwaddr4 = u64x4_splat (hwaddr);
+  while (n_left > 0)
+    {
+      u64x4 r0, r1;
+      r0 = u64x4_load_unaligned (dmac + 0) & mask4;
+      r1 = u64x4_load_unaligned (dmac + 4) & mask4;
+
+      r0 = (r0 != hwaddr4) & ((r0 & igbit4) == 0);
+      r1 = (r1 != hwaddr4) & ((r1 & igbit4) == 0);
+
+      *(u32 *) (dmac_bad + 0) = u8x32_msb_mask ((u8x32) (r0));
+      *(u32 *) (dmac_bad + 4) = u8x32_msb_mask ((u8x32) (r1));
+
+      /* next */
+      dmac += 8;
+      dmac_bad += 8;
+      n_left -= 8;
+    }
+#else
+  while (n_left > 0)
+    {
+      u64 r0, r1, r2, r3;
+
+      r0 = dmac[0] & mask;
+      r1 = dmac[1] & mask;
+      r2 = dmac[2] & mask;
+      r3 = dmac[3] & mask;
+
+      r0 = (r0 != hwaddr) && ((r0 & igbit) == 0);
+      r1 = (r1 != hwaddr) && ((r1 & igbit) == 0);
+      r2 = (r2 != hwaddr) && ((r2 & igbit) == 0);
+      r3 = (r3 != hwaddr) && ((r3 & igbit) == 0);
+
+      dmac_bad[0] = r0;
+      dmac_bad[1] = r1;
+      dmac_bad[2] = r2;
+      dmac_bad[3] = r3;
+
+      /* next */
+      dmac += 4;
+      dmac_bad += 4;
+      n_left -= 4;
+    }
+#endif
+}
+
 /* process frame of buffers, store ethertype into array and update
    buffer metadata fields depending on interface being l2 or l3 assuming that
    packets are untagged. For tagged packets those fields are updated later.
@@ -704,62 +767,7 @@ eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
     }
 
   if (dmac_check)
-    {
-      u64 mask = clib_net_to_host_u64 (0xFFFFFFFFFFFF0000);
-      u64 igbit = clib_net_to_host_u64 (0x0100000000000000);
-      u64 hwaddr = (*(u64 *) hi->hw_address) & mask;
-      u64 *dmac = dmacs;
-      u8 *dmac_bad = dmacs_bad;
-
-      n_left = n_packets;
-
-#ifdef CLIB_HAVE_VEC256
-      u64x4 igbit4 = u64x4_splat (igbit);
-      u64x4 mask4 = u64x4_splat (mask);
-      u64x4 hwaddr4 = u64x4_splat (hwaddr);
-      while (n_left >= 0)
-       {
-         u64x4 r0, r1;
-         r0 = u64x4_load_unaligned (dmac + 0) & mask4;
-         r1 = u64x4_load_unaligned (dmac + 4) & mask4;
-
-         r0 = (r0 != hwaddr4) & ((r0 & igbit4) == 0);
-         r1 = (r1 != hwaddr4) & ((r1 & igbit4) == 0);
-
-         *(u32 *) (dmac_bad + 0) = u8x32_msb_mask ((u8x32) (r0));
-         *(u32 *) (dmac_bad + 4) = u8x32_msb_mask ((u8x32) (r1));
-
-         /* next */
-         dmac += 8;
-         dmac_bad += 8;
-         n_left -= 8;
-       }
-#else
-      while (n_left > 0)
-       {
-         u64 r0, r1, r2, r3;
-         r0 = dmac[0] & mask;
-         r1 = dmac[1] & mask;
-         r2 = dmac[2] & mask;
-         r3 = dmac[3] & mask;
-
-         r0 = (r0 != hwaddr) && ((r0 & igbit) == 0);
-         r1 = (r1 != hwaddr) && ((r1 & igbit) == 0);
-         r2 = (r2 != hwaddr) && ((r2 & igbit) == 0);
-         r3 = (r3 != hwaddr) && ((r3 & igbit) == 0);
-
-         dmac_bad[0] = r0;
-         dmac_bad[1] = r1;
-         dmac_bad[2] = r2;
-         dmac_bad[3] = r3;
-
-         /* next */
-         dmac += 4;
-         dmac_bad += 4;
-         n_left -= 4;
-       }
-#endif
-    }
+    eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets);
 
   next_ip4 = em->l3_next.input_next_ip4;
   next_ip6 = em->l3_next.input_next_ip6;
@@ -990,26 +998,38 @@ ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
     }
 
   /* rx pcap capture if enabled */
-  if (PREDICT_FALSE (vm->pcap[VLIB_RX].pcap_enable))
+  if (PREDICT_FALSE (vlib_global_main.pcap.pcap_rx_enable))
     {
       u32 bi0;
+      vnet_pcap_t *pp = &vlib_global_main.pcap;
 
       from = vlib_frame_vector_args (from_frame);
       n_left = from_frame->n_vectors;
       while (n_left > 0)
        {
+         int classify_filter_result;
          vlib_buffer_t *b0;
          bi0 = from[0];
          from++;
+         n_left--;
          b0 = vlib_get_buffer (vm, bi0);
+         if (pp->filter_classify_table_index != ~0)
+           {
+             classify_filter_result =
+               vnet_is_packet_traced_inline
+               (b0, pp->filter_classify_table_index, 0 /* full classify */ );
+             if (classify_filter_result)
+               pcap_add_buffer (&pp->pcap_main, vm, bi0,
+                                pp->max_bytes_per_pkt);
+             continue;
+           }
 
-         if (vm->pcap[VLIB_RX].pcap_sw_if_index == 0 ||
-             vm->pcap[VLIB_RX].pcap_sw_if_index
-             == vnet_buffer (b0)->sw_if_index[VLIB_RX])
+         if (pp->pcap_sw_if_index == 0 ||
+             pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
            {
-             pcap_add_buffer (&vm->pcap[VLIB_RX].pcap_main, vm, bi0, 512);
+             pcap_add_buffer (&pp->pcap_main, vm, bi0,
+                              pp->max_bytes_per_pkt);
            }
-         n_left--;
        }
     }
 }
@@ -2063,6 +2083,11 @@ ethernet_register_input_type (vlib_main_t * vm,
   }
 
   ti = ethernet_get_type_info (em, type);
+  if (ti == 0)
+    {
+      clib_warning ("type_info NULL for type %d", type);
+      return;
+    }
   ti->node_index = node_index;
   ti->next_index = vlib_node_add_next (vm,
                                       ethernet_input_node.index, node_index);