feature: convert all feature nodes to new feature infra
[vpp.git] / vnet / vnet / ip / ip4_source_and_port_range_check.c
index 8a469ba..28dabeb 100644 (file)
 #include <vnet/fib/fib_table.h>
 #include <vnet/fib/ip4_fib.h>
 
+/**
+ * @file
+ * @brief IPv4 Source and Port Range Checking.
+ *
+ * This file contains the source code for IPv4 source and port range
+ * checking.
+ */
+
+
 /**
  * @brief The pool of range chack DPOs
  */
@@ -88,7 +97,6 @@ static inline u32
 check_adj_port_range_x1 (const protocol_port_range_dpo_t * ppr_dpo,
                         u16 dst_port, u32 next)
 {
-  const protocol_port_range_t *range;
   u16x8vec_t key;
   u16x8vec_t diff1;
   u16x8vec_t diff2;
@@ -131,7 +139,6 @@ check_adj_port_range_x1 (const protocol_port_range_dpo_t * ppr_dpo,
       winner_mask = sum_nonzero & sum_equal;
       if (winner_mask)
        return next;
-      range++;
     }
   return IP4_SOURCE_AND_PORT_RANGE_CHECK_NEXT_DROP;
 }
@@ -148,10 +155,6 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
                                        vlib_frame_t * frame, int is_tx)
 {
   ip4_main_t *im = &ip4_main;
-  ip_lookup_main_t *lm = &im->lookup_main;
-  ip_config_main_t *rx_cm =
-    &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
-  ip_config_main_t *tx_cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
   u32 n_left_from, *from, *to_next;
   u32 next_index;
   vlib_node_runtime_t *error_node = node;
@@ -426,6 +429,7 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
          udp_header_t *udp0;
          const protocol_port_range_dpo_t *ppr_dpo0 = NULL;
          const dpo_id_t *dpo;
+         u32 sw_if_index0;
 
          bi0 = from[0];
          to_next[0] = bi0;
@@ -435,28 +439,17 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
          n_left_to_next -= 1;
 
          b0 = vlib_get_buffer (vm, bi0);
+         sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
 
-         fib_index0 =
-           vec_elt (im->fib_index_by_sw_if_index,
-                    vnet_buffer (b0)->sw_if_index[VLIB_RX]);
+         fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
 
          if (is_tx)
            vlib_buffer_advance (b0, sizeof (ethernet_header_t));
 
          ip0 = vlib_buffer_get_current (b0);
 
-         if (is_tx)
-           {
-             c0 = vnet_get_config_data
-               (&tx_cm->config_main, &b0->current_config_index,
-                &next0, sizeof (c0[0]));
-           }
-         else
-           {
-             c0 = vnet_get_config_data
-               (&rx_cm->config_main, &b0->current_config_index,
-                &next0, sizeof (c0[0]));
-           }
+         c0 = vnet_feature_next_with_data (sw_if_index0, &next0,
+                                           b0, sizeof (c0[0]));
 
          /* we can't use the default VRF here... */
          for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
@@ -562,7 +555,6 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
                                 IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK,
                                 good_packets);
   return frame->n_vectors;
-  return 0;
 }
 
 static uword
@@ -631,14 +623,7 @@ set_ip_source_and_port_range_check (vlib_main_t * vm,
                                    u32 * fib_index,
                                    u32 sw_if_index, u32 is_add)
 {
-  ip4_main_t *im = &ip4_main;
-  ip_lookup_main_t *lm = &im->lookup_main;
-  ip_config_main_t *rx_cm =
-    &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
-  ip_config_main_t *tx_cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
-  u32 ci;
   ip_source_and_port_range_check_config_t config;
-  u32 feature_index;
   int rv = 0;
   int i;
 
@@ -651,36 +636,20 @@ set_ip_source_and_port_range_check (vlib_main_t * vm,
   if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] != ~0) ||
       (fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] != ~0))
     {
-      feature_index = im->ip4_unicast_rx_feature_source_and_port_range_check;
-
-      vec_validate (rx_cm->config_index_by_sw_if_index, sw_if_index);
-
-      ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
-      ci = (is_add
-           ? vnet_config_add_feature
-           : vnet_config_del_feature)
-       (vm, &rx_cm->config_main, ci, feature_index, &config,
-        sizeof (config));
-      rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
+      vnet_feature_enable_disable ("ip4-unicast",
+                                  "ip4-source-and-port-range-check-rx",
+                                  sw_if_index, is_add, &config,
+                                  sizeof (config));
     }
 
   /* For IN we are in the TX path */
   if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] != ~0) ||
       (fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] != ~0))
     {
-      feature_index = im->ip4_unicast_tx_feature_source_and_port_range_check;
-
-      vec_validate (tx_cm->config_index_by_sw_if_index, sw_if_index);
-
-      ci = tx_cm->config_index_by_sw_if_index[sw_if_index];
-      ci = (is_add
-           ? vnet_config_add_feature
-           : vnet_config_del_feature)
-       (vm, &tx_cm->config_main, ci, feature_index, &config,
-        sizeof (config));
-      tx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
-
-      vnet_config_update_tx_feature_count (lm, tx_cm, sw_if_index, is_add);
+      vnet_feature_enable_disable ("ip4-output",
+                                  "ip4-source-and-port-range-check-tx",
+                                  sw_if_index, is_add, &config,
+                                  sizeof (config));
     }
   return rv;
 }
