build: archive make install-ext-deps build logs in ci
[vpp.git] / src / vnet / ipsec / ipsec_spd_policy.c
index 5261621..af08768 100644 (file)
@@ -24,22 +24,6 @@ vlib_combined_counter_main_t ipsec_spd_policy_counters = {
   .stat_segment_name = "/net/ipsec/policy",
 };
 
-static int
-ipsec_spd_entry_sort (void *a1, void *a2)
-{
-  ipsec_main_t *im = &ipsec_main;
-  u32 *id1 = a1;
-  u32 *id2 = a2;
-  ipsec_policy_t *p1, *p2;
-
-  p1 = pool_elt_at_index (im->policies, *id1);
-  p2 = pool_elt_at_index (im->policies, *id2);
-  if (p1 && p2)
-    return p2->priority - p1->priority;
-
-  return 0;
-}
-
 int
 ipsec_policy_mk_type (bool is_outbound,
                      bool is_ipv6,
@@ -189,6 +173,7 @@ ipsec_add_del_policy (vlib_main_t * vm,
   if (is_add)
     {
       u32 policy_index;
+      u32 i;
 
       if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
        {
@@ -216,9 +201,20 @@ ipsec_add_del_policy (vlib_main_t * vm,
       vlib_validate_combined_counter (&ipsec_spd_policy_counters,
                                      policy_index);
       vlib_zero_combined_counter (&ipsec_spd_policy_counters, policy_index);
-      vec_add1 (spd->policies[policy->type], policy_index);
-      vec_sort_with_function (spd->policies[policy->type],
-                             ipsec_spd_entry_sort);
+
+      vec_foreach_index (i, spd->policies[policy->type])
+       {
+         ipsec_policy_t *p =
+           pool_elt_at_index (im->policies, spd->policies[policy->type][i]);
+
+         if (p->priority <= vp->priority)
+           {
+             break;
+           }
+       }
+
+      vec_insert_elts (spd->policies[policy->type], &policy_index, 1, i);
+
       *stat_index = policy_index;
     }
   else
@@ -382,7 +378,6 @@ ipsec_fp_get_policy_ports_mask (ipsec_policy_t *policy,
     }
 
   mask->protocol = (policy->protocol == IPSEC_POLICY_PROTOCOL_ANY) ? 0 : ~0;
-  mask->action = 0;
 }
 
 static_always_inline void
@@ -399,6 +394,15 @@ ipsec_fp_ip4_get_policy_mask (ipsec_policy_t *policy, ipsec_fp_5tuple_t *mask,
   clib_memset_u8 (mask, 0xff, sizeof (ipsec_fp_5tuple_t));
   clib_memset_u8 (&mask->l3_zero_pad, 0, sizeof (mask->l3_zero_pad));
 
+  if (inbound && (policy->type == IPSEC_SPD_POLICY_IP4_INBOUND_PROTECT &&
+                 policy->sa_index != INDEX_INVALID))
+    {
+      ipsec_sa_t *s = ipsec_sa_get (policy->sa_index);
+
+      if (ipsec_sa_is_set_IS_TUNNEL (s))
+       goto set_spi_mask;
+    }
+
   /* find bits where start != stop */
   *plmask = *pladdr_start ^ *pladdr_stop;
   *prmask = *praddr_start ^ *praddr_stop;
@@ -413,6 +417,7 @@ ipsec_fp_ip4_get_policy_mask (ipsec_policy_t *policy, ipsec_fp_5tuple_t *mask,
   *prmask = clib_host_to_net_u32 (
     mask_out_highest_set_bit_u32 (clib_net_to_host_u32 (*prmask)));
 
+set_spi_mask:
   if (inbound)
     {
       if (policy->type != IPSEC_SPD_POLICY_IP4_INBOUND_PROTECT)
@@ -440,6 +445,15 @@ ipsec_fp_ip6_get_policy_mask (ipsec_policy_t *policy, ipsec_fp_5tuple_t *mask,
 
   clib_memset_u8 (mask, 0xff, sizeof (ipsec_fp_5tuple_t));
 
+  if (inbound && (policy->type == IPSEC_SPD_POLICY_IP6_INBOUND_PROTECT &&
+                 policy->sa_index != INDEX_INVALID))
+    {
+      ipsec_sa_t *s = ipsec_sa_get (policy->sa_index);
+
+      if (ipsec_sa_is_set_IS_TUNNEL (s))
+       goto set_spi_mask;
+    }
+
   *plmask = (*pladdr_start++ ^ *pladdr_stop++);
 
   *prmask = (*praddr_start++ ^ *praddr_stop++);
@@ -466,16 +480,16 @@ ipsec_fp_ip6_get_policy_mask (ipsec_policy_t *policy, ipsec_fp_5tuple_t *mask,
 
   if (*prmask++ & clib_host_to_net_u64 (0x1))
     {
-      *prmask = (*pladdr_start ^ *pladdr_stop);
+      *prmask = (*praddr_start ^ *praddr_stop);
       *prmask = clib_host_to_net_u64 (
        mask_out_highest_set_bit_u64 (clib_net_to_host_u64 (*prmask)));
     }
   else
     *prmask = 0;
-
+set_spi_mask:
   if (inbound)
     {
-      if (policy->type != IPSEC_SPD_POLICY_IP4_INBOUND_PROTECT)
+      if (policy->type != IPSEC_SPD_POLICY_IP6_INBOUND_PROTECT)
        mask->spi = 0;
 
       mask->protocol = 0;
@@ -512,7 +526,21 @@ ipsec_fp_get_policy_5tuple (ipsec_policy_t *policy, ipsec_fp_5tuple_t *tuple,
          policy->sa_index != INDEX_INVALID)
        {
          ipsec_sa_t *s = ipsec_sa_get (policy->sa_index);
+
          tuple->spi = s->spi;
+         if (ipsec_sa_is_set_IS_TUNNEL (s))
+           {
+             if (tuple->is_ipv6)
+               {
+                 tuple->ip6_laddr = s->tunnel.t_dst.ip.ip6;
+                 tuple->ip6_raddr = s->tunnel.t_src.ip.ip6;
+               }
+             else
+               {
+                 tuple->laddr = s->tunnel.t_dst.ip.ip4;
+                 tuple->raddr = s->tunnel.t_src.ip.ip4;
+               }
+           }
        }
       else
        tuple->spi = INDEX_INVALID;
@@ -521,7 +549,6 @@ ipsec_fp_get_policy_5tuple (ipsec_policy_t *policy, ipsec_fp_5tuple_t *tuple,
     }
 
   tuple->protocol = policy->protocol;
-
   tuple->lport = policy->lport.start;
   tuple->rport = policy->rport.start;
 }
@@ -590,17 +617,24 @@ ipsec_fp_ip4_add_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
     }
   else
     {
+      u32 i;
+      u32 *old_fp_policies_ids = result_val->fp_policies_ids;
 
-      if (vec_max_len (result_val->fp_policies_ids) !=
-         vec_len (result_val->fp_policies_ids))
+      vec_foreach_index (i, result_val->fp_policies_ids)
        {
-         /* no need to resize */
-         vec_add1 (result_val->fp_policies_ids, policy_index);
+         ipsec_policy_t *p =
+           pool_elt_at_index (im->policies, result_val->fp_policies_ids[i]);
+
+         if (p->priority <= policy->priority)
+           {
+             break;
+           }
        }
-      else
-       {
-         vec_add1 (result_val->fp_policies_ids, policy_index);
 
+      vec_insert_elts (result_val->fp_policies_ids, &policy_index, 1, i);
+
+      if (result_val->fp_policies_ids != old_fp_policies_ids)
+       {
          res = clib_bihash_add_del_16_8 (bihash_table, &result, 1);
 
          if (res != 0)
@@ -626,7 +660,6 @@ ipsec_fp_ip4_add_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
     (fp_spd->fp_mask_ids[policy->type] + searched_idx)->refcount++;
 
   mte->refcount++;
-  vec_add1 (fp_spd->fp_policies[policy->type], policy_index);
   clib_memcpy (vp, policy, sizeof (*vp));
 
   return 0;
@@ -695,17 +728,24 @@ ipsec_fp_ip6_add_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
     }
   else
     {
+      u32 i;
+      u32 *old_fp_policies_ids = result_val->fp_policies_ids;
 
-      if (vec_max_len (result_val->fp_policies_ids) !=
-         vec_len (result_val->fp_policies_ids))
+      vec_foreach_index (i, result_val->fp_policies_ids)
        {
-         /* no need to resize */
-         vec_add1 (result_val->fp_policies_ids, policy_index);
+         ipsec_policy_t *p =
+           pool_elt_at_index (im->policies, result_val->fp_policies_ids[i]);
+
+         if (p->priority <= policy->priority)
+           {
+             break;
+           }
        }
-      else
-       {
-         vec_add1 (result_val->fp_policies_ids, policy_index);
 
+      vec_insert_elts (result_val->fp_policies_ids, &policy_index, 1, i);
+
+      if (result_val->fp_policies_ids != old_fp_policies_ids)
+       {
          res = clib_bihash_add_del_40_8 (bihash_table, &result, 1);
 
          if (res != 0)
@@ -731,7 +771,6 @@ ipsec_fp_ip6_add_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
     (fp_spd->fp_mask_ids[policy->type] + searched_idx)->refcount++;
 
   mte->refcount++;
-  vec_add1 (fp_spd->fp_policies[policy->type], policy_index);
   clib_memcpy (vp, policy, sizeof (*vp));
 
   return 0;
@@ -760,7 +799,7 @@ ipsec_fp_ip6_del_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
                                 fp_spd->ip6_out_lookup_hash_idx);
 
   ipsec_policy_t *vp;
-  u32 ii, iii, imt;
+  u32 ii, imt;
 
   ipsec_fp_ip6_get_policy_mask (policy, &mask, inbound);
   ipsec_fp_get_policy_5tuple (policy, &policy_5tuple, inbound);
@@ -769,57 +808,38 @@ ipsec_fp_ip6_del_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
   if (res != 0)
     return -1;
 
-  res = -1;
   vec_foreach_index (ii, result_val->fp_policies_ids)
     {
       vp =
        pool_elt_at_index (im->policies, *(result_val->fp_policies_ids + ii));
       if (ipsec_policy_is_equal (vp, policy))
        {
-         vec_foreach_index (iii, fp_spd->fp_policies[policy->type])
+         if (vec_len (result_val->fp_policies_ids) == 1)
+           {
+             vec_free (result_val->fp_policies_ids);
+             clib_bihash_add_del_40_8 (bihash_table, &result, 0);
+           }
+         else
+           vec_delete (result_val->fp_policies_ids, 1, ii);
+
+         vec_foreach_index (imt, fp_spd->fp_mask_ids[policy->type])
            {
-             if (*(fp_spd->fp_policies[policy->type] + iii) ==
-                 *(result_val->fp_policies_ids + ii))
+             if ((fp_spd->fp_mask_ids[policy->type] + imt)->mask_type_idx ==
+                 vp->fp_mask_type_id)
                {
-                 if (vec_len (result_val->fp_policies_ids) == 1)
-                   {
-                     vec_free (result_val->fp_policies_ids);
-                     clib_bihash_add_del_40_8 (bihash_table, &result, 0);
-                   }
-                 else
-                   {
-                     vec_del1 (result_val->fp_policies_ids, ii);
-                   }
-                 vec_del1 (fp_spd->fp_policies[policy->type], iii);
-
-                 vec_foreach_index (imt, fp_spd->fp_mask_ids[policy->type])
-                   {
-                     if ((fp_spd->fp_mask_ids[policy->type] + imt)
-                           ->mask_type_idx == vp->fp_mask_type_id)
-                       {
-
-                         if ((fp_spd->fp_mask_ids[policy->type] + imt)
-                               ->refcount-- == 1)
-                           vec_del1 (fp_spd->fp_mask_ids[policy->type], imt);
-
-                         break;
-                       }
-                   }
-
-                 res = 0;
+
+                 if ((fp_spd->fp_mask_ids[policy->type] + imt)->refcount-- ==
+                     1)
+                   vec_del1 (fp_spd->fp_mask_ids[policy->type], imt);
+
                  break;
                }
            }
 
-         if (res != 0)
-           continue;
-         else
-           {
-             ipsec_fp_release_mask_type (im, vp->fp_mask_type_id);
-             ipsec_sa_unlock (vp->sa_index);
-             pool_put (im->policies, vp);
-             return 0;
-           }
+         ipsec_fp_release_mask_type (im, vp->fp_mask_type_id);
+         ipsec_sa_unlock (vp->sa_index);
+         pool_put (im->policies, vp);
+         return 0;
        }
     }
   return -1;
@@ -837,7 +857,7 @@ ipsec_fp_ip4_del_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
     (ipsec_fp_lookup_value_t *) &result.value;
   bool inbound = ipsec_is_policy_inbound (policy);
   ipsec_policy_t *vp;
-  u32 ii, iii, imt;
+  u32 ii, imt;
   clib_bihash_16_8_t *bihash_table =
     inbound ? pool_elt_at_index (im->fp_ip4_lookup_hashes_pool,
                                 fp_spd->ip4_in_lookup_hash_idx) :
@@ -852,57 +872,37 @@ ipsec_fp_ip4_del_policy (ipsec_main_t *im, ipsec_spd_fp_t *fp_spd,
   if (res != 0)
     return -1;
 
-  res = -1;
   vec_foreach_index (ii, result_val->fp_policies_ids)
     {
       vp =
        pool_elt_at_index (im->policies, *(result_val->fp_policies_ids + ii));
       if (ipsec_policy_is_equal (vp, policy))
        {
-         vec_foreach_index (iii, fp_spd->fp_policies[policy->type])
+         if (vec_len (result_val->fp_policies_ids) == 1)
            {
-             if (*(fp_spd->fp_policies[policy->type] + iii) ==
-                 *(result_val->fp_policies_ids + ii))
-               {
-                 if (vec_len (result_val->fp_policies_ids) == 1)
-                   {
-                     vec_free (result_val->fp_policies_ids);
-                     clib_bihash_add_del_16_8 (bihash_table, &result, 0);
-                   }
-                 else
-                   {
-                     vec_del1 (result_val->fp_policies_ids, ii);
-                   }
-                 vec_del1 (fp_spd->fp_policies[policy->type], iii);
-
-                 vec_foreach_index (imt, fp_spd->fp_mask_ids[policy->type])
-                   {
-                     if ((fp_spd->fp_mask_ids[policy->type] + imt)
-                           ->mask_type_idx == vp->fp_mask_type_id)
-                       {
-
-                         if ((fp_spd->fp_mask_ids[policy->type] + imt)
-                               ->refcount-- == 1)
-                           vec_del1 (fp_spd->fp_mask_ids[policy->type], imt);
-
-                         break;
-                       }
-                   }
-
-                 res = 0;
-                 break;
-               }
+             vec_free (result_val->fp_policies_ids);
+             clib_bihash_add_del_16_8 (bihash_table, &result, 0);
            }
-
-         if (res != 0)
-           continue;
          else
+           vec_delete (result_val->fp_policies_ids, 1, ii);
+
+         vec_foreach_index (imt, fp_spd->fp_mask_ids[policy->type])
            {
-             ipsec_fp_release_mask_type (im, vp->fp_mask_type_id);
-             ipsec_sa_unlock (vp->sa_index);
-             pool_put (im->policies, vp);
-             return 0;
+             if ((fp_spd->fp_mask_ids[policy->type] + imt)->mask_type_idx ==
+                 vp->fp_mask_type_id)
+               {
+
+                 if ((fp_spd->fp_mask_ids[policy->type] + imt)->refcount-- ==
+                     1)
+                   vec_del1 (fp_spd->fp_mask_ids[policy->type], imt);
+
+                 break;
+               }
            }
+         ipsec_fp_release_mask_type (im, vp->fp_mask_type_id);
+         ipsec_sa_unlock (vp->sa_index);
+         pool_put (im->policies, vp);
+         return 0;
        }
     }
   return -1;