vpp-swan: removed adding the same rule in SPD

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
This commit is contained in:
Gabriel Oginski
2023-02-03 08:12:36 +00:00
committed by Dave Wallace
parent 844a0e8b07
commit 8de66c090e

View 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;