Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
Signed-off-by: giantcroc <changran.wang@intel.com>
  • Loading branch information
giantcroc committed Sep 26, 2022
1 parent 4c7e21f commit ff5c635
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 36 deletions.
23 changes: 17 additions & 6 deletions source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ UdpProxyFilter::UdpProxyFilter(Network::UdpReadFilterCallbacks& callbacks,
}

if (!config_->proxyAccessLogs().empty()) {
udp_proxy_stats_.emplace(
StreamInfo::StreamInfoImpl(config_->timeSource(), nullptr));
udp_proxy_stats_.emplace(StreamInfo::StreamInfoImpl(config_->timeSource(), nullptr));
}
}

UdpProxyFilter::~UdpProxyFilter(){
UdpProxyFilter::~UdpProxyFilter() {
if (!config_->proxyAccessLogs().empty()) {
fillProxyStreamInfo();
for (const auto& access_log : config_->proxyAccessLogs()) {
access_log->log(nullptr, nullptr, nullptr, udp_proxy_stats_.value());
}
}
}

void UdpProxyFilter::onClusterAddOrUpdate(Upstream::ThreadLocalCluster& cluster) {
auto cluster_name = cluster.info()->name();
ENVOY_LOG(debug, "udp proxy: attaching to cluster {}", cluster_name);
Expand Down Expand Up @@ -322,12 +322,23 @@ void UdpProxyFilter::ActiveSession::fillSessionStreamInfo() {
void UdpProxyFilter::fillProxyStreamInfo() {
ProtobufWkt::Struct stats_obj;
auto& fields_map = *stats_obj.mutable_fields();
fields_map["bytes_sent"] =
ValueUtil::numberValue(config_->stats().downstream_sess_tx_bytes_.value());
fields_map["bytes_received"] =
ValueUtil::numberValue(config_->stats().downstream_sess_rx_bytes_.value());
fields_map["errors_sent"] =
ValueUtil::numberValue(config_->stats().downstream_sess_tx_errors_.value());
fields_map["errors_received"] =
ValueUtil::numberValue(config_->stats().downstream_sess_rx_errors_.value());
fields_map["datagrams_sent"] =
ValueUtil::numberValue(config_->stats().downstream_sess_tx_datagrams_.value());
fields_map["datagrams_received"] =
ValueUtil::numberValue(config_->stats().downstream_sess_rx_datagrams_.value());
fields_map["no_route"] =
ValueUtil::numberValue(config_->stats().downstream_sess_no_route_.value());
fields_map["sess_total"] =
ValueUtil::numberValue(config_->stats().downstream_sess_total_.value());
fields_map["idle_timeout"] =
ValueUtil::numberValue(config_->stats().idle_timeout_.value());
ValueUtil::numberValue(config_->stats().downstream_sess_total_.value());
fields_map["idle_timeout"] = ValueUtil::numberValue(config_->stats().idle_timeout_.value());

udp_proxy_stats_.value().setDynamicMetadata("udp.proxy.proxy", stats_obj);
}
Expand Down
8 changes: 6 additions & 2 deletions source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,12 @@ class UdpProxyFilterConfig {
const Network::ResolvedUdpSocketConfig& upstreamSocketConfig() const {
return upstream_socket_config_;
}
const std::vector<AccessLog::InstanceSharedPtr>& sessionAccessLogs() const { return sess_access_logs_; }
const std::vector<AccessLog::InstanceSharedPtr>& proxyAccessLogs() const { return proxy_access_logs_; }
const std::vector<AccessLog::InstanceSharedPtr>& sessionAccessLogs() const {
return sess_access_logs_;
}
const std::vector<AccessLog::InstanceSharedPtr>& proxyAccessLogs() const {
return proxy_access_logs_;
}

private:
static UdpProxyDownstreamStats generateStats(const std::string& stat_prefix,
Expand Down
111 changes: 83 additions & 28 deletions test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ class UdpProxyFilterTest : public testing::Test {
peer_address_(std::move(peer_address)) {
// Disable strict mock warnings.
ON_CALL(*factory_context_.access_log_manager_.file_, write(_))
.WillByDefault(SaveArg<0>(&access_log_data_));
.WillByDefault(
Invoke([&](absl::string_view data) { output_.push_back(std::string(data)); }));
ON_CALL(os_sys_calls_, supportsIpTransparent()).WillByDefault(Return(true));
EXPECT_CALL(os_sys_calls_, supportsUdpGro()).Times(AtLeast(0)).WillRepeatedly(Return(true));
EXPECT_CALL(callbacks_, udpListener()).Times(AtLeast(0));
Expand Down Expand Up @@ -275,16 +276,31 @@ use_original_src_ip: true

// Return the config from yaml, plus one file access log with the specified format
envoy::extensions::filters::udp::udp_proxy::v3::UdpProxyConfig
accessLogConfig(const std::string& yaml, const std::string& access_log_format) {
accessLogConfig(const std::string& yaml, const std::string& sess_access_log_format,
const std::string& proxy_access_log_format) {
auto config = readConfig(yaml);

envoy::config::accesslog::v3::AccessLog* access_log = config.mutable_access_log()->Add();
access_log->set_name("envoy.access_loggers.file");
envoy::extensions::access_loggers::file::v3::FileAccessLog file_access_log;
file_access_log.set_path("unused");
file_access_log.mutable_log_format()->mutable_text_format_source()->set_inline_string(
access_log_format);
access_log->mutable_typed_config()->PackFrom(file_access_log);
if (!sess_access_log_format.empty()) {
envoy::config::accesslog::v3::AccessLog* sess_access_log =
config.mutable_sess_access_log()->Add();
sess_access_log->set_name("envoy.access_loggers.file");
envoy::extensions::access_loggers::file::v3::FileAccessLog sess_file_access_log;
sess_file_access_log.set_path("unused");
sess_file_access_log.mutable_log_format()->mutable_text_format_source()->set_inline_string(
sess_access_log_format);
sess_access_log->mutable_typed_config()->PackFrom(sess_file_access_log);
}

if (!proxy_access_log_format.empty()) {
envoy::config::accesslog::v3::AccessLog* proxy_access_log =
config.mutable_proxy_access_log()->Add();
proxy_access_log->set_name("envoy.access_loggers.file");
envoy::extensions::access_loggers::file::v3::FileAccessLog proxy_file_access_log;
proxy_file_access_log.set_path("unused");
proxy_file_access_log.mutable_log_format()->mutable_text_format_source()->set_inline_string(
proxy_access_log_format);
proxy_access_log->mutable_typed_config()->PackFrom(proxy_file_access_log);
}
return config;
}

Expand Down Expand Up @@ -314,6 +330,7 @@ use_original_src_ip: true
std::unique_ptr<TestUdpProxyFilter> filter_;
std::vector<TestSession> test_sessions_;
StringViewSaver access_log_data_;
std::vector<std::string> output_;
bool expect_gro_{};
const Network::Address::InstanceConstSharedPtr upstream_address_;
const Network::Address::InstanceConstSharedPtr peer_address_;
Expand Down Expand Up @@ -368,10 +385,20 @@ class UdpProxyFilterIpv4Ipv6Test : public UdpProxyFilterIpv6Test {
TEST_F(UdpProxyFilterTest, BasicFlow) {
InSequence s;

const std::string access_log_format = "%DYNAMIC_METADATA(udp.proxy:bytes_received)% "
"%DYNAMIC_METADATA(udp.proxy:datagrams_received)% "
"%DYNAMIC_METADATA(udp.proxy:bytes_sent)% "
"%DYNAMIC_METADATA(udp.proxy:datagrams_sent)%";
const std::string sess_access_log_format =
"%DYNAMIC_METADATA(udp.proxy.session:bytes_received)% "
"%DYNAMIC_METADATA(udp.proxy.session:datagrams_received)% "
"%DYNAMIC_METADATA(udp.proxy.session:bytes_sent)% "
"%DYNAMIC_METADATA(udp.proxy.session:datagrams_sent)%";

const std::string proxy_access_log_format =
"%DYNAMIC_METADATA(udp.proxy.proxy:bytes_received)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:datagrams_received)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:bytes_sent)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:datagrams_sent)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:no_route)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:sess_total)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:idle_timeout)%";

setup(accessLogConfig(R"EOF(
stat_prefix: foo
Expand All @@ -385,7 +412,7 @@ stat_prefix: foo
upstream_socket_config:
prefer_gro: false
)EOF",
access_log_format),
sess_access_log_format, proxy_access_log_format),
true, false);

expectSessionCreate(upstream_address_);
Expand All @@ -410,7 +437,9 @@ stat_prefix: foo
checkTransferStats(17 /*rx_bytes*/, 3 /*rx_datagrams*/, 17 /*tx_bytes*/, 3 /*tx_datagrams*/);

filter_.reset();
EXPECT_EQ(access_log_data_.value(), "17 3 17 3");
EXPECT_EQ(output_.size(), 2);
EXPECT_EQ(output_.front(), "17 3 17 3 0 1 0");
EXPECT_EQ(output_.back(), "17 3 17 3");
}

// Route with source IP.
Expand Down Expand Up @@ -460,7 +489,12 @@ stat_prefix: foo
TEST_F(UdpProxyFilterTest, IdleTimeout) {
InSequence s;

setup(readConfig(R"EOF(
const std::string sess_access_log_format = "";

const std::string proxy_access_log_format = "%DYNAMIC_METADATA(udp.proxy.proxy:sess_total)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:idle_timeout)%";

setup(accessLogConfig(R"EOF(
stat_prefix: foo
matcher:
on_no_match:
Expand All @@ -469,7 +503,8 @@ stat_prefix: foo
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route
cluster: fake_cluster
)EOF"));
)EOF",
sess_access_log_format, proxy_access_log_format));

expectSessionCreate(upstream_address_);
test_sessions_[0].expectWriteToUpstream("hello");
Expand All @@ -486,19 +521,28 @@ stat_prefix: foo
recvDataFromDownstream("10.0.0.1:1000", "10.0.0.2:80", "hello");
EXPECT_EQ(2, config_->stats().downstream_sess_total_.value());
EXPECT_EQ(1, config_->stats().downstream_sess_active_.value());

filter_.reset();
EXPECT_EQ(output_.size(), 1);
EXPECT_EQ(output_.front(), "2 1");
}

// Verify downstream send and receive error handling.
TEST_F(UdpProxyFilterTest, SendReceiveErrorHandling) {
InSequence s;

const std::string access_log_format = "%DYNAMIC_METADATA(udp.proxy:cluster_name)% "
"%DYNAMIC_METADATA(udp.proxy:bytes_sent)% "
"%DYNAMIC_METADATA(udp.proxy:bytes_received)% "
"%DYNAMIC_METADATA(udp.proxy:errors_sent)% "
"%DYNAMIC_METADATA(udp.proxy:errors_received)% "
"%DYNAMIC_METADATA(udp.proxy:datagrams_sent)% "
"%DYNAMIC_METADATA(udp.proxy:datagrams_received)%";
const std::string sess_access_log_format =
"%DYNAMIC_METADATA(udp.proxy.session:cluster_name)% "
"%DYNAMIC_METADATA(udp.proxy.session:bytes_sent)% "
"%DYNAMIC_METADATA(udp.proxy.session:bytes_received)% "
"%DYNAMIC_METADATA(udp.proxy.session:errors_sent)% "
"%DYNAMIC_METADATA(udp.proxy.session:errors_received)% "
"%DYNAMIC_METADATA(udp.proxy.session:datagrams_sent)% "
"%DYNAMIC_METADATA(udp.proxy.session:datagrams_received)%";

const std::string proxy_access_log_format = "%DYNAMIC_METADATA(udp.proxy.proxy:no_route)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:sess_total)% "
"%DYNAMIC_METADATA(udp.proxy.proxy:idle_timeout)%";

setup(accessLogConfig(R"EOF(
stat_prefix: foo
Expand All @@ -510,7 +554,7 @@ stat_prefix: foo
'@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route
cluster: fake_cluster
)EOF",
access_log_format));
sess_access_log_format, proxy_access_log_format));

filter_->onReceiveError(Api::IoError::IoErrorCode::UnknownError);
EXPECT_EQ(1, config_->stats().downstream_sess_rx_errors_.value());
Expand Down Expand Up @@ -550,7 +594,9 @@ stat_prefix: foo
->value());

filter_.reset();
EXPECT_EQ(access_log_data_.value(), "fake_cluster 0 10 1 1 0 2");
EXPECT_EQ(output_.size(), 2);
EXPECT_EQ(output_.front(), "0 1 0");
EXPECT_EQ(output_.back(), "fake_cluster 0 10 1 1 0 2");
}

// No upstream host handling.
Expand Down Expand Up @@ -579,7 +625,11 @@ stat_prefix: foo
TEST_F(UdpProxyFilterTest, NoUpstreamClusterAtCreation) {
InSequence s;

setup(readConfig(R"EOF(
const std::string sess_access_log_format = "";

const std::string proxy_access_log_format = "%DYNAMIC_METADATA(udp.proxy.proxy:no_route)%";

setup(accessLogConfig(R"EOF(
stat_prefix: foo
matcher:
on_no_match:
Expand All @@ -588,11 +638,16 @@ stat_prefix: foo
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route
cluster: fake_cluster
)EOF"),
)EOF",
sess_access_log_format, proxy_access_log_format),
false);

recvDataFromDownstream("10.0.0.1:1000", "10.0.0.2:80", "hello");
EXPECT_EQ(1, config_->stats().downstream_sess_no_route_.value());

filter_.reset();
EXPECT_EQ(output_.size(), 1);
EXPECT_EQ(output_.front(), "1");
}

// Dynamic cluster addition and removal handling.
Expand Down

0 comments on commit ff5c635

Please sign in to comment.