Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(bench): remove non-generic connection logic #4236

Merged
merged 8 commits into from
Oct 19, 2023

Conversation

jmayclin
Copy link
Contributor

@jmayclin jmayclin commented Oct 4, 2023

This commit shifts the TlsConnection trait to make it more generic. The purpose of this is to allow more general usage of the TlsConnection objects. In the future, "purpose-specific" logic will be implemented on the Config type rather than the connection type.

Description of changes:

Conceptually, a TlsConnection and a TlsConfig are very general items that needn't (and shouldn't) be aware of benchmark specific config. This PR introduces a new pattern where

  1. TlsConnection is general.
  2. TlsConfig is general.
  3. TlsConnections are created from configuration (TlsConfig)
  4. Specific configuration logic is implemented on the TlsConfig rather than the TlsConnection.
  5. When the ability to understand certain configuration is required (e.g. "I know how to understand benchamrking config") that is expressed as a bound on the associated type of the TlsConnection trait.

As an example of this logic, the following function is saying "implement the bench_handshake_for_library function over some generic type T, where T is a TlsConnection, and the Config for that TlsConnection can be created from my benchmark parameters.

This makes sense, because the benchmark handshake isn't just relying on being able to use a TlsConnection, it's relying on being able to create specifically configured TlsConnections. And that is best expressed as a trait on the Config.

fn bench_handshake_for_library<T>( // benchmark some type T
    bench_group: &mut BenchmarkGroup<WallTime>,
    bench_group: &mut BenchmarkGroup<WallTime>,
    handshake_type: HandshakeType,
    handshake_type: HandshakeType,
    kx_group: KXGroup,
    kx_group: KXGroup,
    sig_type: SigType,
    sig_type: SigType,
) {
) where
    T: TlsConnection, // where T is a connection
    T::Config: TlsBenchConfig, // and the config object knows about benchmarking configuration
{

Call-outs:

It does make the trait bounds more complicated, but given the goal of "generalize the traits" this seemed like the most readable way to do it.

Testing:

All tests still pass + CI check. Also need another review on #4210

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

This commit shifts the TlsConnection trait to make it more generic. The
purpose of this is to allow more general usage of the TlsConnection
objects. In the future, "purpose-specific" logic will be implemented on
the Config type rather than the connection type.
@jmayclin jmayclin requested a review from maddeleine October 4, 2023 21:51
@github-actions github-actions bot added the s2n-core team label Oct 4, 2023
@jmayclin jmayclin requested a review from toidiu October 4, 2023 21:52
@jmayclin jmayclin marked this pull request as ready for review October 6, 2023 17:11
Co-authored-by: maddeleine <59030281+maddeleine@users.noreply.github.com>
@jmayclin jmayclin requested a review from maddeleine October 16, 2023 16:52
@jmayclin jmayclin enabled auto-merge (squash) October 16, 2023 19:50
bindings/rust/bench/src/harness.rs Show resolved Hide resolved
bindings/rust/bench/src/harness.rs Outdated Show resolved Hide resolved
Comment on lines 154 to 159
/// The TlsConnection object can be created from a corresponding config type.
/// Any "purpose specific" config creation should be implemented on the config
/// rather than the connection to separate configuration vs implementation.
pub trait TlsConnection: Sized {
/// Library-specific config struct
type Config;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure what you mean by "purpose specific".

Also does it make sense to restrict Config: type Config: TlsConfig. Seems like you need that for it to be useful and you would be able to remove the bounds elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider a situation where I want do a self-talk test with s2n-tls security policies. In that case the only thing that I need to configure the connection is the security policy name. But then the current make_config method makes no sense.

fn make_config(
        mode: Mode,
        crypto_config: CryptoConfig,
        handshake_type: HandshakeType,
    ) -> Result<Self::Config, Box<dyn Error>>;

My "security policy self talk" test doesn't need to know about, or care about the crypto config. I have my own idea of how a connection should be configured.

Instead I could now implement a SecurityPolicySelfTalk trait on the S2nTls config object, which might just be something like

trait SecurityPolicySelfTalk {
    /// return a security policy with appropriately configured default certificates, 
    /// using the specified security policy.
    security_policy_config(sp: &str) -> Self
}

Then I can still use the handshake harnesses to actually drive the handshaking.

(this example is a bad one, but hopefully shows what I'm getting at)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also does it make sense to restrict Config: type Config: TlsConfig. Seems like you need that for it to be useful and you would be able to remove the bounds elsewhere.

Hmm. I'm not following. What is the TlsConfig trait that you are referring to? I don't want to require any specific functionality to be implemented on the Config object, because that forces you to implement that functionality on all of s2n-tls, rustls, and openssl. That might not always be logical or feasible.

More generally I want to push bounds down as far I can to avoid making the implementation unnecessarily restrictive.

bindings/rust/bench/src/harness.rs Show resolved Hide resolved
Co-authored-by: toidiu <apoorv@toidiu.com>
@jmayclin jmayclin requested a review from toidiu October 17, 2023 02:10
* the "purpose specific" comment was found to be confusing, remove it.
@jmayclin jmayclin merged commit dec039d into aws:main Oct 19, 2023
23 checks passed
@jmayclin jmayclin deleted the simplify-tls-trait branch December 22, 2023 01:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants