ipsec: enable input features on tunnels
[vpp.git] / src / vnet / ip / ip6_forward.c
index 1d6c1b7..0c1bc3b 100644 (file)
@@ -239,6 +239,8 @@ void
 ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
 {
   ip6_main_t *im = &ip6_main;
+  vnet_main_t *vnm = vnet_get_main ();
+  vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
 
   vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0);
 
@@ -264,6 +266,11 @@ ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
 
   vnet_feature_enable_disable ("ip6-multicast", "ip6-not-enabled",
                               sw_if_index, !is_enable, 0, 0);
+
+  if (is_enable)
+    hi->l3_if_count++;
+  else if (hi->l3_if_count)
+    hi->l3_if_count--;
 }
 
 /* get first interface address */
@@ -361,8 +368,8 @@ ip6_add_del_interface_address (vlib_main_t * vm,
       ip_interface_address_t *ia;
       vnet_sw_interface_t *sif;
 
-      pool_foreach(sif, vnm->interface_main.sw_interfaces,
-      ({
+      pool_foreach (sif, vnm->interface_main.sw_interfaces)
+       {
           if (im->fib_index_by_sw_if_index[sw_if_index] ==
               im->fib_index_by_sw_if_index[sif->sw_if_index])
             {
@@ -409,7 +416,7 @@ ip6_add_del_interface_address (vlib_main_t * vm,
                      }
                  }));
             }
-      }));
+      }
     }
   /* *INDENT-ON* */
 
@@ -428,7 +435,10 @@ ip6_add_del_interface_address (vlib_main_t * vm,
          goto done;
        }
 
-      ip_interface_address_del (lm, if_address_index, addr_fib);
+      error = ip_interface_address_del (lm, vnm, if_address_index, addr_fib,
+                                       address_length, sw_if_index);
+      if (error)
+       goto done;
     }
   else
     {
@@ -945,7 +955,10 @@ format_ip6_forward_next_trace (u8 * s, va_list * args)
   ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *);
   u32 indent = format_get_indent (s);
 
-  s = format (s, "%U%U",
+  s = format (s, "%Ufib:%d adj:%d flow:%d",
+             format_white_space, indent,
+             t->fib_index, t->adj_index, t->flow_hash);
+  s = format (s, "\n%U%U",
              format_white_space, indent,
              format_ip6_header, t->packet_data, sizeof (t->packet_data));
   return s;
@@ -1299,7 +1312,7 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          vlib_prefetch_buffer_data (b[3], LOAD);
        }
 
-      u8 error[2];
+      ip6_error_t error[2];
       error[0] = IP6_ERROR_UNKNOWN_PROTOCOL;
       error[1] = IP6_ERROR_UNKNOWN_PROTOCOL;
 
@@ -1320,15 +1333,23 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          flags[0] = b[0]->flags;
          flags[1] = b[1]->flags;
 
+         u32 oflags[2];
+         oflags[0] = vnet_buffer2 (b[0])->oflags;
+         oflags[1] = vnet_buffer2 (b[1])->oflags;
+
+         u32 l4_offload[2];
+         l4_offload[0] = (flags[0] & VNET_BUFFER_F_OFFLOAD) &&
+                         (oflags[0] & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM |
+                                       VNET_BUFFER_OFFLOAD_F_UDP_CKSUM));
+         l4_offload[1] = (flags[1] & VNET_BUFFER_F_OFFLOAD) &&
+                         (oflags[1] & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM |
+                                       VNET_BUFFER_OFFLOAD_F_UDP_CKSUM));
+
          u32 good_l4_csum[2];
          good_l4_csum[0] =
-           flags[0] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT |
-                       VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
-                       VNET_BUFFER_F_OFFLOAD_UDP_CKSUM);
+           (flags[0] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload[0];
          good_l4_csum[1] =
-           flags[1] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT |
-                       VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
-                       VNET_BUFFER_F_OFFLOAD_UDP_CKSUM);
+           (flags[1] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload[1];
 
          u32 udp_offset[2] = { };
          u8 is_tcp_udp[2];
@@ -1456,8 +1477,8 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       next[1] =
        error[1] != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[1];
 
-      b[0]->error = error_node->errors[0];
-      b[1]->error = error_node->errors[1];
+      b[0]->error = error_node->errors[error[0]];
+      b[1]->error = error_node->errors[error[1]];
 
       if (head_of_feature_arc)
        {
@@ -1502,11 +1523,15 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          u8 type = lm->builtin_protocol_by_ip_protocol[ip->protocol];
 
          u32 flags = b[0]->flags;
-         u32 good_l4_csum =
-           flags & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT |
-                    VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
-                    VNET_BUFFER_F_OFFLOAD_UDP_CKSUM);
 
+         u32 oflags = vnet_buffer2 (b[0])->oflags;
+
+         u32 l4_offload = (flags & VNET_BUFFER_F_OFFLOAD) &&
+                          (oflags & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM |
+                                     VNET_BUFFER_OFFLOAD_F_UDP_CKSUM));
+
+         u32 good_l4_csum =
+           (flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload;
          u32 udp_offset;
          i16 len_diff = 0;
          u8 is_tcp_udp = ip6_next_proto_is_tcp_udp (b[0], ip, &udp_offset);
@@ -1526,8 +1551,9 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          good_l4_csum |= type == IP_BUILTIN_PROTOCOL_UNKNOWN;
          len_diff = type == IP_BUILTIN_PROTOCOL_UDP ? len_diff : 0;
 
-         u8 need_csum = type != IP_BUILTIN_PROTOCOL_UNKNOWN && !good_l4_csum
-           && !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED);
+         u8 need_csum = type != IP_BUILTIN_PROTOCOL_UNKNOWN &&
+                        !good_l4_csum &&
+                        !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED);
          if (PREDICT_FALSE (need_csum))
            {
              flags = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]);
