VPP-388 Improve IP header lookup in ipsec_output 12/2712/6
authorFlorin Coras <fcoras@cisco.com>
Tue, 6 Sep 2016 13:18:21 +0000 (15:18 +0200)
committerDamjan Marion <dmarion.lists@gmail.com>
Thu, 8 Sep 2016 14:55:29 +0000 (14:55 +0000)
Change-Id: I5df0067c9ce56d7a15a991b82d4761924d91758b
Signed-off-by: Florin Coras <fcoras@cisco.com>
(cherry picked from commit fb28e9a80c8e36db0a3a484a20e9e0114be517bd)

vnet/vnet/ipsec/ipsec_output.c

index c27e8e6..d8f1c0c 100644 (file)
@@ -221,31 +221,48 @@ ipsec_output_node_fn (vlib_main_t * vm,
       u32 bi0;
       vlib_buffer_t *b0;
       ipsec_policy_t *p0;
-      ip4_header_t *ip0;
+      ip4_header_t *ip0 = 0;
       ip6_header_t *ip6_0 = 0;
       udp_header_t *udp0;
-      u8 is_ipv6 = 0;
+      u8 is_ipv6 = 0, is_ipv4 = 0;
+      u32 iph_offset = 0;
+      u32 adj_index0;
+      ip_adjacency_t *adj0 = 0;
 
       bi0 = from[0];
       b0 = vlib_get_buffer (vm, bi0);
       sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
+      adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
 
+      /* Assume ipv4 */
+      if (PREDICT_TRUE
+         (adj_index0 < vec_len (ip4_main.lookup_main.adjacency_heap)))
+       {
+         adj0 = ip_get_adjacency (&ip4_main.lookup_main, adj_index0);
+         iph_offset = adj0->rewrite_header.data_bytes;
+         ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0)
+                                 + iph_offset);
+         is_ipv4 = ((ip0->ip_version_and_header_length & 0xF0) == 0x40);
+       }
 
-      ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
-                             sizeof (ethernet_header_t));
-
-      /* just forward non ipv4 packets */
-      if (PREDICT_FALSE ((ip0->ip_version_and_header_length & 0xF0) != 0x40))
+      /* Test ipv4 assumption. If true, just forward packets */
+      if (PREDICT_FALSE (!is_ipv4))
        {
-         /* ipv6 packets */
+         /* Packet is not ipv4, try ipv6 */
          if (PREDICT_TRUE
-             ((ip0->ip_version_and_header_length & 0xF0) == 0x60))
+             (adj_index0 < vec_len (ip6_main.lookup_main.adjacency_heap)))
            {
-             is_ipv6 = 1;
-             ip6_0 = (ip6_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
-                                       sizeof (ethernet_header_t));
+             adj0 = ip_get_adjacency (&ip6_main.lookup_main, adj_index0);
+             iph_offset = adj0->rewrite_header.data_bytes;
+             ip6_0 = (ip6_header_t *) ((u8 *) vlib_buffer_get_current (b0)
+                                       + iph_offset);
+             is_ipv6 =
+               ((ip6_0->ip_version_traffic_class_and_flow_label & 0xF0) ==
+                0x60);
            }
-         else
+
+         /* If not ipv6, we're done, go to next output feature */
+         if (PREDICT_FALSE (!is_ipv6))
            {
              next_node_index = get_next_output_feature_node_index (vnm, b0);
              goto dispatch0;
@@ -315,7 +332,7 @@ ipsec_output_node_fn (vlib_main_t * vm,
              next_node_index = im->esp_encrypt_node_index;
              vnet_buffer (b0)->output_features.ipsec_sad_index =
                p0->sa_index;
-             vlib_buffer_advance (b0, sizeof (ethernet_header_t));
+             vlib_buffer_advance (b0, iph_offset);
              p0->counter.packets++;
              if (is_ipv6)
                {