MPLS infrastructure improvments
[vpp.git] / vnet / vnet / ip / lookup.c
index 384e389..1a32b4a 100644 (file)
 #include <vnet/dpo/classify_dpo.h>
 #include <vnet/dpo/punt_dpo.h>
 #include <vnet/dpo/receive_dpo.h>
+#include <vnet/dpo/ip_null_dpo.h>
+
+/**
+ * @file
+ * @brief IPv4 and IPv6 adjacency and lookup table managment.
+ *
+ */
 
 clib_error_t *
 ip_interface_address_add_del (ip_lookup_main_t * lm,
@@ -158,8 +165,10 @@ ip_interface_address_add_del (ip_lookup_main_t * lm,
 void ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6)
 {
   /* ensure that adjacency is cacheline aligned and sized */
-  ASSERT(STRUCT_OFFSET_OF(ip_adjacency_t, cacheline0) == 0);
-  ASSERT(STRUCT_OFFSET_OF(ip_adjacency_t, cacheline1) == CLIB_CACHE_LINE_BYTES);
+  STATIC_ASSERT(STRUCT_OFFSET_OF(ip_adjacency_t, cacheline0) == 0,
+               "Cache line marker must be 1st element in struct");
+  STATIC_ASSERT(STRUCT_OFFSET_OF(ip_adjacency_t, cacheline1) == CLIB_CACHE_LINE_BYTES,
+               "Data in cache line 0 is bigger than cache line size");
 
   /* Preallocate three "special" adjacencies */
   lm->adjacency_heap = adj_pool;
@@ -272,6 +281,12 @@ static uword unformat_dpo (unformat_input_t * input, va_list * args)
     dpo_copy(dpo, punt_dpo_get(proto));
   else if (unformat (input, "local"))
     receive_dpo_add_or_lock(proto, ~0, NULL, dpo);
+  else if (unformat (input, "null-send-unreach"))
+      ip_null_dpo_add_and_lock(proto, IP_NULL_ACTION_SEND_ICMP_UNREACH, dpo);
+  else if (unformat (input, "null-send-prohibit"))
+      ip_null_dpo_add_and_lock(proto, IP_NULL_ACTION_SEND_ICMP_PROHIBIT, dpo);
+  else if (unformat (input, "null"))
+      ip_null_dpo_add_and_lock(proto, IP_NULL_ACTION_NONE, dpo);
   else if (unformat (input, "classify"))
     {
       u32 classify_table_index;
@@ -283,7 +298,7 @@ static uword unformat_dpo (unformat_input_t * input, va_list * args)
        }
 
       dpo_set(dpo, DPO_CLASSIFY, proto,
-              classify_dpo_create(fp, classify_table_index));
+              classify_dpo_create(proto, classify_table_index));
     }
   else
     return 0;
@@ -331,10 +346,10 @@ vnet_ip_route_cmd (vlib_main_t * vm,
 {
   unformat_input_t _line_input, * line_input = &_line_input;
   fib_route_path_t *rpaths = NULL, rpath;
-  dpo_id_t dpo = DPO_NULL, *dpos = NULL;
+  dpo_id_t dpo = DPO_INVALID, *dpos = NULL;
   fib_prefix_t *prefixs = NULL, pfx;
+  mpls_label_t out_label, via_label;
   clib_error_t * error = NULL;
-  mpls_label_t out_label;
   u32 table_id, is_del;
   vnet_main_t * vnm;
   u32 fib_index;
@@ -346,6 +361,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
   table_id = 0;
   count = 1;
   memset(&pfx, 0, sizeof(pfx));
+  out_label = via_label = MPLS_LABEL_INVALID;
 
   /* Get a line of input. */
   if (! unformat_user (main_input, unformat_line_input, line_input))
@@ -388,7 +404,16 @@ vnet_ip_route_cmd (vlib_main_t * vm,
              error = clib_error_return(0 , "Paths then labels");
              goto done;
          }
-         rpaths[vec_len(rpaths)-1].frp_label = out_label;
+         vec_add1(rpaths[vec_len(rpaths)-1].frp_label_stack, out_label);
+      }
+      else if (unformat (line_input, "via-label %U",
+                         unformat_mpls_unicast_label,
+                        &rpath.frp_local_label))
+      {
+         rpath.frp_weight = 1;
+         rpath.frp_proto = FIB_PROTOCOL_MPLS;
+         rpath.frp_sw_if_index = ~0;
+         vec_add1(rpaths, rpath);
       }
       else if (unformat (line_input, "count %f", &count))
        ;
@@ -416,7 +441,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                         &rpath.frp_sw_if_index,
                         &rpath.frp_weight))
       {
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_proto = FIB_PROTOCOL_IP4;
          vec_add1(rpaths, rpath);
       }