@@ -1543,7 +1569,6 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
 
          error = len_diff < 0 ? IP6_ERROR_UDP_LENGTH : error;
-
          STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP ==
                         IP6_ERROR_UDP_CHECKSUM,
                         "Wrong IP6 errors constants");
@@ -1576,7 +1601,7 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       next[0] =
        error != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[0];
 
-      b[0]->error = error_node->errors[0];
+      b[0]->error = error_node->errors[error];
 
       if (head_of_feature_arc)
        {
@@ -1869,8 +1894,6 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
          if (p1->flags & VNET_BUFFER_F_GSO)
            ip1_len = gso_mtu_sz (p1);
 
-
-
          ip6_mtu_check (p0, ip0_len,
                         adj0[0].rewrite_header.max_l3_packet_bytes,
                         is_locally_originated0, &next0, is_midchain,
@@ -1879,18 +1902,15 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
                         adj1[0].rewrite_header.max_l3_packet_bytes,
                         is_locally_originated1, &next1, is_midchain,
                         &error1);
-
          /* Don't adjust the buffer for hop count issue; icmp-error node
           * wants to see the IP header */
          if (PREDICT_TRUE (error0 == IP6_ERROR_NONE))
            {
              p0->current_data -= rw_len0;
              p0->current_length += rw_len0;
-
              tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
              vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
              next0 = adj0[0].rewrite_header.next_index;
-
              if (PREDICT_FALSE
                  (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
                vnet_feature_arc_start_w_cfg_index
@@ -1926,11 +1946,9 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
              /* before we paint on the next header, update the L4
               * checksums if required, since there's no offload on a tunnel */
              vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ ,
-                                         1 /* is_ip6 */ ,
-                                         0 /* with gso */ );
+                                         1 /* is_ip6 */ );
              vnet_calc_checksums_inline (vm, p1, 0 /* is_ip4 */ ,
-                                         1 /* is_ip6 */ ,
-                                         0 /* with gso */ );
+                                         1 /* is_ip6 */ );
 
              /* Guess we are only writing on ipv6 header. */
              vnet_rewrite_two_headers (adj0[0], adj1[0],
@@ -2026,8 +2044,7 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
          if (is_midchain)
            {
              vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ ,
-                                         1 /* is_ip6 */ ,
-                                         0 /* with gso */ );
+                                         1 /* is_ip6 */ );
 
              /* Guess we are only writing on ip6 header. */
              vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip6_header_t));
@@ -2060,7 +2077,6 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
                         adj0[0].rewrite_header.max_l3_packet_bytes,
                         is_locally_originated0, &next0, is_midchain,
                         &error0);
-
          /* Don't adjust the buffer for hop count issue; icmp-error node
           * wants to see the IP header */
          if (PREDICT_TRUE (error0 == IP6_ERROR_NONE))
@@ -2279,7 +2295,6 @@ format_ip6_hop_by_hop_ext_hdr (u8 * s, va_list * args)
   ip6_hop_by_hop_option_t *opt0, *limit0;
   ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main;
   u8 type0;
-
   s = format (s, "IP6_HOP_BY_HOP: next protocol %d len %d total %d",
              hbh0->protocol, (hbh0->length + 1) << 3, total_len);
 
@@ -2302,9 +2317,8 @@ format_ip6_hop_by_hop_ext_hdr (u8 * s, va_list * args)
            }
          else
            {
-             s =
-               format (s, "\n    unrecognized option %d length %d", type0,
-                       opt0->length);
+             s = format (s, "\n    unrecognized option %d length %d", type0,
+                         opt0->length);
            }
          opt0 =
            (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
@@ -2352,9 +2366,8 @@ format_ip6_hop_by_hop_trace (u8 * s, va_list * args)
            }
          else
            {
-             s =
-               format (s, "\n    unrecognized option %d length %d", type0,
-                       opt0->length);
+             s = format (s, "\n    unrecognized option %d length %d", type0,
+                         opt0->length);
            }
          opt0 =
            (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
@@ -2801,24 +2814,6 @@ ip6_lookup_init (vlib_main_t * vm)
 
   ip_lookup_init (&im->lookup_main, /* is_ip6 */ 1);
 
-  if (im->lookup_table_nbuckets == 0)
-    im->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS;
-
-  im->lookup_table_nbuckets = 1 << max_log2 (im->lookup_table_nbuckets);
-
-  if (im->lookup_table_size == 0)
-    im->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
-
-  clib_bihash_init_24_8 (&(im->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash),
-                        "ip6 FIB fwding table",
-                        im->lookup_table_nbuckets, im->lookup_table_size);
-  clib_bihash_init_24_8 (&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
-                        "ip6 FIB non-fwding table",
-                        im->lookup_table_nbuckets, im->lookup_table_size);
-  clib_bihash_init_40_8 (&im->ip6_mtable.ip6_mhash,
-                        "ip6 mFIB table",
-                        im->lookup_table_nbuckets, im->lookup_table_size);
-
   /* Create FIB with index 0 and table id of 0. */
   fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
                                     FIB_SOURCE_DEFAULT_ROUTE);
