child-sa: Add support for per-CPU SAs

The CPU ID is also set on inbound SAs as it can be used to configure RSS
or some eBPF program.
This commit is contained in:
Tobias Brunner 2021-05-11 17:55:21 +02:00
parent bdfcfea1f2
commit a505f4b9b0
7 changed files with 94 additions and 11 deletions

View File

@ -820,6 +820,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
child_sa_create_t data = {
.encap = ike_sa->has_condition(ike_sa, COND_NAT_ANY),
.cpu = CPU_ID_MAX,
};
child_sa = child_sa_create(ike_sa->get_my_host(ike_sa),
ike_sa->get_other_host(ike_sa), config, &data);

View File

@ -125,6 +125,7 @@ METHOD(listener_t, ike_updown, bool,
child_sa_create_t child = {
.if_id_in_def = ike_sa->get_if_id(ike_sa, TRUE),
.if_id_out_def = ike_sa->get_if_id(ike_sa, FALSE),
.cpu = CPU_ID_MAX,
};
INIT(entry,

View File

@ -181,6 +181,16 @@ struct private_child_sa_t {
*/
uint32_t if_id_out;
/**
* CPU ID to use for the outbound SA
*/
uint32_t cpu;
/**
* Whether to enable per-CPU feature for this SA
*/
bool per_cpu;
/**
* inbound mark used for this child_sa
*/
@ -834,6 +844,28 @@ METHOD(child_sa_t, set_acquire_seq, void,
this->seq = seq;
}
METHOD(child_sa_t, get_cpu, uint32_t,
private_child_sa_t *this)
{
return this->cpu;
}
METHOD(child_sa_t, use_per_cpu, bool,
private_child_sa_t *this)
{
return this->per_cpu;
}
METHOD(child_sa_t, set_per_cpu, void,
private_child_sa_t *this, bool per_cpu)
{
if (!per_cpu)
{
this->cpu = CPU_ID_MAX;
}
this->per_cpu = per_cpu;
}
METHOD(child_sa_t, get_lifetime, time_t,
private_child_sa_t *this, bool hard)
{
@ -1054,7 +1086,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
.ipcomp = this->ipcomp,
.cpi = cpi,
.encap = this->encap,
.cpu = CPU_ID_MAX,
.cpu = this->per_cpu ? this->cpu : CPU_ID_MAX,
.hw_offload = this->config->get_hw_offload(this->config),
.mark = this->config->get_set_mark(this->config, inbound),
.esn = esn,
@ -1101,12 +1133,25 @@ METHOD(child_sa_t, install, status_t,
}
/**
* Check kernel interface if policy updates are required
* Check whether to install policies for this CHILD_SA
*/
static bool require_policy_update()
static bool require_policies(private_child_sa_t *this)
{
return !this->config->has_option(this->config, OPT_NO_POLICIES);
}
/**
* Check if policy updates are required
*/
static bool require_policy_update(private_child_sa_t *this)
{
kernel_feature_t f;
if (!require_policies(this))
{
return FALSE;
}
f = charon->kernel->get_features(charon->kernel);
return !(f & KERNEL_NO_POLICY_UPDATES);
}
@ -1217,6 +1262,7 @@ static status_t install_policies_outbound(private_child_sa_t *this,
.hw_offload = this->config->get_hw_offload(this->config),
.src = my_addr,
.dst = other_addr,
.pcpu_acquires = this->per_cpu,
.sa = other_sa,
};
uint32_t reqid = other_sa->reqid;
@ -1330,6 +1376,7 @@ static void del_policies_outbound(private_child_sa_t *this,
.hw_offload = this->config->get_hw_offload(this->config),
.src = my_addr,
.dst = other_addr,
.pcpu_acquires = this->per_cpu,
.sa = other_sa,
};
uint32_t reqid = other_sa->reqid;
@ -1427,7 +1474,7 @@ METHOD(child_sa_t, install_policies, status_t,
this->outbound_state |= CHILD_OUTBOUND_POLICIES;
}
if (!this->config->has_option(this->config, OPT_NO_POLICIES))
if (require_policies(this))
{
policy_priority_t priority;
ipsec_sa_cfg_t my_sa, other_sa;
@ -1473,11 +1520,12 @@ METHOD(child_sa_t, install_policies, status_t,
*
* However, if we use labels with SELinux, we can't as we don't set SPIs
* on the policy in order to match SAs with other labels that match the generic
* label that's used on the policies.
* label that's used on the policies. The same is the case for per-CPU SAs.
*/
static bool install_outbound_immediately(private_child_sa_t *this)
{
if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI &&
!this->per_cpu)
{
if (this->config->get_label_mode(this->config) == SEC_LABEL_MODE_SELINUX)
{
@ -1538,7 +1586,7 @@ METHOD(child_sa_t, install_outbound, status_t,
{
return status;
}
if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
if (require_policies(this) &&
!(this->outbound_state & CHILD_OUTBOUND_POLICIES))
{
ipsec_sa_cfg_t my_sa, other_sa;
@ -1582,7 +1630,7 @@ METHOD(child_sa_t, remove_outbound, void,
return;
}
if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
if (require_policies(this) &&
(this->outbound_state & CHILD_OUTBOUND_POLICIES))
{
ipsec_sa_cfg_t my_sa, other_sa;
@ -1749,8 +1797,7 @@ METHOD(child_sa_t, update, status_t,
this->config->has_option(this->config,
OPT_PROXY_MODE);
if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
require_policy_update() && array_count(this->my_ts) &&
if (require_policy_update(this) && array_count(this->my_ts) &&
array_count(this->other_ts))
{
ipsec_sa_cfg_t my_sa, other_sa;
@ -1949,7 +1996,7 @@ METHOD(child_sa_t, destroy, void,
set_state(this, CHILD_DESTROYING);
if (!this->config->has_option(this->config, OPT_NO_POLICIES))
if (require_policies(this))
{
ipsec_sa_cfg_t my_sa, other_sa;
uint32_t manual_prio;
@ -2093,6 +2140,9 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
.get_mark = _get_mark,
.get_if_id = _get_if_id,
.get_label = _get_label,
.get_cpu = _get_cpu,
.set_per_cpu = _set_per_cpu,
.use_per_cpu = _use_per_cpu,
.get_acquire_seq = _get_acquire_seq,
.set_acquire_seq = _set_acquire_seq,
.has_encap = _has_encap,
@ -2133,6 +2183,8 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
.if_id_in = config->get_if_id(config, TRUE) ?: data->if_id_in_def,
.if_id_out = config->get_if_id(config, FALSE) ?: data->if_id_out_def,
.label = data->label ? data->label->clone(data->label) : NULL,
.cpu = data->cpu,
.per_cpu = data->per_cpu,
.seq = data->seq,
.install_time = time_monotonic(NULL),
.policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),

View File

@ -390,6 +390,28 @@ struct child_sa_t {
*/
sec_label_t *(*get_label)(child_sa_t *this);
/**
* Get the CPU ID used with this CHILD_SA.
*
* @return CPU used with this CHILD_SA
*/
uint32_t (*get_cpu)(child_sa_t *this);
/**
* Whether the per-CPU SA feature is enabled for this CHILD_SA.
*
* @return TRUE if per-CPU SA feature is enabled
*/
bool (*use_per_cpu)(child_sa_t *this);
/**
* Set whether the per-CPU SA feature is enabled for this CHILD_SA.
*
* @param per_cpu TRUE to enable per-CPU SA feature, FALSE also resets
* the CPU ID
*/
void (*set_per_cpu)(child_sa_t *this, bool per_cpu);
/**
* Get the optional sequence number associated with the acquire that
* triggered this CHILD_SA.
@ -575,6 +597,10 @@ struct child_sa_create_t {
uint32_t if_id_out_def;
/** Optional security label to apply on SAs (cloned) */
sec_label_t *label;
/** Optional CPU ID, CPU_ID_MAX if not specified */
uint32_t cpu;
/** Optional flag to enable per-CPU SA feature */
bool per_cpu;
/** Optional sequence number associated with the acquire that triggered
* this SA */
uint32_t seq;

View File

@ -1567,6 +1567,7 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
.abort = _abort_,
},
.child = {
.cpu = CPU_ID_MAX,
.seq = seq,
},
.ike_sa = ike_sa,

View File

@ -2833,6 +2833,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
},
},
.child = {
.cpu = CPU_ID_MAX,
.seq = seq,
},
.ike_sa = ike_sa,

View File

@ -349,6 +349,7 @@ METHOD(trap_manager_t, install, bool,
* pass them in a later initiate() call */
.if_id_in_def = peer->get_if_id(peer, TRUE),
.if_id_out_def = peer->get_if_id(peer, FALSE),
.cpu = CPU_ID_MAX,
};
child_sa = child_sa_create(me, other, child, &child_data);