From: Tobias Brunner Date: Tue, 11 May 2021 15:55:21 +0000 (+0200) Subject: child-sa: Add support for per-CPU SAs X-Git-Tag: 6.0.2dr1~5^2~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a505f4b9b007c2fb8a86961d2e8e4513a19b4aed;p=thirdparty%2Fstrongswan.git 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. --- diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 5ef52546c7..e63a9a7260 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -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); diff --git a/src/libcharon/plugins/selinux/selinux_listener.c b/src/libcharon/plugins/selinux/selinux_listener.c index 396c4b042f..cb7c86f119 100644 --- a/src/libcharon/plugins/selinux/selinux_listener.c +++ b/src/libcharon/plugins/selinux/selinux_listener.c @@ -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, diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index a2bc49d2ca..d5c09c1dae 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -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_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() +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), diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h index 57d3458575..64e3df774c 100644 --- a/src/libcharon/sa/child_sa.h +++ b/src/libcharon/sa/child_sa.h @@ -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; diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index 686bc9ea96..a7c52c3526 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -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, diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index 534afb96c1..4c5a6fe099 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -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, diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c index 814c8c8c0a..0855e55172 100644 --- a/src/libcharon/sa/trap_manager.c +++ b/src/libcharon/sa/trap_manager.c @@ -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);