summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c b/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c
index 3fe3c4403e2..2a0d86d7ef0 100644
--- a/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c
+++ b/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c
@@ -500,6 +500,22 @@ sa_equals (kernel_ipsec_sa_id_t *sa, kernel_ipsec_sa_id_t *other_sa)
}
/**
+ * 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
*/
static u_int
@@ -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;