vpp-swan: removed adding the same rule in SPD 30/38130/2
authorGabriel Oginski <gabrielx.oginski@intel.com>
Fri, 3 Feb 2023 08:12:36 +0000 (08:12 +0000)
committerDave Wallace <dwallacelf@gmail.com>
Tue, 14 Feb 2023 01:20:34 +0000 (01:20 +0000)
The current implementation of vpp-swan plugin adds the same policy rule
in SPD twice, and it is not necessary to have two the same rules in
inbound-protect database.

This patch fixes an issue that prevents the addition of a second
identical policy rule in SPD.

Type: fix
Signed-off-by: Gabriel Oginski <gabrielx.oginski@intel.com>
Change-Id: Ieef74288e5301455658e4e101433147d6d2482e9

extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c

index 3fe3c44..2a0d86d 100644 (file)
@@ -499,6 +499,22 @@ sa_equals (kernel_ipsec_sa_id_t *sa, kernel_ipsec_sa_id_t *other_sa)
         sa->spi == other_sa->spi && sa->proto == other_sa->proto;
 }
 
+/**
+ * Equality function for policy SPD
+ */
+static bool
+policy_equals (vl_api_ipsec_spd_entry_t *policy,
+              vl_api_ipsec_spd_entry_t *other_policy)
+{
+
+  /* change protocol due to legacy implementation of ANY protocol inside VPP */
+  if (other_policy->protocol == 255)
+    other_policy->protocol = 0;
+
+  /* return true if both policies are equal */
+  return !memcmp (policy, other_policy, sizeof (*policy));
+}
+
 /**
  * Hash function for interface
  */
@@ -1111,6 +1127,49 @@ manage_policy (private_kernel_vpp_ipsec_t *this, bool add,
   mp->entry.remote_port_start = htons (id->dst_ts->get_from_port (id->dst_ts));
   mp->entry.remote_port_stop = htons (id->dst_ts->get_to_port (id->dst_ts));
 
+  /* check if policy exists in SPD */
+  vl_api_ipsec_spd_dump_t *mp_dump;
+  vl_api_ipsec_spd_details_t *rmp_dump, *tmp;
+
+  mp_dump = vl_msg_api_alloc (sizeof (*mp_dump));
+  memset (mp_dump, 0, sizeof (*mp_dump));
+
+  msg_id = vl_msg_api_get_msg_index ((u8 *) "ipsec_spd_dump_afefbf7d");
+  mp_dump->_vl_msg_id = htons (msg_id);
+  mp_dump->spd_id = htonl (spd->spd_id);
+  mp_dump->sa_id = htonl (sad_id);
+
+  if (vac->send_dump (vac, (char *) mp_dump, sizeof (*mp_dump), &out,
+                     &out_len))
+    {
+      DBG1 (DBG_KNL, "vac %s SPD lookup failed", add ? "adding" : "removing");
+      goto error;
+    }
+
+  int num = out_len / sizeof (*rmp_dump);
+  tmp = (void *) out;
+
+  /* found existing policy */
+  if (add && num)
+    {
+      int i;
+      for (i = 0; i < num; i++)
+       {
+         rmp_dump = tmp;
+         tmp += 1;
+         /* check if found entry equals the new one */
+         if (policy_equals (&mp->entry, &rmp_dump->entry))
+           goto next;
+       }
+    }
+  else if (!add && num == 0)
+    {
+      /* VPP doesn't have any policy to delete */
+      goto next;
+    }
+
+  free (out);
+
   if (vac->send (vac, (char *) mp, sizeof (*mp), &out, &out_len))
     {
       DBG1 (DBG_KNL, "vac %s SPD entry failed", add ? "adding" : "removing");
@@ -1124,6 +1183,7 @@ manage_policy (private_kernel_vpp_ipsec_t *this, bool add,
       goto error;
     }
 
+next:
   if (add)
     {
       ref_get (&spd->policy_num);
@@ -1153,6 +1213,7 @@ manage_policy (private_kernel_vpp_ipsec_t *this, bool add,
   rv = SUCCESS;
 error:
   free (out);
+  vl_msg_api_free (mp_dump);
   vl_msg_api_free (mp);
   this->mutex->unlock (this->mutex);
   return rv;