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

http: make HeaderHashMethod hashing all the header values #15486

Merged
merged 27 commits into from
Apr 9, 2021

Conversation

soulxu
Copy link
Member

@soulxu soulxu commented Mar 15, 2021

Commit Message: http: make HeaderHashMethod hashing all the header values

Additional Description:
Previously the HeaderHashMehod only hash the first value of the header.
This PR aims to hash all the values of the header. The new behavior also can be
disabled by the new runtime guard envoy.reloadable_features.hash_multiple_header_values.

Risk Level: low
Testing: unit-test added
Docs Changes: n/a
Release Notes: add note for new feature
Fixes #15182

Signed-off-by: He Jie Xu hejie.xu@intel.com

Previously the HeaderHashMehod only hash the first value of header.
This commit aims to hash all the values of header.

Signed-off-by: He Jie Xu <hejie.xu@intel.com>
@soulxu soulxu changed the title Make HeaderHashMethod hashing all the header values http: make HeaderHashMethod hashing all the header values Mar 15, 2021
@jmarantz
Copy link
Contributor

One quick note: I see you force-pushed earlier. Please refrain from doing that for Envoy github reviews; it loses comment threads. Just "merge main".

Thank you!

@jmarantz jmarantz self-assigned this Mar 16, 2021
@soulxu
Copy link
Member Author

soulxu commented Mar 22, 2021

One quick note: I see you force-pushed earlier. Please refrain from doing that for Envoy github reviews; it loses comment threads. Just "merge main".

Thanks for the reminder. I already that from my first PR. Actually, I force update it since it is the first push and no other comments yet. I will keep that in mind in later update.

soulxu added 3 commits March 27, 2021 06:16
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
soulxu added 3 commits March 30, 2021 06:19
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

Code looks much better now, just a minor nit in the test remains.

test/common/router/config_impl_test.cc Outdated Show resolved Hide resolved
test/common/router/config_impl_test.cc Outdated Show resolved Hide resolved
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

Substantively LGTM. I think @snowp should look at this for its impact on load-balancing polices based on headers.

test/common/router/config_impl_test.cc Outdated Show resolved Hide resolved
test/common/router/config_impl_test.cc Outdated Show resolved Hide resolved
test/common/router/config_impl_test.cc Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
@jmarantz
Copy link
Contributor

Also I'm not sure what's up with CI. Can you merge main? Don't force-push.

soulxu added 2 commits March 31, 2021 16:01
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
@soulxu
Copy link
Member Author

soulxu commented Mar 31, 2021

Also I'm not sure what's up with CI. Can you merge main? Don't force-push.

Done

source/common/http/BUILD Outdated Show resolved Hide resolved
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
test/common/http/async_client_impl_test.cc Outdated Show resolved Hide resolved
test/common/http/async_client_impl_test.cc Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

Looks great; just a few comments.

