]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
child-sa: Add support for per-CPU SAs
authorTobias Brunner <tobias@strongswan.org>
Tue, 11 May 2021 15:55:21 +0000 (17:55 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 28 May 2025 14:35:26 +0000 (16:35 +0200)
The CPU ID is also set on inbound SAs as it can be used to configure RSS
or some eBPF program.

src/libcharon/plugins/ha/ha_dispatcher.c
src/libcharon/plugins/selinux/selinux_listener.c
src/libcharon/sa/child_sa.c
src/libcharon/sa/child_sa.h
src/libcharon/sa/ikev1/tasks/quick_mode.c
src/libcharon/sa/ikev2/tasks/child_create.c
src/libcharon/sa/trap_manager.c

index 5ef52546c7f6c14daece9df2dcc74e5708ad8ecb..e63a9a72609ac96bda520cff2d28cdebf5dfb654 100644 (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);
index 396c4b042fb20004033da84935b7bd44b3aab218..cb7c86f119e26315690ca7398f22a2cdfcdbe7e2 100644 (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,
index a2bc49d2cad9d64690e0b2a4222dcd67de40c966..d5c09c1dae7bd0aeff074f19767e372034532a99 100644 (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_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),
index 57d3458575c448020a15c9cf6f8f42a68b0485fd..64e3df774cd394048365e96dde244b0dceb3a55b 100644 (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;
index 686bc9ea965e99f6bd40c08fffd5102bce18d3c4..a7c52c35264debd292f7fdcc017f0fd657fda724 100644 (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,
index 534afb96c1ae7f5d7ac2aab50ee851ba9e90e5d9..4c5a6fe0992c015cc764335ccd1d3d407d904136 100644 (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,
index 814c8c8c0ae6024bb987d27dde81ecded81df5e7..0855e5517200f703b9647467712c288f62e86e41 100644 (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);