@@ -2839,24 +2834,6 @@ ip6_lookup_init (vlib_main_t * vm)
 
 VLIB_INIT_FUNCTION (ip6_lookup_init);
 
-#ifndef CLIB_MARCH_VARIANT
-int
-vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config)
-{
-  u32 fib_index;
-
-  fib_index = fib_table_find (FIB_PROTOCOL_IP6, table_id);
-
-  if (~0 == fib_index)
-    return VNET_API_ERROR_NO_SUCH_FIB;
-
-  fib_table_set_flow_hash_config (fib_index, FIB_PROTOCOL_IP6,
-                                 flow_hash_config);
-
-  return 0;
-}
-#endif
-
 static clib_error_t *
 set_ip6_flow_hash_command_fn (vlib_main_t * vm,
                              unformat_input_t * input,
@@ -2871,8 +2848,12 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm,
     {
       if (unformat (input, "table %d", &table_id))
        matched = 1;
-#define _(a,v) \
-    else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;}
+#define _(a, b, v)                                                            \
+  else if (unformat (input, #a))                                              \
+  {                                                                           \
+    flow_hash_config |= v;                                                    \
+    matched = 1;                                                              \
+  }
       foreach_flow_hash_bit
 #undef _
        else
@@ -2883,7 +2864,7 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm,
     return clib_error_return (0, "unknown input `%U'",
                              format_unformat_error, input);
 
-  rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config);
+  rv = ip_flow_hash_set (AF_IP6, table_id, flow_hash_config);
   switch (rv)
     {
     case 0:
@@ -2976,11 +2957,10 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm,
  * @endparblock
 ?*/
 /* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) =
-{
+VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) = {
   .path = "set ip6 flow-hash",
-  .short_help =
-  "set ip6 flow-hash table <table-id> [src] [dst] [sport] [dport] [proto] [reverse]",
+  .short_help = "set ip6 flow-hash table <table-id> [src] [dst] [sport] "
+               "[dport] [proto] [reverse] [flowlabel]",
   .function = set_ip6_flow_hash_command_fn,
 };
 /* *INDENT-ON* */
@@ -3035,8 +3015,7 @@ VLIB_CLI_COMMAND (show_ip6_local, static) =
 
 #ifndef CLIB_MARCH_VARIANT
 int
-vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
-                            u32 table_index)
+vnet_set_ip6_classify_intfc (vlib_main_t *vm, u32 sw_if_index, u32 table_index)
 {
   vnet_main_t *vnm = vnet_get_main ();
   vnet_interface_main_t *im = &vnm->interface_main;
@@ -3067,17 +3046,13 @@ vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
 
       fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
                                                       sw_if_index);
-
-
       if (table_index != (u32) ~ 0)
        {
          dpo_id_t dpo = DPO_INVALID;
-
          dpo_set (&dpo,
                   DPO_CLASSIFY,
                   DPO_PROTO_IP6,
                   classify_dpo_create (DPO_PROTO_IP6, table_index));
-
          fib_table_entry_special_dpo_add (fib_index,
                                           &pfx,
                                           FIB_SOURCE_CLASSIFY,
@@ -3158,34 +3133,6 @@ VLIB_CLI_COMMAND (set_ip6_classify_command, static) =
 };
 /* *INDENT-ON* */
 
-static clib_error_t *
-ip6_config (vlib_main_t * vm, unformat_input_t * input)
-{
-  ip6_main_t *im = &ip6_main;
-  uword heapsize = 0;
-  u32 tmp;
-  u32 nbuckets = 0;
-
-  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
-    {
-      if (unformat (input, "hash-buckets %d", &tmp))
-       nbuckets = tmp;
-      else if (unformat (input, "heap-size %U",
-                        unformat_memory_size, &heapsize))
-       ;
-      else
-       return clib_error_return (0, "unknown input '%U'",
-                                 format_unformat_error, input);
-    }
-
-  im->lookup_table_nbuckets = nbuckets;
-  im->lookup_table_size = heapsize;
-
-  return 0;
-}
-
-VLIB_EARLY_CONFIG_FUNCTION (ip6_config, "ip6");
-
 /*
  * fd.io coding-style-patch-verification: ON
  *