@@ -428,7 +452,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                         &rpath.frp_sw_if_index,
                         &rpath.frp_weight))
       {
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_proto = FIB_PROTOCOL_IP6;
          vec_add1(rpaths, rpath);
       }
@@ -439,7 +462,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                         unformat_vnet_sw_interface, vnm,
                         &rpath.frp_sw_if_index))
       {
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_weight = 1;
          rpath.frp_proto = FIB_PROTOCOL_IP4;
          vec_add1(rpaths, rpath);
@@ -451,7 +473,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                         unformat_vnet_sw_interface, vnm,
                         &rpath.frp_sw_if_index))
       {
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_weight = 1;
          rpath.frp_proto = FIB_PROTOCOL_IP6;
          vec_add1(rpaths, rpath);
@@ -463,7 +484,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
       {
          rpath.frp_weight = 1;
          rpath.frp_sw_if_index = ~0;
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_proto = FIB_PROTOCOL_IP4;
          vec_add1(rpaths, rpath);
       }
@@ -474,7 +494,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
       {
          rpath.frp_weight = 1;
          rpath.frp_sw_if_index = ~0;
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_proto = FIB_PROTOCOL_IP6;
          vec_add1(rpaths, rpath);
       }
@@ -489,7 +508,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
          rpath.frp_fib_index = table_id;
          rpath.frp_weight = 1;
          rpath.frp_sw_if_index = ~0;
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_proto = FIB_PROTOCOL_IP4;
          vec_add1(rpaths, rpath);
       }
@@ -500,7 +518,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
          rpath.frp_fib_index = table_id;
          rpath.frp_weight = 1;
          rpath.frp_sw_if_index = ~0;
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_proto = FIB_PROTOCOL_IP6;
          vec_add1(rpaths, rpath);
       }
@@ -508,7 +525,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                         "lookup in table %d",
                         &rpath.frp_fib_index))
       {
-         rpath.frp_label = MPLS_LABEL_INVALID;
          rpath.frp_proto = pfx.fp_proto;
          rpath.frp_sw_if_index = ~0;
          vec_add1(rpaths, rpath);
@@ -517,7 +533,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
               unformat (line_input, "via %U",
                         unformat_dpo, &dpo, prefixs[0].fp_proto))
       {
-         rpath.frp_label = MPLS_LABEL_INVALID;
          vec_add1 (dpos, dpo);
       }
       else
@@ -672,54 +687,56 @@ VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
   .short_help = "Internet protocol (IP) commands",
 };
 
+VLIB_CLI_COMMAND (vlib_cli_ip6_command, static) = {
+  .path = "ip6",
+  .short_help = "Internet protocol version 6 (IPv6) commands",
+};
+
 VLIB_CLI_COMMAND (vlib_cli_show_ip_command, static) = {
   .path = "show ip",
   .short_help = "Internet protocol (IP) show commands",
 };
 
-VLIB_CLI_COMMAND (vlib_cli_show_ip4_command, static) = {
-  .path = "show ip4",
-  .short_help = "Internet protocol version 4 (IP4) show commands",
-};
-
 VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
   .path = "show ip6",
