1
#include "source/common/network/hash_policy.h"
2

            
3
#include "envoy/common/exception.h"
4
#include "envoy/common/hashable.h"
5
#include "envoy/type/v3/hash_policy.pb.h"
6

            
7
#include "source/common/common/assert.h"
8

            
9
namespace Envoy {
10
namespace Network {
11

            
12
class SourceIpHashMethod : public HashPolicyImpl::HashMethod {
13
public:
14
2
  absl::optional<uint64_t> evaluate(const Network::Connection& connection) const override {
15
2
    const auto* downstream_addr = connection.connectionInfoProvider().remoteAddress().get();
16
2
    if (downstream_addr && downstream_addr->ip()) {
17
1
      ASSERT(!downstream_addr->ip()->addressAsString().empty());
18
1
      return HashUtil::xxHash64(downstream_addr->ip()->addressAsString());
19
1
    }
20

            
21
1
    return absl::nullopt;
22
2
  }
23
};
24

            
25
class FilterStateHashMethod : public HashPolicyImpl::HashMethod {
26
public:
27
2
  FilterStateHashMethod(absl::string_view key) : key_(key) {}
28

            
29
2
  absl::optional<uint64_t> evaluate(const Network::Connection& connection) const override {
30
2
    const auto& filter_state = connection.streamInfo().filterState();
31
2
    if (auto typed_state = filter_state.getDataReadOnly<Hashable>(key_); typed_state != nullptr) {
32
1
      return typed_state->hash();
33
1
    }
34
1
    return absl::nullopt;
35
2
  }
36

            
37
private:
38
  const std::string key_;
39
};
40

            
41
HashPolicyImpl::HashPolicyImpl(
42
4
    const absl::Span<const envoy::type::v3::HashPolicy* const>& hash_policies) {
43
4
  ASSERT(hash_policies.size() == 1);
44
4
  switch (hash_policies[0]->policy_specifier_case()) {
45
2
  case envoy::type::v3::HashPolicy::PolicySpecifierCase::kSourceIp:
46
2
    hash_impl_ = std::make_unique<SourceIpHashMethod>();
47
2
    break;
48
2
  case envoy::type::v3::HashPolicy::PolicySpecifierCase::kFilterState:
49
2
    hash_impl_ = std::make_unique<FilterStateHashMethod>(hash_policies[0]->filter_state().key());
50
2
    break;
51
  case envoy::type::v3::HashPolicy::PolicySpecifierCase::POLICY_SPECIFIER_NOT_SET:
52
    PANIC_DUE_TO_PROTO_UNSET;
53
4
  }
54
4
}
55

            
56
4
absl::optional<uint64_t> HashPolicyImpl::generateHash(const Network::Connection& connection) const {
57
4
  return hash_impl_->evaluate(connection);
58
4
}
59

            
60
} // namespace Network
61
} // namespace Envoy