static uint64_t xxHash64(absl::InlinedVector<absl::string_view, 1>& input, uint64_t seed = 0) {
uint64_t hash = seed;
if (input.size() == 0) {
hash = XXH64(input.data(), input.size(), hash);
Copy link
Contributor

Choose a reason for hiding this comment

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

does this case occur?

If so, just use XX64(nullptr, 0, seed)

Copy link
Contributor

Choose a reason for hiding this comment

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

Or maybe just don't test for that. Remove the if and let it return seed on an empty array.

Copy link
Member Author

@soulxu soulxu Apr 6, 2021

Choose a reason for hiding this comment

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

We didn't use that case when hashing the header value, special with the check num_headers_to_hash:

if (check_multiple_values && (num_headers_to_hash > 1)) {

I just match this behavior with static uint64_t xxHash64(absl::string_view input, uint64_t seed = 0) .
Then those two methods get the same value for empty string and empty vector, you can see that from the unittest

TEST(Hash, xxHash) {
EXPECT_EQ(3728699739546630719U, HashUtil::xxHash64("foo"));
EXPECT_EQ(5234164152756840025U, HashUtil::xxHash64("bar"));
EXPECT_EQ(8917841378505826757U, HashUtil::xxHash64("foo\nbar"));
EXPECT_EQ(4400747396090729504U, HashUtil::xxHash64("lyft"));
EXPECT_EQ(17241709254077376921U, HashUtil::xxHash64(""));
}
TEST(Hash, xxHashWithVector) {
absl::InlinedVector<absl::string_view, 1> v{"foo", "bar"};
EXPECT_EQ(17745830980996999794U, HashUtil::xxHash64(v));
absl::InlinedVector<absl::string_view, 1> empty_vector;
EXPECT_EQ(17241709254077376921U, HashUtil::xxHash64(empty_vector));
}

The upside to handle this empty vector case is in case someone pass the empty vector, then it will get a same behavior just like the empty string one.

But I'm also ok to remove it if you think it needless to a case we didn't use it today.

source/common/common/hash.h Outdated Show resolved Hide resolved
hash = XXH64(input.data(), input.size(), hash);
} else {
for (auto& i : input) {
hash = XXH64(i.data(), i.size(), hash);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice I hadn't thought of using the seed arg to XX64 as a carry.

source/common/common/hash.h Outdated Show resolved Hide resolved
}
}

if (check_multiple_values && (num_headers_to_hash > 1)) {
Copy link
Contributor

@jmarantz jmarantz Apr 6, 2021

Choose a reason for hiding this comment

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

I think Matt commented above but you don't need this conditional. num_headers_hash can be set to a value greater than one online if check_multiple_values is true, and the sorting will be a no-op for size==1.

Copy link
Member Author

Choose a reason for hiding this comment

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

that is what Matt is look for, better to have @mattklein123 check again. also I have comment about the runtime flag above, it may needn't this check anymore.

Copy link
Member

Choose a reason for hiding this comment

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

See my above comment. I think we do need the flag, but we can just set the size to 1 or not above and then we can collapse all of this logic.

Copy link
Member Author

Choose a reason for hiding this comment

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

I updated, hope I understand correctly.

test/common/http/async_client_impl_test.cc Outdated Show resolved Hide resolved
source/common/common/hash.h Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
}
}

if (check_multiple_values && (num_headers_to_hash > 1)) {
Copy link
Member

Choose a reason for hiding this comment

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

See my above comment. I think we do need the flag, but we can just set the size to 1 or not above and then we can collapse all of this logic.

Signed-off-by: He Jie Xu <hejie.xu@intel.com>
soulxu added 2 commits April 7, 2021 03:10
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
jmarantz
jmarantz previously approved these changes Apr 7, 2021
Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

Looks great, thank you! One tiny comment.

test/common/router/config_impl_test.cc Outdated Show resolved Hide resolved
source/common/common/hash.h Outdated Show resolved Hide resolved
source/common/common/hash.cc Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Outdated Show resolved Hide resolved
source/common/http/hash_policy.cc Show resolved Hide resolved
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
jmarantz
jmarantz previously approved these changes Apr 8, 2021
Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

Perfect, thanks!

@snowp can do a final pass.

Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Copy link
Contributor

@snowp snowp left a comment

Choose a reason for hiding this comment

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

LGTM!

Can you merge main to pick up a CI fix?

Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks LGTM. Will defer to others for merge.

@mattklein123 mattklein123 removed their assignment Apr 8, 2021
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
@soulxu
Copy link
Member Author

soulxu commented Apr 9, 2021

Thanks for all the review! just merged with main.

@snowp snowp merged commit 1f642ab into envoyproxy:main Apr 9, 2021
Monkeyanator pushed a commit to Monkeyanator/envoy that referenced this pull request Apr 20, 2021
…#15486)

Previously the HeaderHashMehod only hash the first value of header.
This commit aims to hash all the values of header.

Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

hash policy should look at all values of a header
4 participants