-  .short_help = "Internet protocol version 6 (IP6) show commands",
+  .short_help = "Internet protocol version 6 (IPv6) show commands",
 };
 
 /*?
- * To add or delete routes, use ip route add / del
- * @cliexpar
- * @cliexstart{ip route}
- * To add or delete straightforward static routes, use ip route add / del:
- *  vpp# ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0
- *  vpp# ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0
- *
- * Multiple routes
+ * This command is used to add or delete IPv4 or IPv6 routes. All
+ * IP Addresses ('<em><dst-ip-addr>/<width></em>',
+ * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
+ * can be IPv4 or IPv6, but all must be of the same form in a single
+ * command. To display the current set of routes, use the commands
+ * '<em>show ip fib</em>' and '<em>show ip6 fib</em>'.
  *
+ * @cliexpar
+ * Example of how to add a straight forward static route:
+ * @cliexcmd{ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
+ * Example of how to delete a straight forward static route:
+ * @cliexcmd{ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
  * Mainly for route add/del performance testing, one can add or delete
  * multiple routes by adding 'count N' to the previous item:
- *  vpp# ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0
- *
- * Multipath
- *
+ * @cliexcmd{ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0}
  * Add multiple routes for the same destination to create equal-cost multipath:
- *  vpp# ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0
- *  vpp# ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0
- *
- * For unequal-cost multipath, specify the desired weights:
- *  vpp# ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1
- *  vpp# ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3
- *
- * This combination of weights results in 3/4 of the traffic following the second path, 1/4 following the first path.
- * @cliexend
+ * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0}
+ * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0}
+ * For unequal-cost multipath, specify the desired weights. This
+ * combination of weights results in 3/4 of the traffic following the
+ * second path, 1/4 following the first path:
+ * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1}
+ * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
+ * To add a route to a particular FIB table (VRF), use:
+ * @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
  ?*/
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (ip_route_command, static) = {
   .path = "ip route",
-  .short_help = "Add/delete IP routes",
+  .short_help = "ip route [add|del] [count <n>] <dst-ip-addr>/<width> [table <table-id>] [via <next-hop-ip-addr> [<interface>] [weight <weight>]] | [via arp <interface> <adj-hop-ip-addr>] | [via drop|punt|local<id>|arp|classify <classify-idx>] [lookup in table <out-table-id>]",
   .function = vnet_ip_route_cmd,
   .is_mp_safe = 1,
 };
+/* *INDENT-ON* */
 
 /*
  * The next two routines address a longstanding script hemorrhoid.
@@ -890,9 +907,27 @@ probe_neighbor_address (vlib_main_t * vm,
   return error;
 }
 
+/*?
+ * The '<em>ip probe-neighbor</em>' command ARPs for IPv4 addresses or
+ * attempts IPv6 neighbor discovery depending on the supplied IP address
+ * format.
+ *
+ * @note This command will not immediately affect the indicated FIB; it
+ * is not suitable for use in establishing a FIB entry prior to adding
+ * recursive FIB entries. As in: don't use it in a script to probe a
+ * gateway prior to adding a default route. It won't work. Instead,
+ * configure a static ARP cache entry [see '<em>set ip arp</em>'], or
+ * a static IPv6 neighbor [see '<em>set ip6 neighbor</em>'].
+ *
+ * @cliexpar
+ * Example of probe for an IPv4 address:
+ * @cliexcmd{ip probe-neighbor GigabitEthernet2/0/0 172.16.1.2}
+?*/
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (ip_probe_neighbor_command, static) = {
   .path = "ip probe-neighbor",
   .function = probe_neighbor_address,
-  .short_help = "ip probe-neighbor <intfc> <ip4-addr> | <ip6-addr> [retry nn]",
+  .short_help = "ip probe-neighbor <interface> <ip4-addr> | <ip6-addr> [retry nn]",
   .is_mp_safe = 1,
 };
+/* *INDENT-ON* */