ipsec: set l2_len for GRE-TEB tunnel decap
[vpp.git] / src / vnet / ipsec / esp_decrypt.c
index 16ae3a3..56724c0 100644 (file)
@@ -18,6 +18,7 @@
 #include <vnet/vnet.h>
 #include <vnet/api_errno.h>
 #include <vnet/ip/ip.h>
+#include <vnet/l2/l2_input.h>
 
 #include <vnet/ipsec/ipsec.h>
 #include <vnet/ipsec/esp.h>
@@ -53,6 +54,7 @@ typedef enum
  _(OVERSIZED_HEADER, "buffer with oversized header (dropped)")  \
  _(NO_TAIL_SPACE, "no enough buffer tail space (dropped)")      \
  _(TUN_NO_PROTO, "no tunnel protocol")                          \
+ _(UNSUP_PAYLOAD, "unsupported payload")                        \
 
 
 typedef enum
@@ -311,9 +313,10 @@ esp_decrypt_inline (vlib_main_t * vm,
       b += 1;
     }
 
-  vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
-                                  current_sa_index, current_sa_pkts,
-                                  current_sa_bytes);
+  if (PREDICT_TRUE (~0 != current_sa_index))
+    vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
+                                    current_sa_index, current_sa_pkts,
+                                    current_sa_bytes);
 
   if ((n = vec_len (ptd->integ_ops)))
     {
@@ -504,6 +507,7 @@ esp_decrypt_inline (vlib_main_t * vm,
                  switch (clib_net_to_host_u16 (gre->protocol))
                    {
                    case GRE_PROTOCOL_teb:
+                     vnet_update_l2_len (b[0]);
                      next[0] = ESP_DECRYPT_NEXT_L2_INPUT;
                      break;
                    case GRE_PROTOCOL_ip4:
@@ -513,6 +517,8 @@ esp_decrypt_inline (vlib_main_t * vm,
                      next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
                      break;
                    default:
+                     b[0]->error =
+                       node->errors[ESP_DECRYPT_ERROR_UNSUP_PAYLOAD];
                      next[0] = ESP_DECRYPT_NEXT_DROP;
                      break;
                    }
@@ -520,8 +526,7 @@ esp_decrypt_inline (vlib_main_t * vm,
              else
                {
                  next[0] = ESP_DECRYPT_NEXT_DROP;
-                 b[0]->error =
-                   node->errors[ESP_DECRYPT_ERROR_DECRYPTION_FAILED];
+                 b[0]->error = node->errors[ESP_DECRYPT_ERROR_UNSUP_PAYLOAD];
                  goto trace;
                }
            }
@@ -530,8 +535,20 @@ esp_decrypt_inline (vlib_main_t * vm,
              if (ipsec_sa_is_set_IS_PROTECT (sa0))
                {
                  /*
-                  * Check that the reveal IP header matches that
-                  * of the tunnel we are protecting
+                  * There are two encap possibilities
+                  * 1) the tunnel and ths SA are prodiving encap, i.e. it's
+                  *   MAC | SA-IP | TUN-IP | ESP | PAYLOAD
+                  * implying the SA is in tunnel mode (on a tunnel interface)
+                  * 2) only the tunnel provides encap
+                  *   MAC | TUN-IP | ESP | PAYLOAD
+                  * implying the SA is in transport mode.
+                  *
+                  * For 2) we need only strip the tunnel encap and we're good.
+                  *  since the tunnel and crypto ecnap (int the tun=protect
+                  * object) are the same and we verified above that these match
+                  * for 1) we need to strip the SA-IP outer headers, to
+                  * reveal the tunnel IP and then check that this matches
+                  * the configured tunnel.
                   */
                  const ipsec_tun_protect_t *itp;