ip: Fix crash in ip address add on sub-int without exact-match
[vpp.git] / src / vnet / ip / ip6_forward.c
index 0ed20ee..f1de446 100644 (file)
 #include <vnet/dpo/load_balance_map.h>
 #include <vnet/dpo/classify_dpo.h>
 #include <vnet/classify/vnet_classify.h>
+#include <vnet/pg/pg.h>
 
 #ifndef CLIB_MARCH_VARIANT
 #include <vppinfra/bihash_template.c>
 #endif
 #include <vnet/ip/ip6_forward.h>
-#include <vnet/ipsec/ipsec_tun.h>
 #include <vnet/interface_output.h>
 
 /* Flag used by IOAM code. Classifier sets it pop-hop-by-hop checks it */
@@ -308,12 +308,9 @@ ip6_add_del_interface_address (vlib_main_t * vm,
   ip6_address_fib_t ip6_af, *addr_fib = 0;
   const ip6_address_t *ll_addr;
 
-  /* local0 interface doesn't support IP addressing */
-  if (sw_if_index == 0)
-    {
-      return
-       clib_error_create ("local0 interface doesn't support IP addressing");
-    }
+  error = vnet_sw_interface_supports_addressing (vnm, sw_if_index);
+  if (error)
+    return error;
 
   if (ip6_address_is_link_local_unicast (address))
     {
@@ -1334,15 +1331,23 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          flags[0] = b[0]->flags;
          flags[1] = b[1]->flags;
 
+         vnet_buffer_oflags_t oflags[2];
+         oflags[0] = vnet_buffer (b[0])->oflags;
+         oflags[1] = vnet_buffer (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];
@@ -1516,11 +1521,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);
 
+         vnet_buffer_oflags_t oflags = vnet_buffer (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);
@@ -1540,8 +1549,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]);
@@ -1557,7 +1567,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");
@@ -1768,8 +1777,8 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
            vlib_prefetch_buffer_header (p2, LOAD);
            vlib_prefetch_buffer_header (p3, LOAD);
 
-           CLIB_PREFETCH (p2->pre_data, 32, STORE);
-           CLIB_PREFETCH (p3->pre_data, 32, STORE);
+           clib_prefetch_store (p2->pre_data);
+           clib_prefetch_store (p3->pre_data);
 
            CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
            CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
@@ -1883,8 +1892,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,
@@ -1893,18 +1900,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
@@ -2071,7 +2075,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))
@@ -2290,7 +2293,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);
 
@@ -2313,9 +2315,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 +
@@ -2363,9 +2364,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 +
@@ -3013,8 +3013,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;
@@ -3045,17 +3044,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,