ipfix: add classification nodes for flow statistics (VPP-204)
[vpp.git] / vnet / vnet / ip / ip4_forward.c
index a44afb4..e997366 100644 (file)
@@ -46,6 +46,7 @@
 #include <vnet/api_errno.h>     /* for API error numbers */
 #include <vnet/fib/fib_table.h> /* for FIB table and entry creation */
 #include <vnet/fib/fib_entry.h> /* for FIB table and entry creation */
+#include <vnet/fib/fib_urpf_list.h> /* for FIB uRPF check */
 #include <vnet/fib/ip4_fib.h>
 #include <vnet/dpo/load_balance.h>
 #include <vnet/dpo/classify_dpo.h>
@@ -796,6 +797,12 @@ ip4_add_del_interface_address (vlib_main_t * vm, u32 sw_if_index,
 }
 
 /* Built-in ip4 unicast rx feature path definition */
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_flow_classify, static) = {
+  .node_name = "ip4-flow-classify",
+  .runs_before = ORDER_CONSTRAINTS {"ip4-inacl", 0},
+  .feature_index = &ip4_main.ip4_unicast_rx_feature_flow_classify,
+};
+
 VNET_IP4_UNICAST_FEATURE_INIT (ip4_inacl, static) = {
   .node_name = "ip4-inacl", 
   .runs_before = ORDER_CONSTRAINTS {"ip4-source-check-via-rx", 0},
@@ -1059,7 +1066,7 @@ VLIB_INIT_FUNCTION (ip4_lookup_init);
 
 typedef struct {
   /* Adjacency taken. */
-  u32 adj_index;
+  u32 dpo_index;
   u32 flow_hash;
   u32 fib_index;
 
@@ -1087,7 +1094,7 @@ static u8 * format_ip4_lookup_trace (u8 * s, va_list * args)
   uword indent = format_get_indent (s);
 
   s = format (s, "fib %d dpo-idx %d flow hash: 0x%08x",
-              t->fib_index, t->adj_index, t->flow_hash);
+              t->fib_index, t->dpo_index, t->flow_hash);
   s = format (s, "\n%U%U",
               format_white_space, indent,
               format_ip4_header, t->packet_data, sizeof (t->packet_data));
@@ -1102,14 +1109,14 @@ static u8 * format_ip4_rewrite_trace (u8 * s, va_list * args)
   vnet_main_t * vnm = vnet_get_main();
   uword indent = format_get_indent (s);
 
-  s = format (s, "tx_sw_if_index %d adj-idx %d : %U flow hash: 0x%08x",
-              t->fib_index, t->adj_index, format_ip_adjacency,
-              vnm, t->adj_index, FORMAT_IP_ADJACENCY_NONE,
+  s = format (s, "tx_sw_if_index %d dpo-idx %d : %U flow hash: 0x%08x",
+              t->fib_index, t->dpo_index, format_ip_adjacency,
+              vnm, t->dpo_index, FORMAT_IP_ADJACENCY_NONE,
              t->flow_hash);
   s = format (s, "\n%U%U",
               format_white_space, indent,
               format_ip_adjacency_packet_data,
-              vnm, t->adj_index,
+              vnm, t->dpo_index,
               t->packet_data, sizeof (t->packet_data));
   return s;
 }
@@ -1146,7 +1153,7 @@ ip4_forward_next_trace (vlib_main_t * vm,
       if (b0->flags & VLIB_BUFFER_IS_TRACED)
        {
          t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
-         t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
+         t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
          t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
          t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ?
              vnet_buffer(b0)->sw_if_index[VLIB_TX] :
@@ -1160,7 +1167,7 @@ ip4_forward_next_trace (vlib_main_t * vm,
       if (b1->flags & VLIB_BUFFER_IS_TRACED)
        {
          t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
-         t1->adj_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
+         t1->dpo_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
          t1->flow_hash = vnet_buffer (b1)->ip.flow_hash;
          t1->fib_index = (vnet_buffer(b1)->sw_if_index[VLIB_TX] != (u32)~0) ?
              vnet_buffer(b1)->sw_if_index[VLIB_TX] :
@@ -1187,7 +1194,7 @@ ip4_forward_next_trace (vlib_main_t * vm,
       if (b0->flags & VLIB_BUFFER_IS_TRACED)
        {
          t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
-         t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
+         t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
          t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
          t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ?
              vnet_buffer(b0)->sw_if_index[VLIB_TX] :
@@ -1501,31 +1508,31 @@ ip4_local (vlib_main_t * vm,
          /* 
            * Must have a route to source otherwise we drop the packet.
            * ip4 broadcasts are accepted, e.g. to make dhcp client work
+          *
+          * The checks are:
+          *  - the source is a recieve => it's from us => bogus, do this
+          *    first since it sets a different error code.
+          *  - uRPF check for any route to source - accept if passes.
+          *  - allow packets destined to the broadcast address from unknown sources
            */
-         error0 = (error0 == IP4_ERROR_UNKNOWN_PROTOCOL
-                   && dpo0->dpoi_type != DPO_ADJACENCY
-                   && dpo0->dpoi_type != DPO_ADJACENCY_INCOMPLETE
-                   && dpo0->dpoi_type != DPO_RECEIVE
-                   && dpo0->dpoi_type != DPO_DROP
-                   && dpo0->dpoi_type != DPO_ADJACENCY_GLEAN
-                   && ip0->dst_address.as_u32 != 0xFFFFFFFF
-                   ? IP4_ERROR_SRC_LOOKUP_MISS
-                   : error0);
-          error0 = (dpo0->dpoi_type == DPO_RECEIVE ?
+          error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+                    dpo0->dpoi_type == DPO_RECEIVE) ?
                     IP4_ERROR_SPOOFED_LOCAL_PACKETS : 
                     error0);
-         error1 = (error1 == IP4_ERROR_UNKNOWN_PROTOCOL
-                   && dpo1->dpoi_type != DPO_ADJACENCY
-                   && dpo1->dpoi_type != DPO_ADJACENCY_INCOMPLETE
-                   && dpo1->dpoi_type != DPO_RECEIVE
-                   && dpo1->dpoi_type != DPO_DROP
-                   && dpo1->dpoi_type != DPO_ADJACENCY_GLEAN
-                   && ip1->dst_address.as_u32 != 0xFFFFFFFF
+         error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+                    !fib_urpf_check_size(lb0->lb_urpf) &&
+                    ip0->dst_address.as_u32 != 0xFFFFFFFF)
                    ? IP4_ERROR_SRC_LOOKUP_MISS
-                   : error1);
-          error1 = (dpo0->dpoi_type == DPO_RECEIVE ?
+                   : error0);
+          error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+                    dpo1->dpoi_type == DPO_RECEIVE) ?
                     IP4_ERROR_SPOOFED_LOCAL_PACKETS : 
                     error1);
+         error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+                    !fib_urpf_check_size(lb1->lb_urpf) &&
+                    ip1->dst_address.as_u32 != 0xFFFFFFFF)
+                   ? IP4_ERROR_SRC_LOOKUP_MISS
+                   : error1);
 
          next0 = lm->local_next_by_ip_protocol[proto0];
          next1 = lm->local_next_by_ip_protocol[proto1];
@@ -1670,20 +1677,15 @@ ip4_local (vlib_main_t * vm,
              vnet_buffer (p0)->ip.adj_index[VLIB_RX] =
                  dpo0->dpoi_index;
 
-         /* Must have a route to source otherwise we drop the packet. */
-         error0 = (error0 == IP4_ERROR_UNKNOWN_PROTOCOL
-                   && dpo0->dpoi_type != DPO_ADJACENCY
-                   && dpo0->dpoi_type != DPO_ADJACENCY_INCOMPLETE
-                   && dpo0->dpoi_type != DPO_RECEIVE
-                   && dpo0->dpoi_type != DPO_DROP
-                   && dpo0->dpoi_type != DPO_ADJACENCY_GLEAN
-                   && ip0->dst_address.as_u32 != 0xFFFFFFFF
-                   ? IP4_ERROR_SRC_LOOKUP_MISS
-                   : error0);
-          /* Packet originated from a local address => spoofing */
-          error0 = (dpo0->dpoi_type == DPO_RECEIVE ?
+          error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+                    dpo0->dpoi_type == DPO_RECEIVE) ?
                     IP4_ERROR_SPOOFED_LOCAL_PACKETS : 
                     error0);
+         error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+                    !fib_urpf_check_size(lb0->lb_urpf) &&
+                    ip0->dst_address.as_u32 != 0xFFFFFFFF)
+                   ? IP4_ERROR_SRC_LOOKUP_MISS
+                   : error0);
 
          next0 = lm->local_next_by_ip_protocol[proto0];