@@ -781,20 +750,82 @@ set_ip_source_and_port_range_check_fn (vlib_main_t * vm,
   return error;
 }
 
+/*?
+ * Add the 'ip4-source-and-port-range-check-rx' or
+ * 'ip4-source-and-port-range-check-tx' graph node for a given
+ * interface. 'tcp-out-vrf' and 'udp-out-vrf' will add to
+ * the RX path. 'tcp-in-vrf' and 'udp-in-vrf' will add to
+ * the TX path. A graph node will be inserted into the chain when
+ * the range check is added to the first interface. It will not
+ * be removed from when range check is removed from the last
+ * interface.
+ *
+ * By adding the range check graph node to the interface, incoming
+ * or outgoing TCP/UDP packets will be validated using the
+ * provided IPv4 FIB table (VRF).
+ *
+ * @note 'ip4-source-and-port-range-check-rx' and
+ * 'ip4-source-and-port-range-check-tx' strings are too long, so
+ * they are truncated on the 'show vlib graph' output.
+ *
+ * @todo This content needs to be validated and potentially more detail added.
+ *
+ * @cliexpar
+ * @parblock
+ * Example of graph node before range checking is enabled:
+ * @cliexstart{show vlib graph ip4-source-and-port-range-check-tx}
+ *            Name                      Next                    Previous
+ * ip4-source-and-port-range-      error-drop [0]
+ * @cliexend
+ *
+ * Example of how to enable range checking on TX:
+ * @cliexcmd{set interface ip source-and-port-range-check GigabitEthernet2/0/0 udp-in-vrf 7}
+ *
+ * Example of graph node after range checking is enabled:
+ * @cliexstart{show vlib graph ip4-source-and-port-range-check-tx}
+ *            Name                      Next                    Previous
+ * ip4-source-and-port-range-      error-drop [0]           ip4-rewrite-local
+ *                              interface-output [1]       ip4-rewrite-transit
+ * @cliexend
+ *
+ * Example of how to display the features enabed on an interface:
+ * @cliexstart{show ip interface features GigabitEthernet2/0/0}
+ * IP feature paths configured on GigabitEthernet2/0/0...
+ *
+ * ipv4 unicast:
+ *   ip4-source-and-port-range-check-rx
+ *   ip4-lookup
+ *
+ * ipv4 multicast:
+ *   ip4-lookup-multicast
+ *
+ * ipv4 multicast:
+ *   interface-output
+ *
+ * ipv6 unicast:
+ *   ip6-lookup
+ *
+ * ipv6 multicast:
+ *   ip6-lookup
+ *
+ * ipv6 multicast:
+ *   interface-output
+ * @cliexend
+ * @endparblock
+?*/
 /* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_interface_ip_source_and_port_range_check_command,
-                  static) = {
+VLIB_CLI_COMMAND (set_interface_ip_source_and_port_range_check_command, static) = {
   .path = "set interface ip source-and-port-range-check",
   .function = set_ip_source_and_port_range_check_fn,
-  .short_help = "set int ip source-and-port-range-check <intfc> [tcp-out-vrf <n>] [udp-out-vrf <n>] [tcp-in-vrf <n>] [udp-in-vrf <n>] [del]",
+  .short_help = "set interface ip source-and-port-range-check <interface> [tcp-out-vrf <table-id>] [udp-out-vrf <table-id>] [tcp-in-vrf <table-id>] [udp-in-vrf <table-id>] [del]",
 };
 /* *INDENT-ON* */
 
 static u8 *
 format_ppr_dpo (u8 * s, va_list * args)
 {
-  index_t index = va_arg (args, index_t);
-  CLIB_UNUSED (u32 indent) = va_arg (args, u32);
+  index_t index = va_arg (*args, index_t);
+  CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
 
   protocol_port_range_dpo_t *ppr_dpo;
   int i, j;
@@ -886,7 +917,7 @@ add_port_range_adjacency (u32 fib_index,
                          u32 length, u16 * low_ports, u16 * high_ports)
 {
   protocol_port_range_dpo_t *ppr_dpo;
-  dpo_id_t dpop = DPO_NULL;
+  dpo_id_t dpop = DPO_INVALID;
   int i, j, k;
 
   fib_node_index_t fei;
@@ -916,7 +947,7 @@ add_port_range_adjacency (u32 fib_index,
        * the prefix is already there.
        * check it was sourced by us, and if so get the ragne DPO from it.
        */
-      dpo_id_t dpo = DPO_NULL;
+      dpo_id_t dpo = DPO_INVALID;
       const dpo_id_t *bucket;
 
       if (fib_entry_get_dpo_for_source (fei, FIB_SOURCE_SPECIAL, &dpo))
@@ -976,9 +1007,9 @@ add_port_range_adjacency (u32 fib_index,
     }
   else
     {
-      fib_table_entry_special_dpo_update (fei,
-                                         FIB_SOURCE_SPECIAL,
-                                         FIB_ENTRY_FLAG_NONE, &dpop);
+      fib_entry_special_update (fei,
+                               FIB_SOURCE_SPECIAL,
+                               FIB_ENTRY_FLAG_NONE, &dpop);
     }
 
   return 0;
@@ -1019,7 +1050,7 @@ remove_port_range_adjacency (u32 fib_index,
        * the prefix is already there.
        * check it was sourced by us
        */
-      dpo_id_t dpo = DPO_NULL;
+      dpo_id_t dpo = DPO_INVALID;
       const dpo_id_t *bucket;
 
       if (fib_entry_get_dpo_for_source (fei, FIB_SOURCE_SPECIAL, &dpo))
@@ -1223,12 +1254,29 @@ ip_source_and_port_range_check_command_fn (vlib_main_t * vm,
   return 0;
 }
 
+/*?
+ * This command adds an IP Subnet and range of ports to be validated
+ * by an IP FIB table (VRF).
+ *
+ * @todo This is incomplete. This needs a detailed description and a
+ * practical example.
+ *
+ * @cliexpar
+ * Example of how to add an IPv4 subnet and single port to an IPv4 FIB table:
+ * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 port 23}
+ * Example of how to add an IPv4 subnet and range of ports to an IPv4 FIB table:
+ * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 range 23 - 100}
+ * Example of how to delete an IPv4 subnet and single port from an IPv4 FIB table:
+ * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 port 23 del}
+ * Example of how to delete an IPv4 subnet and range of ports from an IPv4 FIB table:
+ * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 range 23 - 100 del}
+?*/
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (ip_source_and_port_range_check_command, static) = {
   .path = "set ip source-and-port-range-check",
   .function = ip_source_and_port_range_check_command_fn,
   .short_help =
-  "set ip source-and-port-range-check <ip-addr>/<mask> [range <nn> - <nn>] [vrf <id>] [del]",
+  "set ip source-and-port-range-check vrf <table-id> <ip-addr>/<mask> {port nn | range <nn> - <nn>} [del]",
 };
 /* *INDENT-ON* */
 
@@ -1275,7 +1323,7 @@ show_source_and_port_range_check_fn (vlib_main_t * vm,
    * find the longest prefix match on the address requested,
    * check it was sourced by us
    */
-  dpo_id_t dpo = DPO_NULL;
+  dpo_id_t dpo = DPO_INVALID;
   const dpo_id_t *bucket;
 
   if (!fib_entry_get_dpo_for_source (fib_table_lookup (fib_index, &pfx),
@@ -1327,12 +1375,34 @@ show_source_and_port_range_check_fn (vlib_main_t * vm,
   return 0;
 }
 
+/*?
+ * Display the range of ports being validated by an IPv4 FIB for a given
+ * IP or subnet, or test if a given IP and port are being validated.
+ *
+ * @todo This is incomplete. This needs a detailed description and a
+ * practical example.
+ *
+ * @cliexpar
+ * Example of how to display the set of ports being validated for a given
+ * IPv4 subnet:
+ * @cliexstart{show ip source-and-port-range-check vrf 7 172.16.2.0}
+ * 172.16.2.0: 23 - 101
+ * @cliexend
+ * Example of how to test to determine of a given Pv4 address and port
+ * are being validated:
+ * @cliexstart{show ip source-and-port-range-check vrf 7 172.16.2.2 port 23}
+ * 172.16.2.2 port 23 PASS
+ * @cliexend
+ * @cliexstart{show ip source-and-port-range-check vrf 7 172.16.2.2 port 250}
+ * 172.16.2.2 port 250 FAIL
+ * @cliexend
+ ?*/
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (show_source_and_port_range_check, static) = {
   .path = "show ip source-and-port-range-check",
   .function = show_source_and_port_range_check_fn,
   .short_help =
-  "show ip source-and-port-range-check vrf <nn> <ip-addr> <port>",
+  "show ip source-and-port-range-check vrf <table-id> <ip-addr> [port <n>]",
 };
 /* *INDENT-ON* */