diff --git a/BUILD b/BUILD
index 2daac9131ea..778b365ff04 100644
--- a/BUILD
+++ b/BUILD
@@ -1375,6 +1375,7 @@ grpc_cc_library(
"src/core/ext/xds/xds_certificate_provider.cc",
"src/core/ext/xds/xds_client.cc",
"src/core/ext/xds/xds_client_stats.cc",
+ "src/core/ext/xds/xds_http_filters.cc",
"src/core/lib/security/credentials/xds/xds_credentials.cc",
],
hdrs = [
@@ -1388,6 +1389,7 @@ grpc_cc_library(
"src/core/ext/xds/xds_channel_args.h",
"src/core/ext/xds/xds_client.h",
"src/core/ext/xds/xds_client_stats.h",
+ "src/core/ext/xds/xds_http_filters.h",
"src/core/lib/security/credentials/xds/xds_credentials.h",
],
external_deps = [
@@ -1405,6 +1407,8 @@ grpc_cc_library(
"grpc_client_channel",
"grpc_secure",
"grpc_transport_chttp2_client_secure",
+ "udpa_type_upb",
+ "udpa_type_upbdefs",
],
)
@@ -2646,6 +2650,7 @@ grpc_cc_library(
"src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c",
"src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c",
"src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c",
+ "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c",
"src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c",
"src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c",
"src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c",
@@ -2679,6 +2684,7 @@ grpc_cc_library(
"src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h",
"src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h",
"src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h",
+ "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h",
"src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h",
"src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h",
"src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h",
@@ -2729,6 +2735,7 @@ grpc_cc_library(
"src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c",
"src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c",
"src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c",
+ "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c",
"src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c",
"src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c",
"src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c",
@@ -2761,6 +2768,7 @@ grpc_cc_library(
"src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h",
+ "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.h",
@@ -3193,6 +3201,45 @@ grpc_cc_library(
],
)
+grpc_cc_library(
+ name = "udpa_type_upb",
+ srcs = [
+ "src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c",
+ ],
+ hdrs = [
+ "src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h",
+ ],
+ external_deps = [
+ "upb_lib",
+ "upb_lib_descriptor",
+ ],
+ language = "c++",
+ deps = [
+ ":google_api_upb",
+ ":proto_gen_validate_upb",
+ ],
+)
+
+grpc_cc_library(
+ name = "udpa_type_upbdefs",
+ srcs = [
+ "src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c",
+ ],
+ hdrs = [
+ "src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h",
+ ],
+ external_deps = [
+ "upb_lib",
+ "upb_lib_descriptor_reflection",
+ "upb_textformat_lib",
+ ],
+ language = "c++",
+ deps = [
+ ":google_api_upbdefs",
+ ":proto_gen_validate_upbdefs",
+ ],
+)
+
# Once upb code-gen issue is resolved, replace grpc_health_upb with this.
# grpc_upb_proto_library(
# name = "grpc_health_upb",
diff --git a/BUILD.gn b/BUILD.gn
index 42d09d4f16c..ddaeda86644 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -462,6 +462,8 @@ config("grpc_config") {
"src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h",
"src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c",
"src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h",
+ "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c",
+ "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h",
"src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c",
"src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h",
"src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c",
@@ -556,6 +558,8 @@ config("grpc_config") {
"src/core/ext/upb-generated/udpa/annotations/versioning.upb.h",
"src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c",
"src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h",
+ "src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c",
+ "src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h",
"src/core/ext/upb-generated/validate/validate.upb.c",
"src/core/ext/upb-generated/validate/validate.upb.h",
"src/core/ext/upb-generated/xds/core/v3/authority.upb.c",
@@ -634,6 +638,8 @@ config("grpc_config") {
"src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c",
"src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h",
+ "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c",
+ "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c",
"src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h",
"src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c",
@@ -712,6 +718,8 @@ config("grpc_config") {
"src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h",
"src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c",
"src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h",
+ "src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c",
+ "src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h",
"src/core/ext/upbdefs-generated/validate/validate.upbdefs.c",
"src/core/ext/upbdefs-generated/validate/validate.upbdefs.h",
"src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c",
@@ -744,6 +752,8 @@ config("grpc_config") {
"src/core/ext/xds/xds_client.h",
"src/core/ext/xds/xds_client_stats.cc",
"src/core/ext/xds/xds_client_stats.h",
+ "src/core/ext/xds/xds_http_filters.cc",
+ "src/core/ext/xds/xds_http_filters.h",
"src/core/ext/xds/xds_server_config_fetcher.cc",
"src/core/lib/avl/avl.cc",
"src/core/lib/avl/avl.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f4eb3b63967..650d9a9976e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -502,6 +502,9 @@ protobuf_generate_grpc_cpp(
protobuf_generate_grpc_cpp(
src/proto/grpc/testing/xds/v3/route.proto
)
+protobuf_generate_grpc_cpp(
+ src/proto/grpc/testing/xds/v3/router.proto
+)
protobuf_generate_grpc_cpp(
src/proto/grpc/testing/xds/v3/string.proto
)
@@ -1589,6 +1592,7 @@ add_library(grpc
src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c
src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c
+ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c
@@ -1636,6 +1640,7 @@ add_library(grpc
src/core/ext/upb-generated/udpa/annotations/status.upb.c
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
+ src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c
src/core/ext/upb-generated/validate/validate.upb.c
src/core/ext/upb-generated/xds/core/v3/authority.upb.c
src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c
@@ -1675,6 +1680,7 @@ add_library(grpc
src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c
src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c
+ src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c
@@ -1714,6 +1720,7 @@ add_library(grpc
src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c
+ src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c
src/core/ext/upbdefs-generated/validate/validate.upbdefs.c
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c
src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c
@@ -1729,6 +1736,7 @@ add_library(grpc
src/core/ext/xds/xds_certificate_provider.cc
src/core/ext/xds/xds_client.cc
src/core/ext/xds/xds_client_stats.cc
+ src/core/ext/xds/xds_http_filters.cc
src/core/ext/xds/xds_server_config_fetcher.cc
src/core/lib/avl/avl.cc
src/core/lib/backoff/backoff.cc
@@ -15710,6 +15718,10 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/route.grpc.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.cc
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.pb.h
+ ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/router.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.h
diff --git a/Makefile b/Makefile
index c8b6037044b..0d270f97ab6 100644
--- a/Makefile
+++ b/Makefile
@@ -1172,6 +1172,7 @@ LIBGRPC_SRC = \
src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c \
src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c \
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c \
+ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c \
@@ -1219,6 +1220,7 @@ LIBGRPC_SRC = \
src/core/ext/upb-generated/udpa/annotations/status.upb.c \
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
+ src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c \
@@ -1258,6 +1260,7 @@ LIBGRPC_SRC = \
src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \
+ src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c \
@@ -1297,6 +1300,7 @@ LIBGRPC_SRC = \
src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
+ src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c \
@@ -1312,6 +1316,7 @@ LIBGRPC_SRC = \
src/core/ext/xds/xds_certificate_provider.cc \
src/core/ext/xds/xds_client.cc \
src/core/ext/xds/xds_client_stats.cc \
+ src/core/ext/xds/xds_http_filters.cc \
src/core/ext/xds/xds_server_config_fetcher.cc \
src/core/lib/avl/avl.cc \
src/core/lib/backoff/backoff.cc \
@@ -2698,6 +2703,7 @@ src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c: $(OPENS
src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c: $(OPENSSL_DEP)
+src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c: $(OPENSSL_DEP)
@@ -2731,6 +2737,7 @@ src/core/ext/upb-generated/udpa/annotations/security.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/status.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c: $(OPENSSL_DEP)
+src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/xds/core/v3/authority.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/xds/core/v3/context_params.upb.c: $(OPENSSL_DEP)
@@ -2769,6 +2776,7 @@ src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c:
src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c: $(OPENSSL_DEP)
+src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c: $(OPENSSL_DEP)
@@ -2808,6 +2816,7 @@ src/core/ext/upbdefs-generated/udpa/annotations/security.upbdefs.c: $(OPENSSL_DE
src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c: $(OPENSSL_DEP)
+src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/validate/validate.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c: $(OPENSSL_DEP)
src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c: $(OPENSSL_DEP)
@@ -2823,6 +2832,7 @@ src/core/ext/xds/xds_bootstrap.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_certificate_provider.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_client.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_client_stats.cc: $(OPENSSL_DEP)
+src/core/ext/xds/xds_http_filters.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_server_config_fetcher.cc: $(OPENSSL_DEP)
src/core/lib/http/httpcli_security_connector.cc: $(OPENSSL_DEP)
src/core/lib/security/authorization/authorization_engine.cc: $(OPENSSL_DEP)
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index 11573c2545d..b704e8f58c6 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -500,6 +500,7 @@ libs:
- src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h
- src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h
- src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h
+ - src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h
- src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h
- src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h
- src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h
@@ -547,6 +548,7 @@ libs:
- src/core/ext/upb-generated/udpa/annotations/status.upb.h
- src/core/ext/upb-generated/udpa/annotations/versioning.upb.h
- src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
+ - src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h
- src/core/ext/upb-generated/validate/validate.upb.h
- src/core/ext/upb-generated/xds/core/v3/authority.upb.h
- src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h
@@ -586,6 +588,7 @@ libs:
- src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h
- src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h
- src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h
+ - src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h
- src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h
- src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h
- src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.h
@@ -625,6 +628,7 @@ libs:
- src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h
- src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h
- src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h
+ - src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h
- src/core/ext/upbdefs-generated/validate/validate.upbdefs.h
- src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h
- src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h
@@ -642,6 +646,7 @@ libs:
- src/core/ext/xds/xds_channel_args.h
- src/core/ext/xds/xds_client.h
- src/core/ext/xds/xds_client_stats.h
+ - src/core/ext/xds/xds_http_filters.h
- src/core/lib/avl/avl.h
- src/core/lib/backoff/backoff.h
- src/core/lib/channel/channel_args.h
@@ -1006,6 +1011,7 @@ libs:
- src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c
- src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c
- src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c
+ - src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c
- src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c
- src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c
- src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c
@@ -1053,6 +1059,7 @@ libs:
- src/core/ext/upb-generated/udpa/annotations/status.upb.c
- src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
- src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
+ - src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c
- src/core/ext/upb-generated/validate/validate.upb.c
- src/core/ext/upb-generated/xds/core/v3/authority.upb.c
- src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c
@@ -1092,6 +1099,7 @@ libs:
- src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c
- src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c
- src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c
+ - src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c
- src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c
- src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c
- src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c
@@ -1131,6 +1139,7 @@ libs:
- src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c
- src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c
- src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c
+ - src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c
- src/core/ext/upbdefs-generated/validate/validate.upbdefs.c
- src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c
- src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c
@@ -1146,6 +1155,7 @@ libs:
- src/core/ext/xds/xds_certificate_provider.cc
- src/core/ext/xds/xds_client.cc
- src/core/ext/xds/xds_client_stats.cc
+ - src/core/ext/xds/xds_http_filters.cc
- src/core/ext/xds/xds_server_config_fetcher.cc
- src/core/lib/avl/avl.cc
- src/core/lib/backoff/backoff.cc
@@ -8020,6 +8030,7 @@ targets:
- src/proto/grpc/testing/xds/v3/range.proto
- src/proto/grpc/testing/xds/v3/regex.proto
- src/proto/grpc/testing/xds/v3/route.proto
+ - src/proto/grpc/testing/xds/v3/router.proto
- src/proto/grpc/testing/xds/v3/string.proto
- src/proto/grpc/testing/xds/v3/tls.proto
- test/cpp/end2end/test_service_impl.cc
diff --git a/config.m4 b/config.m4
index cc6a6b1048b..fa847df36eb 100644
--- a/config.m4
+++ b/config.m4
@@ -177,6 +177,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c \
src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c \
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c \
+ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c \
@@ -225,6 +226,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upb-generated/udpa/annotations/status.upb.c \
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
+ src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c \
@@ -264,6 +266,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \
+ src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c \
@@ -304,6 +307,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
+ src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c \
@@ -319,6 +323,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/xds/xds_certificate_provider.cc \
src/core/ext/xds/xds_client.cc \
src/core/ext/xds/xds_client_stats.cc \
+ src/core/ext/xds/xds_http_filters.cc \
src/core/ext/xds/xds_server_config_fetcher.cc \
src/core/lib/avl/avl.cc \
src/core/lib/backoff/backoff.cc \
@@ -1053,6 +1058,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/route/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/trace/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3)
+ PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/cluster/v3)
@@ -1074,6 +1080,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/src/proto/grpc/lb/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/annotations)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/data/orca/v1)
+ PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/type/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/validate)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/core/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/annotations)
@@ -1085,6 +1092,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/route/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/trace/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3)
+ PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/cluster/v3)
@@ -1101,6 +1109,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/protobuf)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/google/rpc)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/udpa/annotations)
+ PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/udpa/type/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/validate)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/core/v3)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/xds)
diff --git a/config.w32 b/config.w32
index 03662fc78a1..d45a565d962 100644
--- a/config.w32
+++ b/config.w32
@@ -144,6 +144,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upb-generated\\envoy\\config\\route\\v3\\scoped_route.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\config\\trace\\v3\\http_tracer.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\clusters\\aggregate\\v3\\cluster.upb.c " +
+ "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\router\\v3\\router.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3\\http_connection_manager.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\cert.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\common.upb.c " +
@@ -192,6 +193,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upb-generated\\udpa\\annotations\\status.upb.c " +
"src\\core\\ext\\upb-generated\\udpa\\annotations\\versioning.upb.c " +
"src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1\\orca_load_report.upb.c " +
+ "src\\core\\ext\\upb-generated\\udpa\\type\\v1\\typed_struct.upb.c " +
"src\\core\\ext\\upb-generated\\validate\\validate.upb.c " +
"src\\core\\ext\\upb-generated\\xds\\core\\v3\\authority.upb.c " +
"src\\core\\ext\\upb-generated\\xds\\core\\v3\\collection_entry.upb.c " +
@@ -231,6 +233,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upbdefs-generated\\envoy\\config\\route\\v3\\scoped_route.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\envoy\\config\\trace\\v3\\http_tracer.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\clusters\\aggregate\\v3\\cluster.upbdefs.c " +
+ "src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\router\\v3\\router.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3\\http_connection_manager.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\cert.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\common.upbdefs.c " +
@@ -271,6 +274,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\sensitive.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\status.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\udpa\\annotations\\versioning.upbdefs.c " +
+ "src\\core\\ext\\upbdefs-generated\\udpa\\type\\v1\\typed_struct.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\validate\\validate.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\authority.upbdefs.c " +
"src\\core\\ext\\upbdefs-generated\\xds\\core\\v3\\collection_entry.upbdefs.c " +
@@ -286,6 +290,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\xds\\xds_certificate_provider.cc " +
"src\\core\\ext\\xds\\xds_client.cc " +
"src\\core\\ext\\xds\\xds_client_stats.cc " +
+ "src\\core\\ext\\xds\\xds_http_filters.cc " +
"src\\core\\ext\\xds\\xds_server_config_fetcher.cc " +
"src\\core\\lib\\avl\\avl.cc " +
"src\\core\\lib\\backoff\\backoff.cc " +
@@ -1071,6 +1076,9 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\clusters\\aggregate");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\clusters\\aggregate\\v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\router");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\router\\v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network\\http_connection_manager");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3");
@@ -1117,6 +1125,8 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\data");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\data\\orca");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\type");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\udpa\\type\\v1");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\validate");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\core");
@@ -1144,6 +1154,9 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\clusters\\aggregate");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\clusters\\aggregate\\v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\router");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\router\\v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\network");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\network\\http_connection_manager");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3");
@@ -1177,6 +1190,8 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\google\\rpc");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa\\annotations");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa\\type");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\udpa\\type\\v1");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\validate");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\core");
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index 61f45bb0a25..69f5b8290e0 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -315,6 +315,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h',
'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h',
'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h',
'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h',
@@ -363,6 +364,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
+ 'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/upb-generated/xds/core/v3/authority.upb.h',
'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h',
@@ -402,6 +404,7 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.h',
@@ -442,6 +445,7 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h',
'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h',
'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h',
@@ -459,6 +463,7 @@ Pod::Spec.new do |s|
'src/core/ext/xds/xds_channel_args.h',
'src/core/ext/xds/xds_client.h',
'src/core/ext/xds/xds_client_stats.h',
+ 'src/core/ext/xds/xds_http_filters.h',
'src/core/lib/avl/avl.h',
'src/core/lib/backoff/backoff.h',
'src/core/lib/channel/channel_args.h',
@@ -936,6 +941,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h',
'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h',
'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h',
'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h',
@@ -984,6 +990,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
+ 'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/upb-generated/xds/core/v3/authority.upb.h',
'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h',
@@ -1023,6 +1030,7 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.h',
@@ -1063,6 +1071,7 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h',
'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h',
'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h',
@@ -1080,6 +1089,7 @@ Pod::Spec.new do |s|
'src/core/ext/xds/xds_channel_args.h',
'src/core/ext/xds/xds_client.h',
'src/core/ext/xds/xds_client_stats.h',
+ 'src/core/ext/xds/xds_http_filters.h',
'src/core/lib/avl/avl.h',
'src/core/lib/backoff/backoff.h',
'src/core/lib/channel/channel_args.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 57b0e194884..91aebaa6dd6 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -442,6 +442,8 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h',
'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c',
'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c',
+ 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h',
'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c',
'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c',
@@ -538,6 +540,8 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
+ 'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c',
+ 'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/upb-generated/xds/core/v3/authority.upb.c',
@@ -616,6 +620,8 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c',
+ 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c',
@@ -696,6 +702,8 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c',
'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c',
+ 'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
'src/core/ext/upbdefs-generated/validate/validate.upbdefs.c',
'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c',
@@ -728,6 +736,8 @@ Pod::Spec.new do |s|
'src/core/ext/xds/xds_client.h',
'src/core/ext/xds/xds_client_stats.cc',
'src/core/ext/xds/xds_client_stats.h',
+ 'src/core/ext/xds/xds_http_filters.cc',
+ 'src/core/ext/xds/xds_http_filters.h',
'src/core/ext/xds/xds_server_config_fetcher.cc',
'src/core/lib/avl/avl.cc',
'src/core/lib/avl/avl.h',
@@ -1472,6 +1482,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h',
'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h',
'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h',
+ 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h',
'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h',
@@ -1520,6 +1531,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.h',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
+ 'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h',
'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/upb-generated/xds/core/v3/authority.upb.h',
'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.h',
@@ -1559,6 +1571,7 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.h',
@@ -1599,6 +1612,7 @@ Pod::Spec.new do |s|
'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.h',
'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h',
'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h',
+ 'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h',
'src/core/ext/upbdefs-generated/validate/validate.upbdefs.h',
'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.h',
'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.h',
@@ -1616,6 +1630,7 @@ Pod::Spec.new do |s|
'src/core/ext/xds/xds_channel_args.h',
'src/core/ext/xds/xds_client.h',
'src/core/ext/xds/xds_client_stats.h',
+ 'src/core/ext/xds/xds_http_filters.h',
'src/core/lib/avl/avl.h',
'src/core/lib/backoff/backoff.h',
'src/core/lib/channel/channel_args.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 5c3d0a5ccad..f5065a5d22d 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -357,6 +357,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h )
+ s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c )
+ s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h )
s.files += %w( src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c )
@@ -453,6 +455,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upb-generated/udpa/annotations/versioning.upb.h )
s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c )
s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h )
+ s.files += %w( src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c )
+ s.files += %w( src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h )
s.files += %w( src/core/ext/upb-generated/validate/validate.upb.c )
s.files += %w( src/core/ext/upb-generated/validate/validate.upb.h )
s.files += %w( src/core/ext/upb-generated/xds/core/v3/authority.upb.c )
@@ -531,6 +535,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h )
s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c )
s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h )
+ s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c )
+ s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h )
s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c )
s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h )
s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c )
@@ -611,6 +617,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h )
s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c )
s.files += %w( src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h )
+ s.files += %w( src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c )
+ s.files += %w( src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h )
s.files += %w( src/core/ext/upbdefs-generated/validate/validate.upbdefs.c )
s.files += %w( src/core/ext/upbdefs-generated/validate/validate.upbdefs.h )
s.files += %w( src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c )
@@ -643,6 +651,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/xds/xds_client.h )
s.files += %w( src/core/ext/xds/xds_client_stats.cc )
s.files += %w( src/core/ext/xds/xds_client_stats.h )
+ s.files += %w( src/core/ext/xds/xds_http_filters.cc )
+ s.files += %w( src/core/ext/xds/xds_http_filters.h )
s.files += %w( src/core/ext/xds/xds_server_config_fetcher.cc )
s.files += %w( src/core/lib/avl/avl.cc )
s.files += %w( src/core/lib/avl/avl.h )
diff --git a/grpc.gyp b/grpc.gyp
index 06527d923a6..15b2d727c38 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -591,6 +591,7 @@
'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c',
'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c',
'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c',
+ 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c',
'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c',
@@ -638,6 +639,7 @@
'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
+ 'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.c',
'src/core/ext/upb-generated/xds/core/v3/authority.upb.c',
'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c',
@@ -677,6 +679,7 @@
'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c',
+ 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c',
@@ -716,6 +719,7 @@
'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c',
'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c',
'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c',
+ 'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c',
'src/core/ext/upbdefs-generated/validate/validate.upbdefs.c',
'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c',
'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c',
@@ -731,6 +735,7 @@
'src/core/ext/xds/xds_certificate_provider.cc',
'src/core/ext/xds/xds_client.cc',
'src/core/ext/xds/xds_client_stats.cc',
+ 'src/core/ext/xds/xds_http_filters.cc',
'src/core/ext/xds/xds_server_config_fetcher.cc',
'src/core/lib/avl/avl.cc',
'src/core/lib/backoff/backoff.cc',
diff --git a/package.xml b/package.xml
index 4368ed9d9e3..56873582e2f 100644
--- a/package.xml
+++ b/package.xml
@@ -337,6 +337,8 @@
+
+
@@ -433,6 +435,8 @@
+
+
@@ -511,6 +515,8 @@
+
+
@@ -591,6 +597,8 @@
+
+
@@ -623,6 +631,8 @@
+
+
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 1171f38aa74..455e1460c4f 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -2297,7 +2297,7 @@ void ChannelData::UpdateServiceConfigInDataPlaneLocked() {
server_name_, retry_throttle_config.value().max_milli_tokens,
retry_throttle_config.value().milli_token_ratio);
}
- // Construct per-LB filter stack.
+ // Construct dynamic filter stack.
std::vector filters =
config_selector->GetFilters();
filters.push_back(&kDynamicTerminationFilterVtable);
@@ -2312,6 +2312,7 @@ void ChannelData::UpdateServiceConfigInDataPlaneLocked() {
}
grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
channel_args_, args_to_add.data(), args_to_add.size());
+ new_args = config_selector->ModifyChannelArgs(new_args);
RefCountedPtr dynamic_filters =
DynamicFilters::Create(new_args, std::move(filters));
GPR_ASSERT(dynamic_filters != nullptr);
diff --git a/src/core/ext/filters/client_channel/config_selector.h b/src/core/ext/filters/client_channel/config_selector.h
index 6e41faaecaa..61916d2bc3a 100644
--- a/src/core/ext/filters/client_channel/config_selector.h
+++ b/src/core/ext/filters/client_channel/config_selector.h
@@ -82,8 +82,16 @@ class ConfigSelector : public RefCounted {
return cs1->Equals(cs2);
}
+ // The channel will call this when the resolver returns a new ConfigSelector
+ // to determine what set of dynamic filters will be configured.
virtual std::vector GetFilters() { return {}; }
+ // Modifies channel args to be passed to the dynamic filter stack.
+ // Takes ownership of argument. Caller takes ownership of result.
+ virtual grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) {
+ return args;
+ }
+
virtual CallConfig GetCallConfig(GetCallConfigArgs args) = 0;
grpc_arg MakeChannelArg() const;
diff --git a/src/core/ext/filters/client_channel/dynamic_filters.cc b/src/core/ext/filters/client_channel/dynamic_filters.cc
index afde3c751da..1286fcec42c 100644
--- a/src/core/ext/filters/client_channel/dynamic_filters.cc
+++ b/src/core/ext/filters/client_channel/dynamic_filters.cc
@@ -18,6 +18,7 @@
#include "src/core/ext/filters/client_channel/dynamic_filters.h"
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/surface/lame_client.h"
@@ -160,12 +161,16 @@ RefCountedPtr DynamicFilters::Create(
// Attempt to create channel stack from requested filters.
auto p = CreateChannelStack(args, std::move(filters));
if (p.second != GRPC_ERROR_NONE) {
- // Initial pass failed. Create with lame filter.
+ // Channel stack creation failed with requested filters.
+ // Create with lame filter instead.
grpc_error* error = p.second;
- p = CreateChannelStack(args, {&grpc_lame_filter});
+ grpc_arg error_arg = MakeLameClientErrorArg(error);
+ grpc_channel_args* new_args =
+ grpc_channel_args_copy_and_add(args, &error_arg, 1);
+ GRPC_ERROR_UNREF(error);
+ p = CreateChannelStack(new_args, {&grpc_lame_filter});
GPR_ASSERT(p.second == GRPC_ERROR_NONE);
- grpc_channel_element* elem = grpc_channel_stack_element(p.first, 0);
- SetLameFilterError(elem, error);
+ grpc_channel_args_destroy(new_args);
}
return MakeRefCounted(p.first);
}
diff --git a/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc b/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
index 5e8620736c5..f95b957e26c 100644
--- a/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
+++ b/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
@@ -26,9 +26,11 @@
#include "src/core/ext/filters/client_channel/config_selector.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/ext/xds/xds_client.h"
+#include "src/core/ext/xds/xds_http_filters.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/surface/lame_client.h"
#include "src/core/lib/transport/timeout_encoding.h"
namespace grpc_core {
@@ -135,9 +137,7 @@ class XdsResolver : public Resolver {
class XdsConfigSelector : public ConfigSelector {
public:
- XdsConfigSelector(RefCountedPtr resolver,
- const std::vector& routes,
- grpc_error* error);
+ XdsConfigSelector(RefCountedPtr resolver, grpc_error** error);
~XdsConfigSelector() override;
const char* name() const override { return "XdsConfigSelector"; }
@@ -151,26 +151,41 @@ class XdsResolver : public Resolver {
CallConfig GetCallConfig(GetCallConfigArgs args) override;
+ std::vector GetFilters() override {
+ return filters_;
+ }
+
+ grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) override;
+
private:
struct Route {
+ struct ClusterWeightState {
+ uint32_t range_end;
+ absl::string_view cluster;
+ RefCountedPtr method_config;
+
+ bool operator==(const ClusterWeightState& other) const;
+ };
+
XdsApi::Route route;
- absl::InlinedVector, 2>
- weighted_cluster_state;
RefCountedPtr method_config;
- bool operator==(const Route& other) const {
- return route == other.route &&
- weighted_cluster_state == other.weighted_cluster_state;
- }
+ absl::InlinedVector weighted_cluster_state;
+
+ bool operator==(const Route& other) const;
};
using RouteTable = std::vector;
void MaybeAddCluster(const std::string& name);
- grpc_error* CreateMethodConfig(RefCountedPtr* method_config,
- const XdsApi::Route& route);
+ grpc_error* CreateMethodConfig(
+ const XdsApi::Route& route,
+ const XdsApi::Route::ClusterWeight* cluster_weight,
+ RefCountedPtr* method_config);
RefCountedPtr resolver_;
RouteTable route_table_;
std::map> clusters_;
+ std::vector filters_;
+ grpc_error* filter_error_ = GRPC_ERROR_NONE;
};
void OnListenerUpdate(XdsApi::LdsUpdate listener);
@@ -187,13 +202,20 @@ class XdsResolver : public Resolver {
std::string server_name_;
const grpc_channel_args* args_;
grpc_pollset_set* interested_parties_;
+
RefCountedPtr xds_client_;
+
XdsClient::ListenerWatcherInterface* listener_watcher_ = nullptr;
+ // This will not contain the RouteConfiguration, even if it comes with the
+ // LDS response; instead, the relevant VirtualHost from the
+ // RouteConfiguration will be saved in current_virtual_host_.
+ XdsApi::LdsUpdate current_listener_;
+
std::string route_config_name_;
XdsClient::RouteConfigWatcherInterface* route_config_watcher_ = nullptr;
+ XdsApi::RdsUpdate::VirtualHost current_virtual_host_;
+
ClusterState::ClusterStateMap cluster_state_map_;
- std::vector current_update_;
- XdsApi::Duration http_max_stream_duration_;
};
//
@@ -260,13 +282,35 @@ void XdsResolver::Notifier::RunInWorkSerializer(grpc_error* error) {
delete this;
}
+//
+// XdsResolver::XdsConfigSelector::Route
+//
+
+bool MethodConfigsEqual(const ServiceConfig* sc1, const ServiceConfig* sc2) {
+ if (sc1 == nullptr) return sc2 == nullptr;
+ if (sc2 == nullptr) return false;
+ return sc1->json_string() == sc2->json_string();
+}
+
+bool XdsResolver::XdsConfigSelector::Route::ClusterWeightState::operator==(
+ const ClusterWeightState& other) const {
+ return range_end == other.range_end && cluster == other.cluster &&
+ MethodConfigsEqual(method_config.get(), other.method_config.get());
+}
+
+bool XdsResolver::XdsConfigSelector::Route::operator==(
+ const Route& other) const {
+ return route == other.route &&
+ weighted_cluster_state == other.weighted_cluster_state &&
+ MethodConfigsEqual(method_config.get(), other.method_config.get());
+}
+
//
// XdsResolver::XdsConfigSelector
//
XdsResolver::XdsConfigSelector::XdsConfigSelector(
- RefCountedPtr resolver,
- const std::vector& routes, grpc_error* error)
+ RefCountedPtr resolver, grpc_error** error)
: resolver_(std::move(resolver)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
gpr_log(GPR_INFO, "[xds_resolver %p] creating XdsConfigSelector %p",
@@ -281,8 +325,8 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector(
// weighted_cluster_state field points to the memory in the route field, so
// moving the entry in a reallocation will cause the string_view to point to
// invalid data.
- route_table_.reserve(routes.size());
- for (auto& route : routes) {
+ route_table_.reserve(resolver_->current_virtual_host_.routes.size());
+ for (auto& route : resolver_->current_virtual_host_.routes) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
gpr_log(GPR_INFO, "[xds_resolver %p] XdsConfigSelector %p: route: %s",
resolver_.get(), this, route.ToString().c_str());
@@ -294,27 +338,95 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector(
// one.
if (!route.max_stream_duration.has_value()) {
route_entry.route.max_stream_duration =
- resolver_->http_max_stream_duration_;
+ resolver_->current_listener_.http_max_stream_duration;
}
- error = CreateMethodConfig(&route_entry.method_config, route_entry.route);
if (route.weighted_clusters.empty()) {
+ *error = CreateMethodConfig(route_entry.route, nullptr,
+ &route_entry.method_config);
MaybeAddCluster(route.cluster_name);
} else {
uint32_t end = 0;
for (const auto& weighted_cluster : route_entry.route.weighted_clusters) {
- MaybeAddCluster(weighted_cluster.name);
+ Route::ClusterWeightState cluster_weight_state;
+ *error = CreateMethodConfig(route_entry.route, &weighted_cluster,
+ &cluster_weight_state.method_config);
+ if (*error != GRPC_ERROR_NONE) return;
end += weighted_cluster.weight;
- route_entry.weighted_cluster_state.emplace_back(end,
- weighted_cluster.name);
+ cluster_weight_state.range_end = end;
+ cluster_weight_state.cluster = weighted_cluster.name;
+ route_entry.weighted_cluster_state.push_back(
+ std::move(cluster_weight_state));
+ MaybeAddCluster(weighted_cluster.name);
+ }
+ }
+ }
+ // Populate filter list.
+ if (XdsFaultInjectionEnabled()) {
+ bool found_router = false;
+ for (const auto& http_filter : resolver_->current_listener_.http_filters) {
+ // Stop at the router filter. It's a no-op for us, and we ignore
+ // anything that may come after it, for compatibility with Envoy.
+ if (http_filter.config.config_proto_type_name ==
+ kXdsHttpRouterFilterConfigName) {
+ found_router = true;
+ break;
}
+ // Find filter. This is guaranteed to succeed, because it's checked
+ // at config validation time in the XdsApi code.
+ const XdsHttpFilterImpl* filter_impl =
+ XdsHttpFilterRegistry::GetFilterForType(
+ http_filter.config.config_proto_type_name);
+ GPR_ASSERT(filter_impl != nullptr);
+ // Add C-core filter to list.
+ filters_.push_back(filter_impl->channel_filter());
+ }
+ // For compatibility with Envoy, if the router filter is not
+ // configured, we fail all RPCs.
+ if (!found_router) {
+ filter_error_ = grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "no xDS HTTP router filter configured"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+ filters_.push_back(&grpc_lame_filter);
}
}
}
+XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
+ gpr_log(GPR_INFO, "[xds_resolver %p] destroying XdsConfigSelector %p",
+ resolver_.get(), this);
+ }
+ clusters_.clear();
+ resolver_->MaybeRemoveUnusedClusters();
+ GRPC_ERROR_UNREF(filter_error_);
+}
+
+const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride(
+ const std::string& instance_name,
+ const XdsApi::RdsUpdate::VirtualHost& vhost, const XdsApi::Route& route,
+ const XdsApi::Route::ClusterWeight* cluster_weight) {
+ // Check ClusterWeight, if any.
+ if (cluster_weight != nullptr) {
+ auto it = cluster_weight->typed_per_filter_config.find(instance_name);
+ if (it != cluster_weight->typed_per_filter_config.end()) return &it->second;
+ }
+ // Check Route.
+ auto it = route.typed_per_filter_config.find(instance_name);
+ if (it != route.typed_per_filter_config.end()) return &it->second;
+ // Check VirtualHost.
+ it = vhost.typed_per_filter_config.find(instance_name);
+ if (it != vhost.typed_per_filter_config.end()) return &it->second;
+ // Not found.
+ return nullptr;
+}
+
grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig(
- RefCountedPtr* method_config, const XdsApi::Route& route) {
- grpc_error* error = GRPC_ERROR_NONE;
+ const XdsApi::Route& route,
+ const XdsApi::Route::ClusterWeight* cluster_weight,
+ RefCountedPtr* method_config) {
std::vector fields;
+ // Set timeout.
if (route.max_stream_duration.has_value() &&
(route.max_stream_duration->seconds != 0 ||
route.max_stream_duration->nanos != 0)) {
@@ -322,6 +434,50 @@ grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig(
route.max_stream_duration->seconds,
route.max_stream_duration->nanos));
}
+ // Handle xDS HTTP filters.
+ std::map> per_filter_configs;
+ grpc_channel_args* args = grpc_channel_args_copy(resolver_->args_);
+ for (const auto& http_filter : resolver_->current_listener_.http_filters) {
+ // Stop at the router filter. It's a no-op for us, and we ignore
+ // anything that may come after it, for compatibility with Envoy.
+ if (http_filter.config.config_proto_type_name ==
+ kXdsHttpRouterFilterConfigName) {
+ break;
+ }
+ // Find filter. This is guaranteed to succeed, because it's checked
+ // at config validation time in the XdsApi code.
+ const XdsHttpFilterImpl* filter_impl =
+ XdsHttpFilterRegistry::GetFilterForType(
+ http_filter.config.config_proto_type_name);
+ GPR_ASSERT(filter_impl != nullptr);
+ // Allow filter to add channel args that may affect service config
+ // parsing.
+ args = filter_impl->ModifyChannelArgs(args);
+ // Find config override, if any.
+ const XdsHttpFilterImpl::FilterConfig* config_override =
+ FindFilterConfigOverride(http_filter.name,
+ resolver_->current_virtual_host_, route,
+ cluster_weight);
+ // Generate service config for filter.
+ auto method_config_field =
+ filter_impl->GenerateServiceConfig(http_filter.config, config_override);
+ if (!method_config_field.ok()) {
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("failed to generate method config for HTTP filter ",
+ http_filter.name, ": ",
+ method_config_field.status().ToString())
+ .c_str());
+ }
+ per_filter_configs[method_config_field->service_config_field_name]
+ .push_back(method_config_field->element);
+ }
+ for (const auto& p : per_filter_configs) {
+ fields.emplace_back(absl::StrCat(" \"", p.first, "\": [\n",
+ absl::StrJoin(p.second, ",\n"),
+ "\n ]"));
+ }
+ // Construct service config.
+ grpc_error* error = GRPC_ERROR_NONE;
if (!fields.empty()) {
std::string json = absl::StrCat(
"{\n"
@@ -333,19 +489,20 @@ grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig(
absl::StrJoin(fields, ",\n"),
"\n } ]\n"
"}");
- *method_config =
- ServiceConfig::Create(resolver_->args_, json.c_str(), &error);
+ *method_config = ServiceConfig::Create(args, json.c_str(), &error);
}
+ grpc_channel_args_destroy(args);
return error;
}
-XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
- gpr_log(GPR_INFO, "[xds_resolver %p] destroying XdsConfigSelector %p",
- resolver_.get(), this);
- }
- clusters_.clear();
- resolver_->MaybeRemoveUnusedClusters();
+grpc_channel_args* XdsResolver::XdsConfigSelector::ModifyChannelArgs(
+ grpc_channel_args* args) {
+ if (filter_error_ == GRPC_ERROR_NONE) return args;
+ grpc_arg error_arg = MakeLameClientErrorArg(filter_error_);
+ grpc_channel_args* new_args =
+ grpc_channel_args_copy_and_add(args, &error_arg, 1);
+ grpc_channel_args_destroy(args);
+ return new_args;
}
void XdsResolver::XdsConfigSelector::MaybeAddCluster(const std::string& name) {
@@ -437,13 +594,15 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
}
// Found a route match
absl::string_view cluster_name;
+ RefCountedPtr method_config;
if (entry.route.weighted_clusters.empty()) {
cluster_name = entry.route.cluster_name;
+ method_config = entry.method_config;
} else {
const uint32_t key =
rand() %
entry.weighted_cluster_state[entry.weighted_cluster_state.size() - 1]
- .first;
+ .range_end;
// Find the index in weighted clusters corresponding to key.
size_t mid = 0;
size_t start_index = 0;
@@ -451,9 +610,9 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
size_t index = 0;
while (end_index > start_index) {
mid = (start_index + end_index) / 2;
- if (entry.weighted_cluster_state[mid].first > key) {
+ if (entry.weighted_cluster_state[mid].range_end > key) {
end_index = mid;
- } else if (entry.weighted_cluster_state[mid].first < key) {
+ } else if (entry.weighted_cluster_state[mid].range_end < key) {
start_index = mid + 1;
} else {
index = mid + 1;
@@ -461,8 +620,9 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
}
}
if (index == 0) index = start_index;
- GPR_ASSERT(entry.weighted_cluster_state[index].first > key);
- cluster_name = entry.weighted_cluster_state[index].second;
+ GPR_ASSERT(entry.weighted_cluster_state[index].range_end > key);
+ cluster_name = entry.weighted_cluster_state[index].cluster;
+ method_config = entry.weighted_cluster_state[index].method_config;
}
auto it = clusters_.find(cluster_name);
GPR_ASSERT(it != clusters_.end());
@@ -470,10 +630,10 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
static_cast(resolver_->Ref().release());
ClusterState* cluster_state = it->second->Ref().release();
CallConfig call_config;
- if (entry.method_config != nullptr) {
- call_config.service_config = entry.method_config;
+ if (method_config != nullptr) {
call_config.method_configs =
- entry.method_config->GetMethodParsedConfigVector(grpc_empty_slice());
+ method_config->GetMethodParsedConfigVector(grpc_empty_slice());
+ call_config.service_config = std::move(method_config);
}
call_config.call_attributes[kXdsClusterAttribute] = it->first;
call_config.on_call_committed = [resolver, cluster_state]() {
@@ -577,10 +737,10 @@ void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) {
xds_client_->WatchRouteConfigData(route_config_name_, std::move(watcher));
}
}
- http_max_stream_duration_ = listener.http_max_stream_duration;
+ current_listener_ = std::move(listener);
if (route_config_name_.empty()) {
- GPR_ASSERT(listener.rds_update.has_value());
- OnRouteConfigUpdate(std::move(*listener.rds_update));
+ GPR_ASSERT(current_listener_.rds_update.has_value());
+ OnRouteConfigUpdate(std::move(*current_listener_.rds_update));
}
}
@@ -598,8 +758,8 @@ void XdsResolver::OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update) {
.c_str()));
return;
}
- // Save the list of routes in the resolver.
- current_update_ = std::move(vhost->routes);
+ // Save the virtual host in the resolver.
+ current_virtual_host_ = std::move(*vhost);
// Send a new result to the channel.
GenerateResult();
}
@@ -618,7 +778,7 @@ void XdsResolver::OnResourceDoesNotExist() {
"[xds_resolver %p] LDS/RDS resource does not exist -- clearing "
"update and returning empty service config",
this);
- current_update_.clear();
+ current_virtual_host_.routes.clear();
Result result;
result.service_config =
ServiceConfig::Create(args_, "{}", &result.service_config_error);
@@ -660,12 +820,11 @@ grpc_error* XdsResolver::CreateServiceConfig(
}
void XdsResolver::GenerateResult() {
- if (current_update_.empty()) return;
+ if (current_virtual_host_.routes.empty()) return;
// First create XdsConfigSelector, which may add new entries to the cluster
// state map, and then CreateServiceConfig for LB policies.
grpc_error* error = GRPC_ERROR_NONE;
- auto config_selector =
- MakeRefCounted(Ref(), current_update_, error);
+ auto config_selector = MakeRefCounted(Ref(), &error);
if (error != GRPC_ERROR_NONE) {
OnError(error);
return;
diff --git a/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c b/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c
new file mode 100644
index 00000000000..8e6ff697fc5
--- /dev/null
+++ b/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c
@@ -0,0 +1,41 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * envoy/extensions/filters/http/router/v3/router.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include
+#include "upb/msg.h"
+#include "envoy/extensions/filters/http/router/v3/router.upb.h"
+#include "envoy/config/accesslog/v3/accesslog.upb.h"
+#include "google/protobuf/wrappers.upb.h"
+#include "udpa/annotations/status.upb.h"
+#include "udpa/annotations/versioning.upb.h"
+#include "validate/validate.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const envoy_extensions_filters_http_router_v3_Router_submsgs[2] = {
+ &envoy_config_accesslog_v3_AccessLog_msginit,
+ &google_protobuf_BoolValue_msginit,
+};
+
+static const upb_msglayout_field envoy_extensions_filters_http_router_v3_Router__fields[6] = {
+ {1, UPB_SIZE(4, 8), 1, 1, 11, 1},
+ {2, UPB_SIZE(1, 1), 0, 0, 8, 1},
+ {3, UPB_SIZE(8, 16), 0, 0, 11, 3},
+ {4, UPB_SIZE(2, 2), 0, 0, 8, 1},
+ {5, UPB_SIZE(12, 24), 0, 0, 9, 3},
+ {6, UPB_SIZE(3, 3), 0, 0, 8, 1},
+};
+
+const upb_msglayout envoy_extensions_filters_http_router_v3_Router_msginit = {
+ &envoy_extensions_filters_http_router_v3_Router_submsgs[0],
+ &envoy_extensions_filters_http_router_v3_Router__fields[0],
+ UPB_SIZE(16, 32), 6, false, 255,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h b/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h
new file mode 100644
index 00000000000..2e7084ac970
--- /dev/null
+++ b/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h
@@ -0,0 +1,113 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * envoy/extensions/filters/http/router/v3/router.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_EXTENSIONS_FILTERS_HTTP_ROUTER_V3_ROUTER_PROTO_UPB_H_
+#define ENVOY_EXTENSIONS_FILTERS_HTTP_ROUTER_V3_ROUTER_PROTO_UPB_H_
+
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/decode_fast.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct envoy_extensions_filters_http_router_v3_Router;
+typedef struct envoy_extensions_filters_http_router_v3_Router envoy_extensions_filters_http_router_v3_Router;
+extern const upb_msglayout envoy_extensions_filters_http_router_v3_Router_msginit;
+struct envoy_config_accesslog_v3_AccessLog;
+struct google_protobuf_BoolValue;
+extern const upb_msglayout envoy_config_accesslog_v3_AccessLog_msginit;
+extern const upb_msglayout google_protobuf_BoolValue_msginit;
+
+
+/* envoy.extensions.filters.http.router.v3.Router */
+
+UPB_INLINE envoy_extensions_filters_http_router_v3_Router *envoy_extensions_filters_http_router_v3_Router_new(upb_arena *arena) {
+ return (envoy_extensions_filters_http_router_v3_Router *)_upb_msg_new(&envoy_extensions_filters_http_router_v3_Router_msginit, arena);
+}
+UPB_INLINE envoy_extensions_filters_http_router_v3_Router *envoy_extensions_filters_http_router_v3_Router_parse(const char *buf, size_t size,
+ upb_arena *arena) {
+ envoy_extensions_filters_http_router_v3_Router *ret = envoy_extensions_filters_http_router_v3_Router_new(arena);
+ return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_http_router_v3_Router_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE envoy_extensions_filters_http_router_v3_Router *envoy_extensions_filters_http_router_v3_Router_parse_ex(const char *buf, size_t size,
+ upb_arena *arena, int options) {
+ envoy_extensions_filters_http_router_v3_Router *ret = envoy_extensions_filters_http_router_v3_Router_new(arena);
+ return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_http_router_v3_Router_msginit, arena, options))
+ ? ret : NULL;
+}
+UPB_INLINE char *envoy_extensions_filters_http_router_v3_Router_serialize(const envoy_extensions_filters_http_router_v3_Router *msg, upb_arena *arena, size_t *len) {
+ return upb_encode(msg, &envoy_extensions_filters_http_router_v3_Router_msginit, arena, len);
+}
+
+UPB_INLINE bool envoy_extensions_filters_http_router_v3_Router_has_dynamic_stats(const envoy_extensions_filters_http_router_v3_Router *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_extensions_filters_http_router_v3_Router_dynamic_stats(const envoy_extensions_filters_http_router_v3_Router *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_BoolValue*); }
+UPB_INLINE bool envoy_extensions_filters_http_router_v3_Router_start_child_span(const envoy_extensions_filters_http_router_v3_Router *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool envoy_extensions_filters_http_router_v3_Router_has_upstream_log(const envoy_extensions_filters_http_router_v3_Router *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); }
+UPB_INLINE const struct envoy_config_accesslog_v3_AccessLog* const* envoy_extensions_filters_http_router_v3_Router_upstream_log(const envoy_extensions_filters_http_router_v3_Router *msg, size_t *len) { return (const struct envoy_config_accesslog_v3_AccessLog* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); }
+UPB_INLINE bool envoy_extensions_filters_http_router_v3_Router_suppress_envoy_headers(const envoy_extensions_filters_http_router_v3_Router *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+UPB_INLINE upb_strview const* envoy_extensions_filters_http_router_v3_Router_strict_check_headers(const envoy_extensions_filters_http_router_v3_Router *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); }
+UPB_INLINE bool envoy_extensions_filters_http_router_v3_Router_respect_expected_rq_timeout(const envoy_extensions_filters_http_router_v3_Router *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); }
+
+UPB_INLINE void envoy_extensions_filters_http_router_v3_Router_set_dynamic_stats(envoy_extensions_filters_http_router_v3_Router *msg, struct google_protobuf_BoolValue* value) {
+ _upb_sethas(msg, 1);
+ *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_BoolValue*) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_extensions_filters_http_router_v3_Router_mutable_dynamic_stats(envoy_extensions_filters_http_router_v3_Router *msg, upb_arena *arena) {
+ struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_extensions_filters_http_router_v3_Router_dynamic_stats(msg);
+ if (sub == NULL) {
+ sub = (struct google_protobuf_BoolValue*)_upb_msg_new(&google_protobuf_BoolValue_msginit, arena);
+ if (!sub) return NULL;
+ envoy_extensions_filters_http_router_v3_Router_set_dynamic_stats(msg, sub);
+ }
+ return sub;
+}
+UPB_INLINE void envoy_extensions_filters_http_router_v3_Router_set_start_child_span(envoy_extensions_filters_http_router_v3_Router *msg, bool value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE struct envoy_config_accesslog_v3_AccessLog** envoy_extensions_filters_http_router_v3_Router_mutable_upstream_log(envoy_extensions_filters_http_router_v3_Router *msg, size_t *len) {
+ return (struct envoy_config_accesslog_v3_AccessLog**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len);
+}
+UPB_INLINE struct envoy_config_accesslog_v3_AccessLog** envoy_extensions_filters_http_router_v3_Router_resize_upstream_log(envoy_extensions_filters_http_router_v3_Router *msg, size_t len, upb_arena *arena) {
+ return (struct envoy_config_accesslog_v3_AccessLog**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct envoy_config_accesslog_v3_AccessLog* envoy_extensions_filters_http_router_v3_Router_add_upstream_log(envoy_extensions_filters_http_router_v3_Router *msg, upb_arena *arena) {
+ struct envoy_config_accesslog_v3_AccessLog* sub = (struct envoy_config_accesslog_v3_AccessLog*)_upb_msg_new(&envoy_config_accesslog_v3_AccessLog_msginit, arena);
+ bool ok = _upb_array_append_accessor2(
+ msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena);
+ if (!ok) return NULL;
+ return sub;
+}
+UPB_INLINE void envoy_extensions_filters_http_router_v3_Router_set_suppress_envoy_headers(envoy_extensions_filters_http_router_v3_Router *msg, bool value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+UPB_INLINE upb_strview* envoy_extensions_filters_http_router_v3_Router_mutable_strict_check_headers(envoy_extensions_filters_http_router_v3_Router *msg, size_t *len) {
+ return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len);
+}
+UPB_INLINE upb_strview* envoy_extensions_filters_http_router_v3_Router_resize_strict_check_headers(envoy_extensions_filters_http_router_v3_Router *msg, size_t len, upb_arena *arena) {
+ return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool envoy_extensions_filters_http_router_v3_Router_add_strict_check_headers(envoy_extensions_filters_http_router_v3_Router *msg, upb_strview val, upb_arena *arena) {
+ return _upb_array_append_accessor2(msg, UPB_SIZE(12, 24), UPB_SIZE(3, 4), &val,
+ arena);
+}
+UPB_INLINE void envoy_extensions_filters_http_router_v3_Router_set_respect_expected_rq_timeout(envoy_extensions_filters_http_router_v3_Router *msg, bool value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* ENVOY_EXTENSIONS_FILTERS_HTTP_ROUTER_V3_ROUTER_PROTO_UPB_H_ */
diff --git a/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c b/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c
new file mode 100644
index 00000000000..24407fa6eac
--- /dev/null
+++ b/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c
@@ -0,0 +1,33 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * udpa/type/v1/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include
+#include "upb/msg.h"
+#include "udpa/type/v1/typed_struct.upb.h"
+#include "validate/validate.upb.h"
+#include "google/protobuf/struct.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const udpa_type_v1_TypedStruct_submsgs[1] = {
+ &google_protobuf_Struct_msginit,
+};
+
+static const upb_msglayout_field udpa_type_v1_TypedStruct__fields[2] = {
+ {1, UPB_SIZE(4, 8), 0, 0, 9, 1},
+ {2, UPB_SIZE(12, 24), 1, 0, 11, 1},
+};
+
+const upb_msglayout udpa_type_v1_TypedStruct_msginit = {
+ &udpa_type_v1_TypedStruct_submsgs[0],
+ &udpa_type_v1_TypedStruct__fields[0],
+ UPB_SIZE(16, 32), 2, false, 255,
+};
+
+#include "upb/port_undef.inc"
+
diff --git a/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h b/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h
new file mode 100644
index 00000000000..2dd03ff12d7
--- /dev/null
+++ b/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h
@@ -0,0 +1,77 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * udpa/type/v1/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPB_H_
+#define UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPB_H_
+
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/decode_fast.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct udpa_type_v1_TypedStruct;
+typedef struct udpa_type_v1_TypedStruct udpa_type_v1_TypedStruct;
+extern const upb_msglayout udpa_type_v1_TypedStruct_msginit;
+struct google_protobuf_Struct;
+extern const upb_msglayout google_protobuf_Struct_msginit;
+
+
+/* udpa.type.v1.TypedStruct */
+
+UPB_INLINE udpa_type_v1_TypedStruct *udpa_type_v1_TypedStruct_new(upb_arena *arena) {
+ return (udpa_type_v1_TypedStruct *)_upb_msg_new(&udpa_type_v1_TypedStruct_msginit, arena);
+}
+UPB_INLINE udpa_type_v1_TypedStruct *udpa_type_v1_TypedStruct_parse(const char *buf, size_t size,
+ upb_arena *arena) {
+ udpa_type_v1_TypedStruct *ret = udpa_type_v1_TypedStruct_new(arena);
+ return (ret && upb_decode(buf, size, ret, &udpa_type_v1_TypedStruct_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE udpa_type_v1_TypedStruct *udpa_type_v1_TypedStruct_parse_ex(const char *buf, size_t size,
+ upb_arena *arena, int options) {
+ udpa_type_v1_TypedStruct *ret = udpa_type_v1_TypedStruct_new(arena);
+ return (ret && _upb_decode(buf, size, ret, &udpa_type_v1_TypedStruct_msginit, arena, options))
+ ? ret : NULL;
+}
+UPB_INLINE char *udpa_type_v1_TypedStruct_serialize(const udpa_type_v1_TypedStruct *msg, upb_arena *arena, size_t *len) {
+ return upb_encode(msg, &udpa_type_v1_TypedStruct_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview udpa_type_v1_TypedStruct_type_url(const udpa_type_v1_TypedStruct *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool udpa_type_v1_TypedStruct_has_value(const udpa_type_v1_TypedStruct *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE const struct google_protobuf_Struct* udpa_type_v1_TypedStruct_value(const udpa_type_v1_TypedStruct *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Struct*); }
+
+UPB_INLINE void udpa_type_v1_TypedStruct_set_type_url(udpa_type_v1_TypedStruct *msg, upb_strview value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void udpa_type_v1_TypedStruct_set_value(udpa_type_v1_TypedStruct *msg, struct google_protobuf_Struct* value) {
+ _upb_sethas(msg, 1);
+ *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Struct*) = value;
+}
+UPB_INLINE struct google_protobuf_Struct* udpa_type_v1_TypedStruct_mutable_value(udpa_type_v1_TypedStruct *msg, upb_arena *arena) {
+ struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)udpa_type_v1_TypedStruct_value(msg);
+ if (sub == NULL) {
+ sub = (struct google_protobuf_Struct*)_upb_msg_new(&google_protobuf_Struct_msginit, arena);
+ if (!sub) return NULL;
+ udpa_type_v1_TypedStruct_set_value(msg, sub);
+ }
+ return sub;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPB_H_ */
diff --git a/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c
new file mode 100644
index 00000000000..f1d9a578077
--- /dev/null
+++ b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c
@@ -0,0 +1,76 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * envoy/extensions/filters/http/router/v3/router.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include "upb/def.h"
+#include "envoy/extensions/filters/http/router/v3/router.upbdefs.h"
+
+extern upb_def_init envoy_config_accesslog_v3_accesslog_proto_upbdefinit;
+extern upb_def_init google_protobuf_wrappers_proto_upbdefinit;
+extern upb_def_init udpa_annotations_status_proto_upbdefinit;
+extern upb_def_init udpa_annotations_versioning_proto_upbdefinit;
+extern upb_def_init validate_validate_proto_upbdefinit;
+extern const upb_msglayout envoy_extensions_filters_http_router_v3_Router_msginit;
+
+static const upb_msglayout *layouts[1] = {
+ &envoy_extensions_filters_http_router_v3_Router_msginit,
+};
+
+static const char descriptor[909] = {'\n', '4', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 'f', 'i', 'l', 't', 'e', 'r',
+'s', '/', 'h', 't', 't', 'p', '/', 'r', 'o', 'u', 't', 'e', 'r', '/', 'v', '3', '/', 'r', 'o', 'u', 't', 'e', 'r', '.', 'p',
+'r', 'o', 't', 'o', '\022', '\'', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i',
+'l', 't', 'e', 'r', 's', '.', 'h', 't', 't', 'p', '.', 'r', 'o', 'u', 't', 'e', 'r', '.', 'v', '3', '\032', ')', 'e', 'n', 'v',
+'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o', 'g', '/', 'v', '3', '/', 'a', 'c',
+'c', 'e', 's', 's', 'l', 'o', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o',
+'t', 'o', 'b', 'u', 'f', '/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p',
+'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't',
+'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i',
+'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l',
+'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\255', '\004', '\n', '\006', 'R', 'o', 'u', 't', 'e', 'r', '\022', '?', '\n',
+'\r', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 's', 't', 'a', 't', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o',
+'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\014',
+'d', 'y', 'n', 'a', 'm', 'i', 'c', 'S', 't', 'a', 't', 's', '\022', '(', '\n', '\020', 's', 't', 'a', 'r', 't', '_', 'c', 'h', 'i',
+'l', 'd', '_', 's', 'p', 'a', 'n', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\016', 's', 't', 'a', 'r', 't', 'C', 'h', 'i', 'l', 'd',
+'S', 'p', 'a', 'n', '\022', 'G', '\n', '\014', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_', 'l', 'o', 'g', '\030', '\003', ' ', '\003', '(',
+'\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o',
+'g', '.', 'v', '3', '.', 'A', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'R', '\013', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 'L',
+'o', 'g', '\022', '4', '\n', '\026', 's', 'u', 'p', 'p', 'r', 'e', 's', 's', '_', 'e', 'n', 'v', 'o', 'y', '_', 'h', 'e', 'a', 'd',
+'e', 'r', 's', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\024', 's', 'u', 'p', 'p', 'r', 'e', 's', 's', 'E', 'n', 'v', 'o', 'y', 'H',
+'e', 'a', 'd', 'e', 'r', 's', '\022', '\307', '\001', '\n', '\024', 's', 't', 'r', 'i', 'c', 't', '_', 'c', 'h', 'e', 'c', 'k', '_', 'h',
+'e', 'a', 'd', 'e', 'r', 's', '\030', '\005', ' ', '\003', '(', '\t', 'B', '\224', '\001', '\372', 'B', '\220', '\001', '\222', '\001', '\214', '\001', '\"', '\211',
+'\001', 'r', '\206', '\001', 'R', '\036', 'x', '-', 'e', 'n', 'v', 'o', 'y', '-', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '-', 'r', 'q',
+'-', 't', 'i', 'm', 'e', 'o', 'u', 't', '-', 'm', 's', 'R', '&', 'x', '-', 'e', 'n', 'v', 'o', 'y', '-', 'u', 'p', 's', 't',
+'r', 'e', 'a', 'm', '-', 'r', 'q', '-', 'p', 'e', 'r', '-', 't', 'r', 'y', '-', 't', 'i', 'm', 'e', 'o', 'u', 't', '-', 'm',
+'s', 'R', '\023', 'x', '-', 'e', 'n', 'v', 'o', 'y', '-', 'm', 'a', 'x', '-', 'r', 'e', 't', 'r', 'i', 'e', 's', 'R', '\025', 'x',
+'-', 'e', 'n', 'v', 'o', 'y', '-', 'r', 'e', 't', 'r', 'y', '-', 'g', 'r', 'p', 'c', '-', 'o', 'n', 'R', '\020', 'x', '-', 'e',
+'n', 'v', 'o', 'y', '-', 'r', 'e', 't', 'r', 'y', '-', 'o', 'n', 'R', '\022', 's', 't', 'r', 'i', 'c', 't', 'C', 'h', 'e', 'c',
+'k', 'H', 'e', 'a', 'd', 'e', 'r', 's', '\022', '=', '\n', '\033', 'r', 'e', 's', 'p', 'e', 'c', 't', '_', 'e', 'x', 'p', 'e', 'c',
+'t', 'e', 'd', '_', 'r', 'q', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\030', 'r', 'e', 's',
+'p', 'e', 'c', 't', 'E', 'x', 'p', 'e', 'c', 't', 'e', 'd', 'R', 'q', 'T', 'i', 'm', 'e', 'o', 'u', 't', ':', '0', '\232', '\305',
+'\210', '\036', '+', '\n', ')', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.',
+'h', 't', 't', 'p', '.', 'r', 'o', 'u', 't', 'e', 'r', '.', 'v', '2', '.', 'R', 'o', 'u', 't', 'e', 'r', 'B', 'N', '\n', '5',
+'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n',
+'s', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'h', 't', 't', 'p', '.', 'r', 'o', 'u', 't', 'e', 'r',
+'.', 'v', '3', 'B', '\013', 'R', 'o', 'u', 't', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020',
+'\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+};
+
+static upb_def_init *deps[6] = {
+ &envoy_config_accesslog_v3_accesslog_proto_upbdefinit,
+ &google_protobuf_wrappers_proto_upbdefinit,
+ &udpa_annotations_status_proto_upbdefinit,
+ &udpa_annotations_versioning_proto_upbdefinit,
+ &validate_validate_proto_upbdefinit,
+ NULL
+};
+
+upb_def_init envoy_extensions_filters_http_router_v3_router_proto_upbdefinit = {
+ deps,
+ layouts,
+ "envoy/extensions/filters/http/router/v3/router.proto",
+ UPB_STRVIEW_INIT(descriptor, 909)
+};
diff --git a/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h
new file mode 100644
index 00000000000..dc91890ed65
--- /dev/null
+++ b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h
@@ -0,0 +1,35 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * envoy/extensions/filters/http/router/v3/router.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef ENVOY_EXTENSIONS_FILTERS_HTTP_ROUTER_V3_ROUTER_PROTO_UPBDEFS_H_
+#define ENVOY_EXTENSIONS_FILTERS_HTTP_ROUTER_V3_ROUTER_PROTO_UPBDEFS_H_
+
+#include "upb/def.h"
+#include "upb/port_def.inc"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "upb/def.h"
+
+#include "upb/port_def.inc"
+
+extern upb_def_init envoy_extensions_filters_http_router_v3_router_proto_upbdefinit;
+
+UPB_INLINE const upb_msgdef *envoy_extensions_filters_http_router_v3_Router_getmsgdef(upb_symtab *s) {
+ _upb_symtab_loaddefinit(s, &envoy_extensions_filters_http_router_v3_router_proto_upbdefinit);
+ return upb_symtab_lookupmsg(s, "envoy.extensions.filters.http.router.v3.Router");
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* ENVOY_EXTENSIONS_FILTERS_HTTP_ROUTER_V3_ROUTER_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c b/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c
new file mode 100644
index 00000000000..f786bff37ab
--- /dev/null
+++ b/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c
@@ -0,0 +1,44 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * udpa/type/v1/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include "upb/def.h"
+#include "udpa/type/v1/typed_struct.upbdefs.h"
+
+extern upb_def_init validate_validate_proto_upbdefinit;
+extern upb_def_init google_protobuf_struct_proto_upbdefinit;
+extern const upb_msglayout udpa_type_v1_TypedStruct_msginit;
+
+static const upb_msglayout *layouts[1] = {
+ &udpa_type_v1_TypedStruct_msginit,
+};
+
+static const char descriptor[251] = {'\n', '\037', 'u', 'd', 'p', 'a', '/', 't', 'y', 'p', 'e', '/', 'v', '1', '/', 't', 'y', 'p', 'e', 'd', '_', 's', 't', 'r', 'u',
+'c', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\014', 'u', 'd', 'p', 'a', '.', 't', 'y', 'p', 'e', '.', 'v', '1', '\032', '\027', 'v',
+'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\034', 'g',
+'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 't', 'r', 'u', 'c', 't', '.', 'p', 'r', 'o',
+'t', 'o', '\"', 'W', '\n', '\013', 'T', 'y', 'p', 'e', 'd', 'S', 't', 'r', 'u', 'c', 't', '\022', '\031', '\n', '\010', 't', 'y', 'p', 'e',
+'_', 'u', 'r', 'l', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 't', 'y', 'p', 'e', 'U', 'r', 'l', '\022', '-', '\n', '\005', 'v', 'a',
+'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b',
+'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', '2', '\n', '\034', 'c', 'o', 'm', '.', 'g',
+'i', 't', 'h', 'u', 'b', '.', 'u', 'd', 'p', 'a', '.', 'u', 'd', 'p', 'a', '.', 't', 'y', 'p', 'e', '.', 'v', '1', 'B', '\020',
+'T', 'y', 'p', 'e', 'd', 'S', 't', 'r', 'u', 'c', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o',
+'3',
+};
+
+static upb_def_init *deps[3] = {
+ &validate_validate_proto_upbdefinit,
+ &google_protobuf_struct_proto_upbdefinit,
+ NULL
+};
+
+upb_def_init udpa_type_v1_typed_struct_proto_upbdefinit = {
+ deps,
+ layouts,
+ "udpa/type/v1/typed_struct.proto",
+ UPB_STRVIEW_INIT(descriptor, 251)
+};
diff --git a/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h b/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h
new file mode 100644
index 00000000000..d30baef2b22
--- /dev/null
+++ b/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h
@@ -0,0 +1,35 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * udpa/type/v1/typed_struct.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPBDEFS_H_
+#define UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPBDEFS_H_
+
+#include "upb/def.h"
+#include "upb/port_def.inc"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "upb/def.h"
+
+#include "upb/port_def.inc"
+
+extern upb_def_init udpa_type_v1_typed_struct_proto_upbdefinit;
+
+UPB_INLINE const upb_msgdef *udpa_type_v1_TypedStruct_getmsgdef(upb_symtab *s) {
+ _upb_symtab_loaddefinit(s, &udpa_type_v1_typed_struct_proto_upbdefinit);
+ return upb_symtab_lookupmsg(s, "udpa.type.v1.TypedStruct");
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* UDPA_TYPE_V1_TYPED_STRUCT_PROTO_UPBDEFS_H_ */
diff --git a/src/core/ext/xds/xds_api.cc b/src/core/ext/xds/xds_api.cc
index ce58dd9a2e7..19640db2736 100644
--- a/src/core/ext/xds/xds_api.cc
+++ b/src/core/ext/xds/xds_api.cc
@@ -28,22 +28,6 @@
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
-
-#include "upb/upb.hpp"
-
-#include
-#include
-#include
-
-#include "src/core/ext/xds/xds_api.h"
-#include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gpr/useful.h"
-#include "src/core/lib/gprpp/host_port.h"
-#include "src/core/lib/iomgr/error.h"
-#include "src/core/lib/iomgr/sockaddr_utils.h"
-#include "src/core/lib/slice/slice_utils.h"
-
#include "envoy/config/cluster/v3/circuit_breaker.upb.h"
#include "envoy/config/cluster/v3/cluster.upb.h"
#include "envoy/config/cluster/v3/cluster.upbdefs.h"
@@ -58,12 +42,14 @@
#include "envoy/config/endpoint/v3/load_report.upb.h"
#include "envoy/config/listener/v3/api_listener.upb.h"
#include "envoy/config/listener/v3/listener.upb.h"
+#include "envoy/config/listener/v3/listener.upbdefs.h"
#include "envoy/config/listener/v3/listener_components.upb.h"
#include "envoy/config/route/v3/route.upb.h"
#include "envoy/config/route/v3/route.upbdefs.h"
#include "envoy/config/route/v3/route_components.upb.h"
#include "envoy/extensions/clusters/aggregate/v3/cluster.upb.h"
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h"
+#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h"
#include "envoy/extensions/transport_sockets/tls/v3/common.upb.h"
#include "envoy/extensions/transport_sockets/tls/v3/tls.upb.h"
#include "envoy/service/cluster/v3/cds.upb.h"
@@ -86,8 +72,23 @@
#include "google/protobuf/struct.upb.h"
#include "google/protobuf/wrappers.upb.h"
#include "google/rpc/status.upb.h"
+#include "udpa/type/v1/typed_struct.upb.h"
#include "upb/text_encode.h"
#include "upb/upb.h"
+#include "upb/upb.hpp"
+
+#include
+#include
+#include
+
+#include "src/core/ext/xds/xds_api.h"
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/host_port.h"
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/slice/slice_utils.h"
namespace grpc_core {
@@ -137,6 +138,16 @@ bool XdsSecurityEnabled() {
return parse_succeeded && parsed_value;
}
+// TODO(lidiz): This will be removed once the fault injection feature is
+// fully integration-tested and enabled by default.
+bool XdsFaultInjectionEnabled() {
+ char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+ bool parsed_value;
+ bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value);
+ gpr_free(value);
+ return parse_succeeded && parsed_value;
+}
+
//
// XdsApi::Route
//
@@ -156,7 +167,20 @@ std::string XdsApi::Route::Matchers::ToString() const {
}
std::string XdsApi::Route::ClusterWeight::ToString() const {
- return absl::StrFormat("{cluster=%s, weight=%d}", name, weight);
+ std::vector contents;
+ contents.push_back(absl::StrCat("cluster=", name));
+ contents.push_back(absl::StrCat("weight=", weight));
+ if (!typed_per_filter_config.empty()) {
+ std::vector parts;
+ for (const auto& p : typed_per_filter_config) {
+ const std::string& key = p.first;
+ const auto& config = p.second;
+ parts.push_back(absl::StrCat(key, "=", config.ToString()));
+ }
+ contents.push_back(absl::StrCat("typed_per_filter_config={",
+ absl::StrJoin(parts, ", "), "}"));
+ }
+ return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
}
std::string XdsApi::Route::ToString() const {
@@ -171,6 +195,15 @@ std::string XdsApi::Route::ToString() const {
if (max_stream_duration.has_value()) {
contents.push_back(max_stream_duration->ToString());
}
+ if (!typed_per_filter_config.empty()) {
+ contents.push_back("typed_per_filter_config={");
+ for (const auto& p : typed_per_filter_config) {
+ const std::string& name = p.first;
+ const auto& config = p.second;
+ contents.push_back(absl::StrCat(" ", name, "=", config.ToString()));
+ }
+ contents.push_back("}");
+ }
return absl::StrJoin(contents, "\n");
}
@@ -193,6 +226,14 @@ std::string XdsApi::RdsUpdate::ToString() const {
vhosts.push_back("\n }\n");
}
vhosts.push_back(" ]\n");
+ vhosts.push_back(" typed_per_filter_config={\n");
+ for (const auto& p : vhost.typed_per_filter_config) {
+ const std::string& name = p.first;
+ const auto& config = p.second;
+ vhosts.push_back(
+ absl::StrCat(" ", name, "=", config.ToString(), "\n"));
+ }
+ vhosts.push_back(" }\n");
vhosts.push_back("]\n");
}
return absl::StrJoin(vhosts, "");
@@ -398,6 +439,14 @@ bool XdsApi::DownstreamTlsContext::Empty() const {
return common_tls_context.Empty();
}
+//
+// XdsApi::LdsUpdate::HttpFilter
+//
+
+std::string XdsApi::LdsUpdate::HttpFilter::ToString() const {
+ return absl::StrCat("{name=", name, ", config=", config.ToString(), "}");
+}
+
//
// XdsApi::LdsUpdate
//
@@ -420,6 +469,14 @@ std::string XdsApi::LdsUpdate::ToString() const {
absl::StrFormat("rds_update=%s", rds_update->ToString()));
}
}
+ if (!http_filters.empty()) {
+ std::vector filter_strings;
+ for (const auto& http_filter : http_filters) {
+ filter_strings.push_back(http_filter.ToString());
+ }
+ contents.push_back(absl::StrCat("http_filters=[",
+ absl::StrJoin(filter_strings, ", "), "]"));
+ }
return absl::StrCat("{", absl::StrJoin(contents, ", "), "}");
}
@@ -563,39 +620,63 @@ XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer,
node_(node),
build_version_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING, " ",
grpc_version_string())),
- user_agent_name_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING)) {}
+ user_agent_name_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING)) {
+ // Populate upb symtab with xDS proto messages that we want to print
+ // properly in logs.
+ // Note: This won't actually work properly until upb adds support for
+ // Any fields in textproto printing (internal b/178821188).
+ envoy_config_listener_v3_Listener_getmsgdef(symtab_.ptr());
+ envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab_.ptr());
+ envoy_config_cluster_v3_Cluster_getmsgdef(symtab_.ptr());
+ envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab_.ptr());
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef(
+ symtab_.ptr());
+ // Load HTTP filter proto messages into the upb symtab.
+ XdsHttpFilterRegistry::PopulateSymtab(symtab_.ptr());
+}
namespace {
+struct EncodingContext {
+ XdsClient* client;
+ TraceFlag* tracer;
+ upb_symtab* symtab;
+ upb_arena* arena;
+ bool use_v3;
+};
+
// Works for both std::string and absl::string_view.
template
inline upb_strview StdStringToUpbString(const T& str) {
return upb_strview_make(str.data(), str.size());
}
-void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
- const Json& value);
+void PopulateMetadataValue(const EncodingContext& context,
+ google_protobuf_Value* value_pb, const Json& value);
-void PopulateListValue(upb_arena* arena, google_protobuf_ListValue* list_value,
+void PopulateListValue(const EncodingContext& context,
+ google_protobuf_ListValue* list_value,
const Json::Array& values) {
for (const auto& value : values) {
- auto* value_pb = google_protobuf_ListValue_add_values(list_value, arena);
- PopulateMetadataValue(arena, value_pb, value);
+ auto* value_pb =
+ google_protobuf_ListValue_add_values(list_value, context.arena);
+ PopulateMetadataValue(context, value_pb, value);
}
}
-void PopulateMetadata(upb_arena* arena, google_protobuf_Struct* metadata_pb,
+void PopulateMetadata(const EncodingContext& context,
+ google_protobuf_Struct* metadata_pb,
const Json::Object& metadata) {
for (const auto& p : metadata) {
- google_protobuf_Value* value = google_protobuf_Value_new(arena);
- PopulateMetadataValue(arena, value, p.second);
+ google_protobuf_Value* value = google_protobuf_Value_new(context.arena);
+ PopulateMetadataValue(context, value, p.second);
google_protobuf_Struct_fields_set(
- metadata_pb, StdStringToUpbString(p.first), value, arena);
+ metadata_pb, StdStringToUpbString(p.first), value, context.arena);
}
}
-void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
- const Json& value) {
+void PopulateMetadataValue(const EncodingContext& context,
+ google_protobuf_Value* value_pb, const Json& value) {
switch (value.type()) {
case Json::Type::JSON_NULL:
google_protobuf_Value_set_null_value(value_pb, 0);
@@ -616,14 +697,14 @@ void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
break;
case Json::Type::OBJECT: {
google_protobuf_Struct* struct_value =
- google_protobuf_Value_mutable_struct_value(value_pb, arena);
- PopulateMetadata(arena, struct_value, value.object_value());
+ google_protobuf_Value_mutable_struct_value(value_pb, context.arena);
+ PopulateMetadata(context, struct_value, value.object_value());
break;
}
case Json::Type::ARRAY: {
google_protobuf_ListValue* list_value =
- google_protobuf_Value_mutable_list_value(value_pb, arena);
- PopulateListValue(arena, list_value, value.array_value());
+ google_protobuf_Value_mutable_list_value(value_pb, context.arena);
+ PopulateListValue(context, list_value, value.array_value());
break;
}
}
@@ -650,7 +731,8 @@ std::string EncodeStringField(uint32_t field_number, const std::string& str) {
EncodeVarint(str.size()) + str;
}
-void PopulateBuildVersion(upb_arena* arena, envoy_config_core_v3_Node* node_msg,
+void PopulateBuildVersion(const EncodingContext& context,
+ envoy_config_core_v3_Node* node_msg,
const std::string& build_version) {
std::string encoded_build_version = EncodeStringField(5, build_version);
// TODO(roth): This should use upb_msg_addunknown(), but that API is
@@ -658,10 +740,11 @@ void PopulateBuildVersion(upb_arena* arena, envoy_config_core_v3_Node* node_msg,
// API for now. Change this once we upgrade to a version of upb that
// fixes this bug.
_upb_msg_addunknown(node_msg, encoded_build_version.data(),
- encoded_build_version.size(), arena);
+ encoded_build_version.size(), context.arena);
}
-void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
+void PopulateNode(const EncodingContext& context,
+ const XdsBootstrap::Node* node,
const std::string& build_version,
const std::string& user_agent_name,
envoy_config_core_v3_Node* node_msg) {
@@ -676,13 +759,13 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
}
if (!node->metadata.object_value().empty()) {
google_protobuf_Struct* metadata =
- envoy_config_core_v3_Node_mutable_metadata(node_msg, arena);
- PopulateMetadata(arena, metadata, node->metadata.object_value());
+ envoy_config_core_v3_Node_mutable_metadata(node_msg, context.arena);
+ PopulateMetadata(context, metadata, node->metadata.object_value());
}
if (!node->locality_region.empty() || !node->locality_zone.empty() ||
!node->locality_subzone.empty()) {
envoy_config_core_v3_Locality* locality =
- envoy_config_core_v3_Node_mutable_locality(node_msg, arena);
+ envoy_config_core_v3_Node_mutable_locality(node_msg, context.arena);
if (!node->locality_region.empty()) {
envoy_config_core_v3_Locality_set_region(
locality, StdStringToUpbString(node->locality_region));
@@ -697,8 +780,8 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
}
}
}
- if (!use_v3) {
- PopulateBuildVersion(arena, node_msg, build_version);
+ if (!context.use_v3) {
+ PopulateBuildVersion(context, node_msg, build_version);
}
envoy_config_core_v3_Node_set_user_agent_name(
node_msg, StdStringToUpbString(user_agent_name));
@@ -706,7 +789,7 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node, bool use_v3,
node_msg, upb_strview_makez(grpc_version_string()));
envoy_config_core_v3_Node_add_client_features(
node_msg, upb_strview_makez("envoy.lb.does_not_support_overprovisioning"),
- arena);
+ context.arena);
}
inline absl::string_view UpbStringToAbsl(const upb_strview& str) {
@@ -718,24 +801,25 @@ inline std::string UpbStringToStdString(const upb_strview& str) {
}
void MaybeLogDiscoveryRequest(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_service_discovery_v3_DiscoveryRequest* request) {
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
const upb_msgdef* msg_type =
- envoy_service_discovery_v3_DiscoveryRequest_getmsgdef(symtab);
+ envoy_service_discovery_v3_DiscoveryRequest_getmsgdef(context.symtab);
char buf[10240];
upb_text_encode(request, msg_type, nullptr, 0, buf, sizeof(buf));
- gpr_log(GPR_DEBUG, "[xds_client %p] constructed ADS request: %s", client,
- buf);
+ gpr_log(GPR_DEBUG, "[xds_client %p] constructed ADS request: %s",
+ context.client, buf);
}
}
grpc_slice SerializeDiscoveryRequest(
- upb_arena* arena, envoy_service_discovery_v3_DiscoveryRequest* request) {
+ const EncodingContext& context,
+ envoy_service_discovery_v3_DiscoveryRequest* request) {
size_t output_length;
char* output = envoy_service_discovery_v3_DiscoveryRequest_serialize(
- request, arena, &output_length);
+ request, context.arena, &output_length);
return grpc_slice_from_copied_buffer(output, output_length);
}
@@ -766,6 +850,8 @@ grpc_slice XdsApi::CreateAdsRequest(
const std::string& version, const std::string& nonce, grpc_error* error,
bool populate_node) {
upb::Arena arena;
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
+ server.ShouldUseV3()};
// Create a request.
envoy_service_discovery_v3_DiscoveryRequest* request =
envoy_service_discovery_v3_DiscoveryRequest_new(arena.ptr());
@@ -805,69 +891,88 @@ grpc_slice XdsApi::CreateAdsRequest(
envoy_config_core_v3_Node* node_msg =
envoy_service_discovery_v3_DiscoveryRequest_mutable_node(request,
arena.ptr());
- PopulateNode(arena.ptr(), node_, server.ShouldUseV3(), build_version_,
- user_agent_name_, node_msg);
+ PopulateNode(context, node_, build_version_, user_agent_name_, node_msg);
}
// Add resource_names.
for (const auto& resource_name : resource_names) {
envoy_service_discovery_v3_DiscoveryRequest_add_resource_names(
request, StdStringToUpbString(resource_name), arena.ptr());
}
- MaybeLogDiscoveryRequest(client_, tracer_, symtab_.ptr(), request);
- return SerializeDiscoveryRequest(arena.ptr(), request);
+ MaybeLogDiscoveryRequest(context, request);
+ return SerializeDiscoveryRequest(context, request);
}
namespace {
void MaybeLogDiscoveryResponse(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_service_discovery_v3_DiscoveryResponse* response) {
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
const upb_msgdef* msg_type =
- envoy_service_discovery_v3_DiscoveryResponse_getmsgdef(symtab);
+ envoy_service_discovery_v3_DiscoveryResponse_getmsgdef(context.symtab);
char buf[10240];
upb_text_encode(response, msg_type, nullptr, 0, buf, sizeof(buf));
- gpr_log(GPR_DEBUG, "[xds_client %p] received response: %s", client, buf);
+ gpr_log(GPR_DEBUG, "[xds_client %p] received response: %s", context.client,
+ buf);
+ }
+}
+
+void MaybeLogHttpConnectionManager(
+ const EncodingContext& context,
+ const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager*
+ http_connection_manager_config) {
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
+ gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
+ const upb_msgdef* msg_type =
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef(
+ context.symtab);
+ char buf[10240];
+ upb_text_encode(http_connection_manager_config, msg_type, nullptr, 0, buf,
+ sizeof(buf));
+ gpr_log(GPR_DEBUG, "[xds_client %p] HttpConnectionManager: %s",
+ context.client, buf);
}
}
void MaybeLogRouteConfiguration(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_config_route_v3_RouteConfiguration* route_config) {
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
const upb_msgdef* msg_type =
- envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab);
+ envoy_config_route_v3_RouteConfiguration_getmsgdef(context.symtab);
char buf[10240];
upb_text_encode(route_config, msg_type, nullptr, 0, buf, sizeof(buf));
- gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", client, buf);
+ gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", context.client,
+ buf);
}
}
-void MaybeLogCluster(XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+void MaybeLogCluster(const EncodingContext& context,
const envoy_config_cluster_v3_Cluster* cluster) {
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
const upb_msgdef* msg_type =
- envoy_config_cluster_v3_Cluster_getmsgdef(symtab);
+ envoy_config_cluster_v3_Cluster_getmsgdef(context.symtab);
char buf[10240];
upb_text_encode(cluster, msg_type, nullptr, 0, buf, sizeof(buf));
- gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", client, buf);
+ gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", context.client, buf);
}
}
void MaybeLogClusterLoadAssignment(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_config_endpoint_v3_ClusterLoadAssignment* cla) {
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
const upb_msgdef* msg_type =
- envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab);
+ envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(
+ context.symtab);
char buf[10240];
upb_text_encode(cla, msg_type, nullptr, 0, buf, sizeof(buf));
- gpr_log(GPR_DEBUG, "[xds_client %p] ClusterLoadAssignment: %s", client,
- buf);
+ gpr_log(GPR_DEBUG, "[xds_client %p] ClusterLoadAssignment: %s",
+ context.client, buf);
}
}
@@ -1064,7 +1169,84 @@ grpc_error* RouteRuntimeFractionParse(
return GRPC_ERROR_NONE;
}
-grpc_error* RouteActionParse(const envoy_config_route_v3_Route* route_msg,
+grpc_error* ExtractHttpFilterTypeName(const EncodingContext& context,
+ const google_protobuf_Any* any,
+ absl::string_view* filter_type) {
+ *filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any));
+ if (*filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") {
+ upb_strview any_value = google_protobuf_Any_value(any);
+ const auto* typed_struct = udpa_type_v1_TypedStruct_parse(
+ any_value.data, any_value.size, context.arena);
+ if (typed_struct == nullptr) {
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "could not parse TypedStruct from filter config");
+ }
+ *filter_type =
+ UpbStringToAbsl(udpa_type_v1_TypedStruct_type_url(typed_struct));
+ }
+ *filter_type = absl::StripPrefix(*filter_type, "type.googleapis.com/");
+ return GRPC_ERROR_NONE;
+}
+
+template
+grpc_error* ParseTypedPerFilterConfig(
+ const EncodingContext& context, const ParentType* parent,
+ const EntryType* (*entry_func)(const ParentType*, size_t*),
+ upb_strview (*key_func)(const EntryType*),
+ const google_protobuf_Any* (*value_func)(const EntryType*),
+ XdsApi::TypedPerFilterConfig* typed_per_filter_config) {
+ size_t filter_it = UPB_MAP_BEGIN;
+ while (true) {
+ const auto* filter_entry = entry_func(parent, &filter_it);
+ if (filter_entry == nullptr) break;
+ absl::string_view key = UpbStringToAbsl(key_func(filter_entry));
+ if (key.empty()) {
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("empty filter name in map");
+ }
+ const google_protobuf_Any* any = value_func(filter_entry);
+ bool is_optional = false;
+ absl::string_view filter_type =
+ UpbStringToAbsl(google_protobuf_Any_type_url(any));
+ if (filter_type ==
+ "type.googleapis.com/envoy.config.route.v3.FilterConfig") {
+ upb_strview any_value = google_protobuf_Any_value(any);
+ const auto* filter_config = envoy_config_route_v3_FilterConfig_parse(
+ any_value.data, any_value.size, context.arena);
+ if (filter_config == nullptr) {
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("could not parse FilterConfig wrapper for ", key)
+ .c_str());
+ }
+ is_optional =
+ envoy_config_route_v3_FilterConfig_is_optional(filter_config);
+ any = envoy_config_route_v3_FilterConfig_config(filter_config);
+ }
+ grpc_error* error = ExtractHttpFilterTypeName(context, any, &filter_type);
+ if (error != GRPC_ERROR_NONE) return error;
+ const XdsHttpFilterImpl* filter_impl =
+ XdsHttpFilterRegistry::GetFilterForType(filter_type);
+ if (filter_impl == nullptr) {
+ if (is_optional) continue;
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("no filter registered for config type ", filter_type)
+ .c_str());
+ }
+ absl::StatusOr filter_config =
+ filter_impl->GenerateFilterConfigOverride(
+ google_protobuf_Any_value(any), context.arena);
+ if (!filter_config.ok()) {
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("filter config for type ", filter_type,
+ " failed to parse: ", filter_config.status().ToString())
+ .c_str());
+ }
+ (*typed_per_filter_config)[std::string(key)] = std::move(*filter_config);
+ }
+ return GRPC_ERROR_NONE;
+}
+
+grpc_error* RouteActionParse(const EncodingContext& context,
+ const envoy_config_route_v3_Route* route_msg,
XdsApi::Route* route, bool* ignore_route) {
if (!envoy_config_route_v3_Route_has_route(route_msg)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@@ -1117,6 +1299,18 @@ grpc_error* RouteActionParse(const envoy_config_route_v3_Route* route_msg,
cluster.weight = google_protobuf_UInt32Value_value(weight);
if (cluster.weight == 0) continue;
sum_of_weights += cluster.weight;
+ if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) &&
+ context.use_v3) {
+ grpc_error* error = ParseTypedPerFilterConfig<
+ envoy_config_route_v3_WeightedCluster_ClusterWeight,
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry>(
+ context, cluster_weight,
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_typed_per_filter_config_next,
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_key,
+ envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_value,
+ &cluster.typed_per_filter_config);
+ if (error != GRPC_ERROR_NONE) return error;
+ }
route->weighted_clusters.emplace_back(std::move(cluster));
}
if (total_weight != sum_of_weights) {
@@ -1156,16 +1350,16 @@ grpc_error* RouteActionParse(const envoy_config_route_v3_Route* route_msg,
}
grpc_error* RouteConfigParse(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_config_route_v3_RouteConfiguration* route_config,
XdsApi::RdsUpdate* rds_update) {
- MaybeLogRouteConfiguration(client, tracer, symtab, route_config);
+ MaybeLogRouteConfiguration(context, route_config);
// Get the virtual hosts.
- size_t size;
+ size_t num_virtual_hosts;
const envoy_config_route_v3_VirtualHost* const* virtual_hosts =
- envoy_config_route_v3_RouteConfiguration_virtual_hosts(route_config,
- &size);
- for (size_t i = 0; i < size; ++i) {
+ envoy_config_route_v3_RouteConfiguration_virtual_hosts(
+ route_config, &num_virtual_hosts);
+ for (size_t i = 0; i < num_virtual_hosts; ++i) {
rds_update->virtual_hosts.emplace_back();
XdsApi::RdsUpdate::VirtualHost& vhost = rds_update->virtual_hosts.back();
// Parse domains.
@@ -1185,6 +1379,19 @@ grpc_error* RouteConfigParse(
if (vhost.domains.empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("VirtualHost has no domains");
}
+ // Parse typed_per_filter_config.
+ if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) &&
+ context.use_v3) {
+ grpc_error* error = ParseTypedPerFilterConfig<
+ envoy_config_route_v3_VirtualHost,
+ envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry>(
+ context, virtual_hosts[i],
+ envoy_config_route_v3_VirtualHost_typed_per_filter_config_next,
+ envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_key,
+ envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_value,
+ &vhost.typed_per_filter_config);
+ if (error != GRPC_ERROR_NONE) return error;
+ }
// Parse routes.
size_t num_routes;
const envoy_config_route_v3_Route* const* routes =
@@ -1212,9 +1419,21 @@ grpc_error* RouteConfigParse(
if (error != GRPC_ERROR_NONE) return error;
error = RouteRuntimeFractionParse(match, &route);
if (error != GRPC_ERROR_NONE) return error;
- error = RouteActionParse(routes[j], &route, &ignore_route);
+ error = RouteActionParse(context, routes[j], &route, &ignore_route);
if (error != GRPC_ERROR_NONE) return error;
if (ignore_route) continue;
+ if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) &&
+ context.use_v3) {
+ grpc_error* error = ParseTypedPerFilterConfig<
+ envoy_config_route_v3_Route,
+ envoy_config_route_v3_Route_TypedPerFilterConfigEntry>(
+ context, routes[j],
+ envoy_config_route_v3_Route_typed_per_filter_config_next,
+ envoy_config_route_v3_Route_TypedPerFilterConfigEntry_key,
+ envoy_config_route_v3_Route_TypedPerFilterConfigEntry_value,
+ &route.typed_per_filter_config);
+ if (error != GRPC_ERROR_NONE) return error;
+ }
vhost.routes.emplace_back(std::move(route));
}
if (vhost.routes.empty()) {
@@ -1337,20 +1556,20 @@ grpc_error* CommonTlsContextParse(
}
grpc_error* LdsResponseParseClient(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab, upb_arena* arena,
+ const EncodingContext& context,
const envoy_config_listener_v3_ApiListener* api_listener,
XdsApi::LdsUpdate* lds_update) {
lds_update->type = XdsApi::LdsUpdate::ListenerType::kHttpApiListener;
const upb_strview encoded_api_listener = google_protobuf_Any_value(
envoy_config_listener_v3_ApiListener_api_listener(api_listener));
- const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager*
- http_connection_manager =
- envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse(
- encoded_api_listener.data, encoded_api_listener.size, arena);
+ const auto* http_connection_manager =
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse(
+ encoded_api_listener.data, encoded_api_listener.size, context.arena);
if (http_connection_manager == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Could not parse HttpConnectionManager config from ApiListener");
}
+ MaybeLogHttpConnectionManager(context, http_connection_manager);
if (XdsTimeoutEnabled()) {
// Obtain max_stream_duration from Http Protocol Options.
const envoy_config_core_v3_HttpProtocolOptions* options =
@@ -1367,6 +1586,58 @@ grpc_error* LdsResponseParseClient(
}
}
}
+ // Parse filters.
+ if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) && context.use_v3) {
+ size_t num_filters = 0;
+ const auto* http_filters =
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_http_filters(
+ http_connection_manager, &num_filters);
+ std::set names_seen;
+ for (size_t i = 0; i < num_filters; ++i) {
+ const auto* http_filter = http_filters[i];
+ absl::string_view name = UpbStringToAbsl(
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_name(
+ http_filter));
+ if (name.empty()) {
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("empty filter name at index ", i).c_str());
+ }
+ if (names_seen.find(name) != names_seen.end()) {
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("duplicate HTTP filter name: ", name).c_str());
+ }
+ names_seen.insert(name);
+ const google_protobuf_Any* any =
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_typed_config(
+ http_filter);
+ absl::string_view filter_type;
+ grpc_error* error = ExtractHttpFilterTypeName(context, any, &filter_type);
+ if (error != GRPC_ERROR_NONE) return error;
+ const XdsHttpFilterImpl* filter_impl =
+ XdsHttpFilterRegistry::GetFilterForType(filter_type);
+ if (filter_impl == nullptr) {
+ if (envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_is_optional(
+ http_filter)) {
+ continue;
+ }
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("no filter registered for config type ", filter_type)
+ .c_str());
+ }
+ absl::StatusOr filter_config =
+ filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any),
+ context.arena);
+ if (!filter_config.ok()) {
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat(
+ "filter config for type ", filter_type,
+ " failed to parse: ", filter_config.status().ToString())
+ .c_str());
+ }
+ lds_update->http_filters.emplace_back(XdsApi::LdsUpdate::HttpFilter{
+ std::string(name), std::move(*filter_config)});
+ }
+ }
// Found inlined route_config. Parse it to find the cluster_name.
if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config(
http_connection_manager)) {
@@ -1374,21 +1645,19 @@ grpc_error* LdsResponseParseClient(
envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_config(
http_connection_manager);
XdsApi::RdsUpdate rds_update;
- grpc_error* error =
- RouteConfigParse(client, tracer, symtab, route_config, &rds_update);
+ grpc_error* error = RouteConfigParse(context, route_config, &rds_update);
if (error != GRPC_ERROR_NONE) return error;
lds_update->rds_update = std::move(rds_update);
return GRPC_ERROR_NONE;
}
// Validate that RDS must be used to get the route_config dynamically.
- if (!envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_rds(
- http_connection_manager)) {
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "HttpConnectionManager neither has inlined route_config nor RDS.");
- }
const envoy_extensions_filters_network_http_connection_manager_v3_Rds* rds =
envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_rds(
http_connection_manager);
+ if (rds == nullptr) {
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "HttpConnectionManager neither has inlined route_config nor RDS.");
+ }
// Check that the ConfigSource specifies ADS.
const envoy_config_core_v3_ConfigSource* config_source =
envoy_extensions_filters_network_http_connection_manager_v3_Rds_config_source(
@@ -1409,13 +1678,15 @@ grpc_error* LdsResponseParseClient(
}
grpc_error* LdsResponseParseServer(
- upb_arena* arena, const envoy_config_listener_v3_Listener* listener,
- const std::string& /*listener_name*/,
- const envoy_config_core_v3_Address* /*address*/,
+ const EncodingContext& context,
+ const envoy_config_listener_v3_Listener* listener,
XdsApi::LdsUpdate* lds_update) {
lds_update->type = XdsApi::LdsUpdate::ListenerType::kTcpListener;
// TODO(yashykt): Support filter chain match.
// Right now, we are supporting and expecting only one entry in filter_chains.
+ // As part of this, we'll need to refactor the code to process the
+ // HttpConnectionManager config so that it is shared with the client-side
+ // parsing.
size_t size = 0;
auto* filter_chains =
envoy_config_listener_v3_Listener_filter_chains(listener, &size);
@@ -1439,7 +1710,7 @@ grpc_error* LdsResponseParseServer(
auto* downstream_tls_context =
envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_parse(
encoded_downstream_tls_context.data,
- encoded_downstream_tls_context.size, arena);
+ encoded_downstream_tls_context.size, context.arena);
if (downstream_tls_context == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Can't decode downstream tls context.");
@@ -1475,11 +1746,11 @@ grpc_error* LdsResponseParseServer(
}
grpc_error* LdsResponseParse(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_service_discovery_v3_DiscoveryResponse* response,
const std::set& expected_listener_names,
XdsApi::LdsUpdateMap* lds_update_map,
- std::set* resource_names_failed, upb_arena* arena) {
+ std::set* resource_names_failed) {
std::vector errors;
// Get the resources from the response.
size_t size;
@@ -1499,8 +1770,8 @@ grpc_error* LdsResponseParse(
const upb_strview encoded_listener =
google_protobuf_Any_value(resources[i]);
const envoy_config_listener_v3_Listener* listener =
- envoy_config_listener_v3_Listener_parse(encoded_listener.data,
- encoded_listener.size, arena);
+ envoy_config_listener_v3_Listener_parse(
+ encoded_listener.data, encoded_listener.size, context.arena);
if (listener == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("resource index ", i, ": Can't decode listener.")
@@ -1546,11 +1817,9 @@ grpc_error* LdsResponseParse(
}
grpc_error* error = GRPC_ERROR_NONE;
if (api_listener != nullptr) {
- error = LdsResponseParseClient(client, tracer, symtab, arena,
- api_listener, &lds_update);
+ error = LdsResponseParseClient(context, api_listener, &lds_update);
} else {
- error = LdsResponseParseServer(arena, listener, listener_name, address,
- &lds_update);
+ error = LdsResponseParseServer(context, listener, &lds_update);
}
if (error != GRPC_ERROR_NONE) {
errors.push_back(grpc_error_add_child(
@@ -1564,11 +1833,11 @@ grpc_error* LdsResponseParse(
}
grpc_error* RdsResponseParse(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_service_discovery_v3_DiscoveryResponse* response,
const std::set& expected_route_configuration_names,
XdsApi::RdsUpdateMap* rds_update_map,
- std::set* resource_names_failed, upb_arena* arena) {
+ std::set* resource_names_failed) {
std::vector errors;
// Get the resources from the response.
size_t size;
@@ -1589,7 +1858,8 @@ grpc_error* RdsResponseParse(
google_protobuf_Any_value(resources[i]);
const envoy_config_route_v3_RouteConfiguration* route_config =
envoy_config_route_v3_RouteConfiguration_parse(
- encoded_route_config.data, encoded_route_config.size, arena);
+ encoded_route_config.data, encoded_route_config.size,
+ context.arena);
if (route_config == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("resource index ", i, ": Can't decode route_config.")
@@ -1614,8 +1884,7 @@ grpc_error* RdsResponseParse(
}
// Parse the route_config.
XdsApi::RdsUpdate& rds_update = (*rds_update_map)[route_config_name];
- grpc_error* error =
- RouteConfigParse(client, tracer, symtab, route_config, &rds_update);
+ grpc_error* error = RouteConfigParse(context, route_config, &rds_update);
if (error != GRPC_ERROR_NONE) {
errors.push_back(grpc_error_add_child(
GRPC_ERROR_CREATE_FROM_COPIED_STRING(
@@ -1628,11 +1897,11 @@ grpc_error* RdsResponseParse(
}
grpc_error* CdsResponseParse(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_service_discovery_v3_DiscoveryResponse* response,
const std::set& expected_cluster_names,
XdsApi::CdsUpdateMap* cds_update_map,
- std::set* resource_names_failed, upb_arena* arena) {
+ std::set* resource_names_failed) {
std::vector errors;
// Get the resources from the response.
size_t size;
@@ -1652,15 +1921,15 @@ grpc_error* CdsResponseParse(
// Decode the cluster.
const upb_strview encoded_cluster = google_protobuf_Any_value(resources[i]);
const envoy_config_cluster_v3_Cluster* cluster =
- envoy_config_cluster_v3_Cluster_parse(encoded_cluster.data,
- encoded_cluster.size, arena);
+ envoy_config_cluster_v3_Cluster_parse(
+ encoded_cluster.data, encoded_cluster.size, context.arena);
if (cluster == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("resource index ", i, ": Can't decode cluster.")
.c_str()));
continue;
}
- MaybeLogCluster(client, tracer, symtab, cluster);
+ MaybeLogCluster(context, cluster);
// Ignore unexpected cluster names.
std::string cluster_name =
UpbStringToStdString(envoy_config_cluster_v3_Cluster_name(cluster));
@@ -1737,7 +2006,7 @@ grpc_error* CdsResponseParse(
aggregate_cluster_config =
envoy_extensions_clusters_aggregate_v3_ClusterConfig_parse(
aggregate_cluster_config_upb_strview.data,
- aggregate_cluster_config_upb_strview.size, arena);
+ aggregate_cluster_config_upb_strview.size, context.arena);
if (aggregate_cluster_config == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat(cluster_name, ": Can't parse aggregate cluster.")
@@ -1872,7 +2141,7 @@ grpc_error* CdsResponseParse(
auto* upstream_tls_context =
envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_parse(
encoded_upstream_tls_context.data,
- encoded_upstream_tls_context.size, arena);
+ encoded_upstream_tls_context.size, context.arena);
if (upstream_tls_context == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat(cluster_name,
@@ -2068,11 +2337,11 @@ grpc_error* DropParseAndAppend(
}
grpc_error* EdsResponseParse(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_service_discovery_v3_DiscoveryResponse* response,
const std::set& expected_eds_service_names,
XdsApi::EdsUpdateMap* eds_update_map,
- std::set* resource_names_failed, upb_arena* arena) {
+ std::set* resource_names_failed) {
std::vector errors;
// Get the resources from the response.
size_t size;
@@ -2094,7 +2363,7 @@ grpc_error* EdsResponseParse(
envoy_config_endpoint_v3_ClusterLoadAssignment* cluster_load_assignment =
envoy_config_endpoint_v3_ClusterLoadAssignment_parse(
encoded_cluster_load_assignment.data,
- encoded_cluster_load_assignment.size, arena);
+ encoded_cluster_load_assignment.size, context.arena);
if (cluster_load_assignment == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("resource index ", i,
@@ -2102,8 +2371,7 @@ grpc_error* EdsResponseParse(
.c_str()));
continue;
}
- MaybeLogClusterLoadAssignment(client, tracer, symtab,
- cluster_load_assignment);
+ MaybeLogClusterLoadAssignment(context, cluster_load_assignment);
// Check the EDS service name. Ignore unexpected names.
std::string eds_service_name = UpbStringToStdString(
envoy_config_endpoint_v3_ClusterLoadAssignment_cluster_name(
@@ -2214,13 +2482,15 @@ void MoveUpdatesToFailedSet(UpdateMap* update_map,
} // namespace
XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
- const grpc_slice& encoded_response,
+ const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response,
const std::set& expected_listener_names,
const std::set& expected_route_configuration_names,
const std::set& expected_cluster_names,
const std::set& expected_eds_service_names) {
AdsParseResult result;
upb::Arena arena;
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
+ server.ShouldUseV3()};
// Decode the response.
const envoy_service_discovery_v3_DiscoveryResponse* response =
envoy_service_discovery_v3_DiscoveryResponse_parse(
@@ -2232,7 +2502,7 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode DiscoveryResponse.");
return result;
}
- MaybeLogDiscoveryResponse(client_, tracer_, symtab_.ptr(), response);
+ MaybeLogDiscoveryResponse(context, response);
// Record the type_url, the version_info, and the nonce of the response.
result.type_url = TypeUrlInternalToExternal(UpbStringToAbsl(
envoy_service_discovery_v3_DiscoveryResponse_type_url(response)));
@@ -2242,34 +2512,33 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
envoy_service_discovery_v3_DiscoveryResponse_nonce(response));
// Parse the response according to the resource type.
if (IsLds(result.type_url)) {
- result.parse_error = LdsResponseParse(
- client_, tracer_, symtab_.ptr(), response, expected_listener_names,
- &result.lds_update_map, &result.resource_names_failed, arena.ptr());
+ result.parse_error =
+ LdsResponseParse(context, response, expected_listener_names,
+ &result.lds_update_map, &result.resource_names_failed);
if (result.parse_error != GRPC_ERROR_NONE) {
MoveUpdatesToFailedSet(&result.lds_update_map,
&result.resource_names_failed);
}
} else if (IsRds(result.type_url)) {
- result.parse_error = RdsResponseParse(
- client_, tracer_, symtab_.ptr(), response,
- expected_route_configuration_names, &result.rds_update_map,
- &result.resource_names_failed, arena.ptr());
+ result.parse_error =
+ RdsResponseParse(context, response, expected_route_configuration_names,
+ &result.rds_update_map, &result.resource_names_failed);
if (result.parse_error != GRPC_ERROR_NONE) {
MoveUpdatesToFailedSet(&result.rds_update_map,
&result.resource_names_failed);
}
} else if (IsCds(result.type_url)) {
- result.parse_error = CdsResponseParse(
- client_, tracer_, symtab_.ptr(), response, expected_cluster_names,
- &result.cds_update_map, &result.resource_names_failed, arena.ptr());
+ result.parse_error =
+ CdsResponseParse(context, response, expected_cluster_names,
+ &result.cds_update_map, &result.resource_names_failed);
if (result.parse_error != GRPC_ERROR_NONE) {
MoveUpdatesToFailedSet(&result.cds_update_map,
&result.resource_names_failed);
}
} else if (IsEds(result.type_url)) {
- result.parse_error = EdsResponseParse(
- client_, tracer_, symtab_.ptr(), response, expected_eds_service_names,
- &result.eds_update_map, &result.resource_names_failed, arena.ptr());
+ result.parse_error =
+ EdsResponseParse(context, response, expected_eds_service_names,
+ &result.eds_update_map, &result.resource_names_failed);
if (result.parse_error != GRPC_ERROR_NONE) {
MoveUpdatesToFailedSet(&result.eds_update_map,
&result.resource_names_failed);
@@ -2281,25 +2550,25 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse(
namespace {
void MaybeLogLrsRequest(
- XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
+ const EncodingContext& context,
const envoy_service_load_stats_v3_LoadStatsRequest* request) {
- if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
+ if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) &&
gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
const upb_msgdef* msg_type =
- envoy_service_load_stats_v3_LoadStatsRequest_getmsgdef(symtab);
+ envoy_service_load_stats_v3_LoadStatsRequest_getmsgdef(context.symtab);
char buf[10240];
upb_text_encode(request, msg_type, nullptr, 0, buf, sizeof(buf));
- gpr_log(GPR_DEBUG, "[xds_client %p] constructed LRS request: %s", client,
- buf);
+ gpr_log(GPR_DEBUG, "[xds_client %p] constructed LRS request: %s",
+ context.client, buf);
}
}
grpc_slice SerializeLrsRequest(
- const envoy_service_load_stats_v3_LoadStatsRequest* request,
- upb_arena* arena) {
+ const EncodingContext& context,
+ const envoy_service_load_stats_v3_LoadStatsRequest* request) {
size_t output_length;
char* output = envoy_service_load_stats_v3_LoadStatsRequest_serialize(
- request, arena, &output_length);
+ request, context.arena, &output_length);
return grpc_slice_from_copied_buffer(output, output_length);
}
@@ -2308,6 +2577,8 @@ grpc_slice SerializeLrsRequest(
grpc_slice XdsApi::CreateLrsInitialRequest(
const XdsBootstrap::XdsServer& server) {
upb::Arena arena;
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
+ server.ShouldUseV3()};
// Create a request.
envoy_service_load_stats_v3_LoadStatsRequest* request =
envoy_service_load_stats_v3_LoadStatsRequest_new(arena.ptr());
@@ -2315,25 +2586,25 @@ grpc_slice XdsApi::CreateLrsInitialRequest(
envoy_config_core_v3_Node* node_msg =
envoy_service_load_stats_v3_LoadStatsRequest_mutable_node(request,
arena.ptr());
- PopulateNode(arena.ptr(), node_, server.ShouldUseV3(), build_version_,
- user_agent_name_, node_msg);
+ PopulateNode(context, node_, build_version_, user_agent_name_, node_msg);
envoy_config_core_v3_Node_add_client_features(
node_msg, upb_strview_makez("envoy.lrs.supports_send_all_clusters"),
arena.ptr());
- MaybeLogLrsRequest(client_, tracer_, symtab_.ptr(), request);
- return SerializeLrsRequest(request, arena.ptr());
+ MaybeLogLrsRequest(context, request);
+ return SerializeLrsRequest(context, request);
}
namespace {
void LocalityStatsPopulate(
+ const EncodingContext& context,
envoy_config_endpoint_v3_UpstreamLocalityStats* output,
const XdsLocalityName& locality_name,
- const XdsClusterLocalityStats::Snapshot& snapshot, upb_arena* arena) {
+ const XdsClusterLocalityStats::Snapshot& snapshot) {
// Set locality.
envoy_config_core_v3_Locality* locality =
- envoy_config_endpoint_v3_UpstreamLocalityStats_mutable_locality(output,
- arena);
+ envoy_config_endpoint_v3_UpstreamLocalityStats_mutable_locality(
+ output, context.arena);
if (!locality_name.region().empty()) {
envoy_config_core_v3_Locality_set_region(
locality, StdStringToUpbString(locality_name.region()));
@@ -2361,7 +2632,7 @@ void LocalityStatsPopulate(
const XdsClusterLocalityStats::BackendMetric& metric_value = p.second;
envoy_config_endpoint_v3_EndpointLoadMetricStats* load_metric =
envoy_config_endpoint_v3_UpstreamLocalityStats_add_load_metric_stats(
- output, arena);
+ output, context.arena);
envoy_config_endpoint_v3_EndpointLoadMetricStats_set_metric_name(
load_metric, StdStringToUpbString(metric_name));
envoy_config_endpoint_v3_EndpointLoadMetricStats_set_num_requests_finished_with_metric(
@@ -2376,6 +2647,8 @@ void LocalityStatsPopulate(
grpc_slice XdsApi::CreateLrsRequest(
ClusterLoadReportMap cluster_load_report_map) {
upb::Arena arena;
+ const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(),
+ false};
// Create a request.
envoy_service_load_stats_v3_LoadStatsRequest* request =
envoy_service_load_stats_v3_LoadStatsRequest_new(arena.ptr());
@@ -2402,8 +2675,7 @@ grpc_slice XdsApi::CreateLrsRequest(
envoy_config_endpoint_v3_UpstreamLocalityStats* locality_stats =
envoy_config_endpoint_v3_ClusterStats_add_upstream_locality_stats(
cluster_stats, arena.ptr());
- LocalityStatsPopulate(locality_stats, locality_name, snapshot,
- arena.ptr());
+ LocalityStatsPopulate(context, locality_stats, locality_name, snapshot);
}
// Add dropped requests.
uint64_t total_dropped_requests = 0;
@@ -2432,8 +2704,8 @@ grpc_slice XdsApi::CreateLrsRequest(
google_protobuf_Duration_set_seconds(load_report_interval, timespec.tv_sec);
google_protobuf_Duration_set_nanos(load_report_interval, timespec.tv_nsec);
}
- MaybeLogLrsRequest(client_, tracer_, symtab_.ptr(), request);
- return SerializeLrsRequest(request, arena.ptr());
+ MaybeLogLrsRequest(context, request);
+ return SerializeLrsRequest(context, request);
}
grpc_error* XdsApi::ParseLrsResponse(const grpc_slice& encoded_response,
diff --git a/src/core/ext/xds/xds_api.h b/src/core/ext/xds/xds_api.h
index 88aeeb43a34..d7f3d90b955 100644
--- a/src/core/ext/xds/xds_api.h
+++ b/src/core/ext/xds/xds_api.h
@@ -36,6 +36,7 @@
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/xds/xds_bootstrap.h"
#include "src/core/ext/xds/xds_client_stats.h"
+#include "src/core/ext/xds/xds_http_filters.h"
#include "src/core/lib/security/authorization/matchers.h"
namespace grpc_core {
@@ -45,6 +46,10 @@ namespace grpc_core {
// default.
bool XdsSecurityEnabled();
+// TODO(lidiz): This will be removed once the fault injection feature is
+// fully integration-tested and enabled by default.
+bool XdsFaultInjectionEnabled();
+
class XdsClient;
class XdsApi {
@@ -58,13 +63,16 @@ class XdsApi {
int64_t seconds = 0;
int32_t nanos = 0;
bool operator==(const Duration& other) const {
- return (seconds == other.seconds && nanos == other.nanos);
+ return seconds == other.seconds && nanos == other.nanos;
}
std::string ToString() const {
return absl::StrFormat("Duration seconds: %ld, nanos %d", seconds, nanos);
}
};
+ using TypedPerFilterConfig =
+ std::map;
+
// TODO(donnadionne): When we can use absl::variant<>, consider using that
// for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters
struct Route {
@@ -75,9 +83,9 @@ class XdsApi {
absl::optional fraction_per_million;
bool operator==(const Matchers& other) const {
- return (path_matcher == other.path_matcher &&
- header_matchers == other.header_matchers &&
- fraction_per_million == other.fraction_per_million);
+ return path_matcher == other.path_matcher &&
+ header_matchers == other.header_matchers &&
+ fraction_per_million == other.fraction_per_million;
}
std::string ToString() const;
};
@@ -91,8 +99,11 @@ class XdsApi {
struct ClusterWeight {
std::string name;
uint32_t weight;
+ TypedPerFilterConfig typed_per_filter_config;
+
bool operator==(const ClusterWeight& other) const {
- return (name == other.name && weight == other.weight);
+ return name == other.name && weight == other.weight &&
+ typed_per_filter_config == other.typed_per_filter_config;
}
std::string ToString() const;
};
@@ -103,11 +114,13 @@ class XdsApi {
// not set.
absl::optional max_stream_duration;
+ TypedPerFilterConfig typed_per_filter_config;
+
bool operator==(const Route& other) const {
- return (matchers == other.matchers &&
- cluster_name == other.cluster_name &&
- weighted_clusters == other.weighted_clusters &&
- max_stream_duration == other.max_stream_duration);
+ return matchers == other.matchers && cluster_name == other.cluster_name &&
+ weighted_clusters == other.weighted_clusters &&
+ max_stream_duration == other.max_stream_duration &&
+ typed_per_filter_config == other.typed_per_filter_config;
}
std::string ToString() const;
};
@@ -116,9 +129,11 @@ class XdsApi {
struct VirtualHost {
std::vector domains;
std::vector routes;
+ TypedPerFilterConfig typed_per_filter_config;
bool operator==(const VirtualHost& other) const {
- return domains == other.domains && routes == other.routes;
+ return domains == other.domains && routes == other.routes &&
+ typed_per_filter_config == other.typed_per_filter_config;
}
};
@@ -214,11 +229,24 @@ class XdsApi {
// Present only if it is inlined in the LDS response.
absl::optional rds_update;
+ struct HttpFilter {
+ std::string name;
+ XdsHttpFilterImpl::FilterConfig config;
+
+ bool operator==(const HttpFilter& other) const {
+ return name == other.name && config == other.config;
+ }
+
+ std::string ToString() const;
+ };
+ std::vector http_filters;
+
bool operator==(const LdsUpdate& other) const {
return downstream_tls_context == other.downstream_tls_context &&
route_config_name == other.route_config_name &&
rds_update == other.rds_update &&
- http_max_stream_duration == other.http_max_stream_duration;
+ http_max_stream_duration == other.http_max_stream_duration &&
+ http_filters == other.http_filters;
}
std::string ToString() const;
@@ -397,7 +425,7 @@ class XdsApi {
std::set resource_names_failed;
};
AdsParseResult ParseAdsResponse(
- const grpc_slice& encoded_response,
+ const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response,
const std::set& expected_listener_names,
const std::set& expected_route_configuration_names,
const std::set& expected_cluster_names,
diff --git a/src/core/ext/xds/xds_client.cc b/src/core/ext/xds/xds_client.cc
index efc1661147b..fddf9f201b2 100644
--- a/src/core/ext/xds/xds_client.cc
+++ b/src/core/ext/xds/xds_client.cc
@@ -38,6 +38,7 @@
#include "src/core/ext/xds/xds_channel_args.h"
#include "src/core/ext/xds/xds_client.h"
#include "src/core/ext/xds/xds_client_stats.h"
+#include "src/core/ext/xds/xds_http_filters.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
@@ -1161,7 +1162,8 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
recv_message_payload_ = nullptr;
// Parse and validate the response.
XdsApi::AdsParseResult result = xds_client()->api_.ParseAdsResponse(
- response_slice, ResourceNamesForRequest(XdsApi::kLdsTypeUrl),
+ chand()->server_, response_slice,
+ ResourceNamesForRequest(XdsApi::kLdsTypeUrl),
ResourceNamesForRequest(XdsApi::kRdsTypeUrl),
ResourceNamesForRequest(XdsApi::kCdsTypeUrl),
ResourceNamesForRequest(XdsApi::kEdsTypeUrl));
@@ -2196,13 +2198,17 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshotLocked(
// accessors for global state
//
-void XdsClientGlobalInit() { g_mu = new Mutex; }
+void XdsClientGlobalInit() {
+ g_mu = new Mutex;
+ XdsHttpFilterRegistry::Init();
+}
void XdsClientGlobalShutdown() {
delete g_mu;
g_mu = nullptr;
gpr_free(g_fallback_bootstrap_config);
g_fallback_bootstrap_config = nullptr;
+ XdsHttpFilterRegistry::Shutdown();
}
RefCountedPtr XdsClient::GetOrCreate(grpc_error** error) {
diff --git a/src/core/ext/xds/xds_http_filters.cc b/src/core/ext/xds/xds_http_filters.cc
new file mode 100644
index 00000000000..11b644339b6
--- /dev/null
+++ b/src/core/ext/xds/xds_http_filters.cc
@@ -0,0 +1,107 @@
+//
+// Copyright 2021 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include
+
+#include "src/core/ext/xds/xds_http_filters.h"
+
+#include "envoy/extensions/filters/http/router/v3/router.upb.h"
+#include "envoy/extensions/filters/http/router/v3/router.upbdefs.h"
+
+namespace grpc_core {
+
+const char* kXdsHttpRouterFilterConfigName =
+ "envoy.extensions.filters.http.router.v3.Router";
+
+namespace {
+
+class XdsHttpRouterFilter : public XdsHttpFilterImpl {
+ public:
+ void PopulateSymtab(upb_symtab* symtab) const override {
+ envoy_extensions_filters_http_router_v3_Router_getmsgdef(symtab);
+ }
+
+ absl::StatusOr GenerateFilterConfig(
+ upb_strview serialized_filter_config, upb_arena* arena) const override {
+ if (envoy_extensions_filters_http_router_v3_Router_parse(
+ serialized_filter_config.data, serialized_filter_config.size,
+ arena) == nullptr) {
+ return absl::InvalidArgumentError("could not parse router filter config");
+ }
+ return FilterConfig{kXdsHttpRouterFilterConfigName, Json()};
+ }
+
+ absl::StatusOr GenerateFilterConfigOverride(
+ upb_strview /*serialized_filter_config*/,
+ upb_arena* /*arena*/) const override {
+ return absl::InvalidArgumentError(
+ "router filter does not support config override");
+ }
+
+ // No-op -- this filter is special-cased by the xds resolver.
+ const grpc_channel_filter* channel_filter() const override { return nullptr; }
+
+ // No-op -- this filter is special-cased by the xds resolver.
+ absl::StatusOr GenerateServiceConfig(
+ const FilterConfig& /*hcm_filter_config*/,
+ const FilterConfig* /*filter_config_override*/) const override {
+ return absl::UnimplementedError("router filter should never be called");
+ }
+};
+
+using FilterOwnerList = std::vector>;
+using FilterRegistryMap = std::map;
+
+FilterOwnerList* g_filters = nullptr;
+FilterRegistryMap* g_filter_registry = nullptr;
+
+} // namespace
+
+void XdsHttpFilterRegistry::RegisterFilter(
+ std::unique_ptr filter,
+ const std::set& config_proto_type_names) {
+ for (auto config_proto_type_name : config_proto_type_names) {
+ (*g_filter_registry)[config_proto_type_name] = filter.get();
+ }
+ g_filters->push_back(std::move(filter));
+}
+
+const XdsHttpFilterImpl* XdsHttpFilterRegistry::GetFilterForType(
+ absl::string_view proto_type_name) {
+ auto it = g_filter_registry->find(proto_type_name);
+ if (it == g_filter_registry->end()) return nullptr;
+ return it->second;
+}
+
+void XdsHttpFilterRegistry::PopulateSymtab(upb_symtab* symtab) {
+ for (const auto& filter : *g_filters) {
+ filter->PopulateSymtab(symtab);
+ }
+}
+
+void XdsHttpFilterRegistry::Init() {
+ g_filters = new FilterOwnerList;
+ g_filter_registry = new FilterRegistryMap;
+ RegisterFilter(absl::make_unique(),
+ {kXdsHttpRouterFilterConfigName});
+}
+
+void XdsHttpFilterRegistry::Shutdown() {
+ delete g_filter_registry;
+ delete g_filters;
+}
+
+} // namespace grpc_core
diff --git a/src/core/ext/xds/xds_http_filters.h b/src/core/ext/xds/xds_http_filters.h
new file mode 100644
index 00000000000..61e96cde665
--- /dev/null
+++ b/src/core/ext/xds/xds_http_filters.h
@@ -0,0 +1,124 @@
+//
+// Copyright 2021 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_CORE_EXT_XDS_XDS_HTTP_FILTERS_H
+#define GRPC_CORE_EXT_XDS_XDS_HTTP_FILTERS_H
+
+#include
+
+#include
+#include
+#include
+
+#include "absl/status/statusor.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/any.upb.h"
+#include "upb/def.h"
+
+#include
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/json/json.h"
+
+namespace grpc_core {
+
+extern const char* kXdsHttpRouterFilterConfigName;
+
+class XdsHttpFilterImpl {
+ public:
+ struct FilterConfig {
+ absl::string_view config_proto_type_name;
+ Json config;
+
+ bool operator==(const FilterConfig& other) const {
+ return config_proto_type_name == other.config_proto_type_name &&
+ config == other.config;
+ }
+ std::string ToString() const {
+ return absl::StrCat("{config_proto_type_name=", config_proto_type_name,
+ " config=", config.Dump(), "}");
+ }
+ };
+
+ // Service config data for the filter, returned by GenerateServiceConfig().
+ struct ServiceConfigJsonEntry {
+ // The top-level field name in the method config.
+ // Filter implementations should use their primary config proto type
+ // name for this.
+ // The value of this field in the method config will be a JSON array,
+ // which will be populated with the elements returned by each filter
+ // instance.
+ std::string service_config_field_name;
+ // The element to add to the JSON array.
+ std::string element;
+ };
+
+ virtual ~XdsHttpFilterImpl() = default;
+
+ // Loads the proto message into the upb symtab.
+ virtual void PopulateSymtab(upb_symtab* symtab) const = 0;
+
+ // Generates a Config from the xDS filter config proto.
+ // Used for the top-level config in the HCM HTTP filter list.
+ virtual absl::StatusOr GenerateFilterConfig(
+ upb_strview serialized_filter_config, upb_arena* arena) const = 0;
+
+ // Generates a Config from the xDS filter config proto.
+ // Used for the typed_per_filter_config override in VirtualHost and Route.
+ virtual absl::StatusOr GenerateFilterConfigOverride(
+ upb_strview serialized_filter_config, upb_arena* arena) const = 0;
+
+ // C-core channel filter implementation.
+ virtual const grpc_channel_filter* channel_filter() const = 0;
+
+ // Modifies channel args that may affect service config parsing (not
+ // visible to the channel as a whole).
+ // Takes ownership of args. Caller takes ownership of return value.
+ virtual grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) const {
+ return args;
+ }
+
+ // Function to convert the Configs into a JSON string to be added to the
+ // per-method part of the service config.
+ // The hcm_filter_config comes from the HttpConnectionManager config.
+ // The filter_config_override comes from the first of the ClusterWeight,
+ // Route, or VirtualHost entries that it is found in, or null if
+ // there is no override in any of those locations.
+ virtual absl::StatusOr GenerateServiceConfig(
+ const FilterConfig& hcm_filter_config,
+ const FilterConfig* filter_config_override) const = 0;
+};
+
+class XdsHttpFilterRegistry {
+ public:
+ static void RegisterFilter(
+ std::unique_ptr filter,
+ const std::set& config_proto_type_names);
+
+ static const XdsHttpFilterImpl* GetFilterForType(
+ absl::string_view proto_type_name);
+
+ static void PopulateSymtab(upb_symtab* symtab);
+
+ // Global init and shutdown.
+ static void Init();
+ static void Shutdown();
+};
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_XDS_XDS_HTTP_FILTERS_H */
diff --git a/src/core/lib/channel/channel_stack.cc b/src/core/lib/channel/channel_stack.cc
index e9b348972f2..60b83667c54 100644
--- a/src/core/lib/channel/channel_stack.cc
+++ b/src/core/lib/channel/channel_stack.cc
@@ -81,6 +81,18 @@ grpc_channel_element* grpc_channel_stack_last_element(
return grpc_channel_stack_element(channel_stack, channel_stack->count - 1);
}
+size_t grpc_channel_stack_filter_instance_number(
+ grpc_channel_stack* channel_stack, grpc_channel_element* elem) {
+ size_t num_found = 0;
+ for (size_t i = 0; i < channel_stack->count; ++i) {
+ grpc_channel_element* element =
+ grpc_channel_stack_element(channel_stack, i);
+ if (element == elem) break;
+ if (element->filter == elem->filter) ++num_found;
+ }
+ return num_found;
+}
+
grpc_call_element* grpc_call_stack_element(grpc_call_stack* call_stack,
size_t index) {
return CALL_ELEMS_FROM_STACK(call_stack) + index;
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index e297df9488d..1573ae1e056 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -204,6 +204,13 @@ grpc_channel_element* grpc_channel_stack_element(grpc_channel_stack* stack,
/* Get the last channel element in a channel stack */
grpc_channel_element* grpc_channel_stack_last_element(
grpc_channel_stack* stack);
+
+// A utility function for a filter to determine how many other instances
+// of the same filter exist above it in the same stack. Intended to be
+// used in the filter's init_channel_elem() method.
+size_t grpc_channel_stack_filter_instance_number(
+ grpc_channel_stack* channel_stack, grpc_channel_element* elem);
+
/* Get a call stack element given a call stack and an index */
grpc_call_element* grpc_call_stack_element(grpc_call_stack* stack, size_t i);
diff --git a/src/core/lib/surface/lame_client.cc b/src/core/lib/surface/lame_client.cc
index d32cc28ea65..f92c1920df3 100644
--- a/src/core/lib/surface/lame_client.cc
+++ b/src/core/lib/surface/lame_client.cc
@@ -35,12 +35,20 @@
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/static_metadata.h"
+#define GRPC_ARG_LAME_FILTER_ERROR "grpc.lame_filter_error"
+
namespace grpc_core {
namespace {
struct ChannelData {
- ChannelData() : state_tracker("lame_channel", GRPC_CHANNEL_SHUTDOWN) {}
+ explicit ChannelData(grpc_channel_element_args* args)
+ : state_tracker("lame_channel", GRPC_CHANNEL_SHUTDOWN) {
+ grpc_error* err = grpc_channel_args_find_pointer(
+ args->channel_args, GRPC_ARG_LAME_FILTER_ERROR);
+ if (err != nullptr) error = GRPC_ERROR_REF(err);
+ }
+
~ChannelData() { GRPC_ERROR_UNREF(error); }
grpc_error* error = GRPC_ERROR_NONE;
@@ -105,9 +113,7 @@ static void lame_destroy_call_elem(grpc_call_element* /*elem*/,
static grpc_error* lame_init_channel_elem(grpc_channel_element* elem,
grpc_channel_element_args* args) {
- GPR_ASSERT(args->is_first);
- GPR_ASSERT(args->is_last);
- new (elem->channel_data) ChannelData;
+ new (elem->channel_data) ChannelData(args);
return GRPC_ERROR_NONE;
}
@@ -116,12 +122,25 @@ static void lame_destroy_channel_elem(grpc_channel_element* elem) {
chand->~ChannelData();
}
+// Channel arg vtable for a grpc_error*.
+void* ErrorCopy(void* p) {
+ grpc_error* error = static_cast(p);
+ return GRPC_ERROR_REF(error);
+}
+void ErrorDestroy(void* p) {
+ grpc_error* error = static_cast(p);
+ GRPC_ERROR_UNREF(error);
+}
+int ErrorCompare(void* p, void* q) { return GPR_ICMP(p, q); }
+const grpc_arg_pointer_vtable kLameFilterErrorArgVtable = {
+ ErrorCopy, ErrorDestroy, ErrorCompare};
+
} // namespace
-void SetLameFilterError(grpc_channel_element* elem, grpc_error* error) {
- GPR_ASSERT(elem->filter == &grpc_lame_filter);
- auto chand = static_cast(elem->channel_data);
- chand->error = error;
+grpc_arg MakeLameClientErrorArg(grpc_error* error) {
+ return grpc_channel_arg_pointer_create(
+ const_cast(GRPC_ARG_LAME_FILTER_ERROR), error,
+ &kLameFilterErrorArgVtable);
}
} // namespace grpc_core
@@ -146,20 +165,20 @@ grpc_channel* grpc_lame_client_channel_create(const char* target,
grpc_status_code error_code,
const char* error_message) {
grpc_core::ExecCtx exec_ctx;
- grpc_channel_element* elem;
- grpc_channel* channel =
- grpc_channel_create(target, nullptr, GRPC_CLIENT_LAME_CHANNEL, nullptr);
- elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
GRPC_API_TRACE(
"grpc_lame_client_channel_create(target=%s, error_code=%d, "
"error_message=%s)",
3, (target, (int)error_code, error_message));
- grpc_core::SetLameFilterError(
- elem, grpc_error_set_str(
- grpc_error_set_int(
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("lame client channel"),
- GRPC_ERROR_INT_GRPC_STATUS, error_code),
- GRPC_ERROR_STR_GRPC_MESSAGE,
- grpc_slice_from_static_string(error_message)));
+ grpc_error* error = grpc_error_set_str(
+ grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("lame client channel"),
+ GRPC_ERROR_INT_GRPC_STATUS, error_code),
+ GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string(error_message));
+ grpc_arg error_arg = grpc_core::MakeLameClientErrorArg(error);
+ grpc_channel_args args = {1, &error_arg};
+ grpc_channel* channel =
+ grpc_channel_create(target, &args, GRPC_CLIENT_LAME_CHANNEL, nullptr);
+ GRPC_ERROR_UNREF(error);
return channel;
}
diff --git a/src/core/lib/surface/lame_client.h b/src/core/lib/surface/lame_client.h
index 8fd3f4eb6c3..94c7e553ad8 100644
--- a/src/core/lib/surface/lame_client.h
+++ b/src/core/lib/surface/lame_client.h
@@ -23,10 +23,11 @@
#include "src/core/lib/channel/channel_stack.h"
-extern const grpc_channel_filter grpc_lame_filter;
-
namespace grpc_core {
-void SetLameFilterError(grpc_channel_element* elem, grpc_error* error);
+// Does NOT take ownership of error.
+grpc_arg MakeLameClientErrorArg(grpc_error* error);
} // namespace grpc_core
+extern const grpc_channel_filter grpc_lame_filter;
+
#endif /* GRPC_CORE_LIB_SURFACE_LAME_CLIENT_H */
diff --git a/src/proto/grpc/testing/xds/v3/BUILD b/src/proto/grpc/testing/xds/v3/BUILD
index 6d212fa72c1..024cd63d786 100644
--- a/src/proto/grpc/testing/xds/v3/BUILD
+++ b/src/proto/grpc/testing/xds/v3/BUILD
@@ -186,6 +186,7 @@ grpc_proto_library(
srcs = [
"http_connection_manager.proto",
],
+ well_known_protos = True,
deps = [
"config_source_proto",
"protocol_proto",
@@ -193,6 +194,13 @@ grpc_proto_library(
],
)
+grpc_proto_library(
+ name = "router_proto",
+ srcs = [
+ "router.proto",
+ ],
+)
+
grpc_proto_library(
name = "string_proto",
srcs = [
diff --git a/src/proto/grpc/testing/xds/v3/http_connection_manager.proto b/src/proto/grpc/testing/xds/v3/http_connection_manager.proto
index 786ac0f01dc..74477073c70 100644
--- a/src/proto/grpc/testing/xds/v3/http_connection_manager.proto
+++ b/src/proto/grpc/testing/xds/v3/http_connection_manager.proto
@@ -18,6 +18,8 @@ syntax = "proto3";
package envoy.extensions.filters.network.http_connection_manager.v3;
+import "google/protobuf/any.proto";
+
import "src/proto/grpc/testing/xds/v3/config_source.proto";
import "src/proto/grpc/testing/xds/v3/protocol.proto";
import "src/proto/grpc/testing/xds/v3/route.proto";
@@ -40,6 +42,11 @@ message HttpConnectionManager {
ScopedRoutes scoped_routes = 31;
}
+ // A list of individual HTTP filters that make up the filter chain for
+ // requests made to the connection manager. :ref:`Order matters `
+ // as the filters are processed sequentially as request events happen.
+ repeated HttpFilter http_filters = 5;
+
// Additional settings for HTTP requests handled by the connection manager. These will be
// applicable to both HTTP1 and HTTP2 requests.
config.core.v3.HttpProtocolOptions common_http_protocol_options = 35;
@@ -58,3 +65,18 @@ message Rds {
message ScopedRoutes {
}
+
+message HttpFilter {
+ // The name of the filter configuration. The name is used as a fallback to
+ // select an extension if the type of the configuration proto is not
+ // sufficient. It also serves as a resource name in ExtensionConfigDS.
+ string name = 1;
+
+ oneof config_type {
+ // Filter specific configuration which depends on the filter being instantiated. See the supported
+ // filters for further documentation.
+ google.protobuf.Any typed_config = 4;
+ }
+
+ bool is_optional = 6;
+}
diff --git a/src/proto/grpc/testing/xds/v3/route.proto b/src/proto/grpc/testing/xds/v3/route.proto
index b7fc40b279e..baeaaf644d4 100644
--- a/src/proto/grpc/testing/xds/v3/route.proto
+++ b/src/proto/grpc/testing/xds/v3/route.proto
@@ -23,6 +23,7 @@ import "src/proto/grpc/testing/xds/v3/regex.proto";
import "src/proto/grpc/testing/xds/v3/percent.proto";
import "src/proto/grpc/testing/xds/v3/range.proto";
+import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";
@@ -64,6 +65,13 @@ message VirtualHost {
// The list of routes that will be matched, in order, for incoming requests.
// The first route that matches will be used.
repeated Route routes = 3;
+
+ // The per_filter_config field can be used to provide virtual host-specific
+ // configurations for filters. The key should match the filter name, such as
+ // *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter
+ // specific; see the :ref:`HTTP filter documentation `
+ // for if and how it is utilized.
+ map typed_per_filter_config = 15;
}
// A route is both a specification of how to match a request as well as an indication of what to do
@@ -88,6 +96,13 @@ message Route {
// Return a redirect.
RedirectAction redirect = 3;
}
+
+ // The typed_per_filter_config field can be used to provide route-specific
+ // configurations for filters. The key should match the filter name, such as
+ // *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter
+ // specific; see the :ref:`HTTP filter documentation ` for
+ // if and how it is utilized.
+ map typed_per_filter_config = 13;
}
// Compared to the :ref:`cluster ` field that specifies a
@@ -108,6 +123,13 @@ message WeightedCluster {
// the choice of an upstream cluster is determined by its weight. The sum of weights across all
// entries in the clusters array must add up to the total_weight, which defaults to 100.
google.protobuf.UInt32Value weight = 2;
+
+ // The per_filter_config field can be used to provide weighted cluster-specific
+ // configurations for filters. The key should match the filter name, such as
+ // *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter
+ // specific; see the :ref:`HTTP filter documentation `
+ // for if and how it is utilized.
+ map typed_per_filter_config = 10;
}
// Specifies one or more upstream clusters associated with the route.
@@ -334,3 +356,13 @@ message RouteConfiguration {
message RedirectAction {
}
+
+message FilterConfig {
+ // The filter config.
+ google.protobuf.Any config = 1;
+
+ // If true, the filter is optional, meaning that if the client does
+ // not support the specified filter, it may ignore the map entry rather
+ // than rejecting the config.
+ bool is_optional = 2;
+}
diff --git a/src/proto/grpc/testing/xds/v3/router.proto b/src/proto/grpc/testing/xds/v3/router.proto
new file mode 100644
index 00000000000..00b11b37128
--- /dev/null
+++ b/src/proto/grpc/testing/xds/v3/router.proto
@@ -0,0 +1,28 @@
+// Copyright 2021 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Local copy of Envoy xDS proto file, used for testing only.
+
+syntax = "proto3";
+
+package envoy.extensions.filters.http.router.v3;
+
+// [#protodoc-title: Router]
+// Router :ref:`configuration overview `.
+// [#extension: envoy.filters.http.router]
+
+// We don't actually use any of the fields in this message, but we need
+// the message itself to signify which filter to use.
+message Router {
+}
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 68e641c8966..0cc1ff89eeb 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -153,6 +153,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c',
'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c',
'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c',
+ 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c',
'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c',
'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c',
@@ -201,6 +202,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
+ 'src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.c',
'src/core/ext/upb-generated/xds/core/v3/authority.upb.c',
'src/core/ext/upb-generated/xds/core/v3/collection_entry.upb.c',
@@ -240,6 +242,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c',
+ 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c',
'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/common.upbdefs.c',
@@ -280,6 +283,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upbdefs-generated/udpa/annotations/sensitive.upbdefs.c',
'src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c',
'src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c',
+ 'src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c',
'src/core/ext/upbdefs-generated/validate/validate.upbdefs.c',
'src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c',
'src/core/ext/upbdefs-generated/xds/core/v3/collection_entry.upbdefs.c',
@@ -295,6 +299,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/xds/xds_certificate_provider.cc',
'src/core/ext/xds/xds_client.cc',
'src/core/ext/xds/xds_client_stats.cc',
+ 'src/core/ext/xds/xds_http_filters.cc',
'src/core/ext/xds/xds_server_config_fetcher.cc',
'src/core/lib/avl/avl.cc',
'src/core/lib/backoff/backoff.cc',
diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD
index d0bee59ff8b..f637482c610 100644
--- a/test/cpp/end2end/BUILD
+++ b/test/cpp/end2end/BUILD
@@ -544,6 +544,7 @@ grpc_cc_test(
"//src/proto/grpc/testing/xds/v3:listener_proto",
"//src/proto/grpc/testing/xds/v3:lrs_proto",
"//src/proto/grpc/testing/xds/v3:route_proto",
+ "//src/proto/grpc/testing/xds/v3:router_proto",
"//src/proto/grpc/testing/xds/v3:tls_proto",
"//test/core/util:grpc_test_util",
"//test/cpp/util:test_util",
diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc
index e1033f2fdb3..cce899eb3e4 100644
--- a/test/cpp/end2end/xds_end2end_test.cc
+++ b/test/cpp/end2end/xds_end2end_test.cc
@@ -91,6 +91,7 @@
#include "src/proto/grpc/testing/xds/v3/listener.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/route.grpc.pb.h"
+#include "src/proto/grpc/testing/xds/v3/router.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/tls.grpc.pb.h"
namespace grpc {
@@ -1580,6 +1581,13 @@ class XdsEnd2endTest : public ::testing::TestWithParam {
// Initialize default xDS resources.
// Construct LDS resource.
default_listener_.set_name(kServerName);
+ HttpConnectionManager http_connection_manager;
+ auto* filter = http_connection_manager.add_http_filters();
+ filter->set_name("router");
+ filter->mutable_typed_config()->PackFrom(
+ envoy::extensions::filters::http::router::v3::Router());
+ default_listener_.mutable_api_listener()->mutable_api_listener()->PackFrom(
+ http_connection_manager);
// Construct RDS resource.
default_route_config_.set_name(kDefaultRouteConfigurationName);
auto* virtual_host = default_route_config_.add_virtual_hosts();
@@ -1985,6 +1993,10 @@ class XdsEnd2endTest : public ::testing::TestWithParam {
static Listener BuildListener(const RouteConfiguration& route_config) {
HttpConnectionManager http_connection_manager;
*(http_connection_manager.mutable_route_config()) = route_config;
+ auto* filter = http_connection_manager.add_http_filters();
+ filter->set_name("router");
+ filter->mutable_typed_config()->PackFrom(
+ envoy::extensions::filters::http::router::v3::Router());
Listener listener;
listener.set_name(kServerName);
listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
@@ -2603,6 +2615,8 @@ TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) {
// Manually configure use of RDS.
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
auto* rds = http_connection_manager.mutable_rds();
rds->set_route_config_name(kDefaultRouteConfigurationName);
rds->mutable_config_source()->mutable_ads();
@@ -3004,7 +3018,7 @@ TEST_P(LdsTest, NoApiListener) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
@@ -3017,6 +3031,8 @@ TEST_P(LdsTest, NoApiListener) {
TEST_P(LdsTest, WrongRouteSpecifier) {
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
http_connection_manager.mutable_scoped_routes();
listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
http_connection_manager);
@@ -3024,7 +3040,7 @@ TEST_P(LdsTest, WrongRouteSpecifier) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
@@ -3038,6 +3054,8 @@ TEST_P(LdsTest, WrongRouteSpecifier) {
TEST_P(LdsTest, RdsMissingConfigSource) {
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
http_connection_manager.mutable_rds()->set_route_config_name(
kDefaultRouteConfigurationName);
listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
@@ -3046,7 +3064,7 @@ TEST_P(LdsTest, RdsMissingConfigSource) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -3059,6 +3077,8 @@ TEST_P(LdsTest, RdsMissingConfigSource) {
TEST_P(LdsTest, RdsConfigSourceDoesNotSpecifyAds) {
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
auto* rds = http_connection_manager.mutable_rds();
rds->set_route_config_name(kDefaultRouteConfigurationName);
rds->mutable_config_source()->mutable_self();
@@ -3068,7 +3088,7 @@ TEST_P(LdsTest, RdsConfigSourceDoesNotSpecifyAds) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
@@ -3096,7 +3116,7 @@ TEST_P(LdsTest, MultipleBadResources) {
EchoResponse response;
grpc::Status status = stub2->Echo(&context, request, &response);
EXPECT_FALSE(status.ok());
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
@@ -3109,6 +3129,196 @@ TEST_P(LdsTest, MultipleBadResources) {
": Listener has neither address nor ApiListener"))));
}
+// TODO(roth): Remove this test when we remove the
+// GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION environment variable guard.
+TEST_P(LdsTest, HttpFiltersEnabled) {
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ SetNextResolutionForLbChannelAllBalancers();
+ AdsServiceImpl::EdsResourceArgs args({
+ {"locality0", GetBackendPorts()},
+ });
+ balancers_[0]->ads_service()->SetEdsResource(
+ BuildEdsResource(args, DefaultEdsServiceName()));
+ WaitForAllBackends();
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we fail RPCs if there is no router filter.
+TEST_P(LdsTest, FailRpcsIfNoHttpRouterFilter) {
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ SetNextResolutionForLbChannelAllBalancers();
+ auto listener = default_listener_;
+ HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
+ http_connection_manager.clear_http_filters();
+ listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+ http_connection_manager);
+ SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+ AdsServiceImpl::EdsResourceArgs args({
+ {"locality0", GetBackendPorts()},
+ });
+ balancers_[0]->ads_service()->SetEdsResource(
+ BuildEdsResource(args, DefaultEdsServiceName()));
+ Status status = SendRpc();
+ EXPECT_EQ(status.error_code(), StatusCode::UNAVAILABLE);
+ EXPECT_EQ(status.error_message(), "no xDS HTTP router filter configured");
+ // Wait until xDS server sees ACK.
+ while (balancers_[0]->ads_service()->lds_response_state().state ==
+ AdsServiceImpl::ResponseState::SENT) {
+ CheckRpcSendFailure();
+ }
+ const auto response_state =
+ balancers_[0]->ads_service()->lds_response_state();
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// TODO(lidiz): As part of adding the fault injection filter, add a test
+// that we ignore filters after the router filter.
+
+// Test that we NACK empty filter names.
+TEST_P(LdsTest, RejectsEmptyHttpFilterName) {
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ auto listener = default_listener_;
+ HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
+ auto* filter = http_connection_manager.add_http_filters();
+ filter->mutable_typed_config()->PackFrom(Listener());
+ listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+ http_connection_manager);
+ SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (balancers_[0]->ads_service()->lds_response_state().state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state =
+ balancers_[0]->ads_service()->lds_response_state();
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(response_state.error_message,
+ ::testing::HasSubstr("empty filter name at index 1"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK duplicate HTTP filter names.
+TEST_P(LdsTest, RejectsDuplicateHttpFilterName) {
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ auto listener = default_listener_;
+ HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
+ *http_connection_manager.add_http_filters() =
+ http_connection_manager.http_filters(0);
+ listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+ http_connection_manager);
+ SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (balancers_[0]->ads_service()->lds_response_state().state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state =
+ balancers_[0]->ads_service()->lds_response_state();
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(response_state.error_message,
+ ::testing::HasSubstr("duplicate HTTP filter name: router"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK unknown filter types.
+TEST_P(LdsTest, RejectsUnknownHttpFilterType) {
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ auto listener = default_listener_;
+ HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
+ auto* filter = http_connection_manager.add_http_filters();
+ filter->set_name("unknown");
+ filter->mutable_typed_config()->PackFrom(Listener());
+ listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+ http_connection_manager);
+ SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (balancers_[0]->ads_service()->lds_response_state().state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state =
+ balancers_[0]->ads_service()->lds_response_state();
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(response_state.error_message,
+ ::testing::HasSubstr("no filter registered for config type "
+ "envoy.config.listener.v3.Listener"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we ignore optional unknown filter types.
+TEST_P(LdsTest, IgnoresOptionalUnknownHttpFilterType) {
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ auto listener = default_listener_;
+ HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
+ auto* filter = http_connection_manager.add_http_filters();
+ filter->set_name("unknown");
+ filter->mutable_typed_config()->PackFrom(Listener());
+ filter->set_is_optional(true);
+ listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+ http_connection_manager);
+ SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+ AdsServiceImpl::EdsResourceArgs args({
+ {"locality0", GetBackendPorts()},
+ });
+ balancers_[0]->ads_service()->SetEdsResource(
+ BuildEdsResource(args, DefaultEdsServiceName()));
+ SetNextResolutionForLbChannelAllBalancers();
+ WaitForAllBackends();
+ EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state,
+ AdsServiceImpl::ResponseState::ACKED);
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK unparseable filter configs.
+TEST_P(LdsTest, RejectsUnparseableHttpFilterType) {
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ auto listener = default_listener_;
+ HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
+ auto* filter = http_connection_manager.add_http_filters();
+ filter->set_name("unknown");
+ filter->mutable_typed_config()->PackFrom(listener);
+ filter->mutable_typed_config()->set_type_url(
+ "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router");
+ listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
+ http_connection_manager);
+ SetListenerAndRouteConfiguration(0, listener, default_route_config_);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (balancers_[0]->ads_service()->lds_response_state().state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state =
+ balancers_[0]->ads_service()->lds_response_state();
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(
+ response_state.error_message,
+ ::testing::HasSubstr(
+ "filter config for type "
+ "envoy.extensions.filters.http.router.v3.Router failed to parse"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
using LdsRdsTest = BasicTest;
// Tests that LDS client should send an ACK upon correct LDS response (with
@@ -3160,7 +3370,7 @@ TEST_P(LdsRdsTest, NoMatchedDomain) {
CheckRpcSendFailure();
// Do a bit of polling, to allow the ACK to get to the ADS server.
channel_->WaitForConnected(grpc_timeout_milliseconds_to_deadline(100));
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
}
@@ -3207,7 +3417,7 @@ TEST_P(LdsRdsTest, RouteMatchHasQueryParameters) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3226,7 +3436,7 @@ TEST_P(LdsRdsTest, RouteMatchHasValidPrefixEmptyOrSingleSlash) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
(void)SendRpc();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
}
@@ -3240,7 +3450,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNoLeadingSlash) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3256,7 +3466,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixExtraContent) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3272,7 +3482,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixDoubleSlash) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3288,7 +3498,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPathEmptyPath) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3304,7 +3514,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPathNoLeadingSlash) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3320,7 +3530,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPathTooManySlashes) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3336,7 +3546,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPathOnlyOneSlash) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3352,7 +3562,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingService) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3368,7 +3578,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingMethod) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No valid routes specified."));
@@ -3385,7 +3595,7 @@ TEST_P(LdsRdsTest, RouteMatchHasInvalidPathRegex) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr(
@@ -3401,7 +3611,7 @@ TEST_P(LdsRdsTest, RouteHasNoRouteAction) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr("No RouteAction found in route."));
@@ -3419,7 +3629,7 @@ TEST_P(LdsRdsTest, RouteActionClusterHasEmptyClusterName) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
response_state.error_message,
@@ -3447,7 +3657,7 @@ TEST_P(LdsRdsTest, RouteActionWeightedTargetHasIncorrectTotalWeightSet) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr(
@@ -3474,7 +3684,7 @@ TEST_P(LdsRdsTest, RouteActionWeightedClusterHasZeroTotalWeight) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
response_state.error_message,
@@ -3502,7 +3712,7 @@ TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasEmptyClusterName) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
response_state.error_message,
@@ -3530,7 +3740,7 @@ TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasNoWeight) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr(
@@ -3550,7 +3760,7 @@ TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRegex) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
response_state.error_message,
@@ -3572,7 +3782,7 @@ TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRange) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
response_state.error_message,
@@ -4634,6 +4844,8 @@ TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) {
// Construct listener.
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
// Set up HTTP max_stream_duration of 3.5 seconds
auto* duration =
http_connection_manager.mutable_common_http_protocol_options()
@@ -4772,6 +4984,8 @@ TEST_P(LdsRdsTest, XdsRoutingHttpTimeoutDisabled) {
// Construct listener.
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
// Set up HTTP max_stream_duration of 3.5 seconds
auto* duration =
http_connection_manager.mutable_common_http_protocol_options()
@@ -4837,6 +5051,8 @@ TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenXdsTimeoutExplicit0) {
// Construct listener.
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
// Set up HTTP max_stream_duration of 3.5 seconds
auto* duration =
http_connection_manager.mutable_common_http_protocol_options()
@@ -4910,14 +5126,16 @@ TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenHttpTimeoutExplicit0) {
{"locality0", {g_port_saver->GetPort()}},
});
balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
+ auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
+ listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
+ &http_connection_manager);
// Set up HTTP max_stream_duration to be explicit 0
auto* duration =
http_connection_manager.mutable_common_http_protocol_options()
->mutable_max_stream_duration();
duration->set_seconds(0);
duration->set_nanos(0);
- auto listener = default_listener_;
listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
http_connection_manager);
// Set listener and route config.
@@ -5043,7 +5261,7 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) {
EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
EXPECT_EQ(kNumEcho1Rpcs, backends_[1]->backend_service1()->request_count());
EXPECT_EQ(0, backends_[1]->backend_service2()->request_count());
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
}
@@ -5090,7 +5308,7 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderContentType) {
CheckRpcSendOk(kNumEchoRpcs);
EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
}
@@ -5158,7 +5376,7 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) {
EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
EXPECT_EQ(0, backends_[1]->backend_service()->request_count());
EXPECT_EQ(0, backends_[2]->backend_service()->request_count());
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
}
@@ -5215,7 +5433,7 @@ TEST_P(LdsRdsTest, XdsRoutingRuntimeFractionMatching) {
(1 - kErrorTolerance)),
::testing::Le(static_cast(kNumRpcs) * 25 / 100 *
(1 + kErrorTolerance))));
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
}
@@ -5314,7 +5532,7 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingUnmatchCases) {
EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count());
EXPECT_EQ(kNumEcho1Rpcs, backends_[0]->backend_service1()->request_count());
EXPECT_EQ(0, backends_[0]->backend_service2()->request_count());
- const auto& response_state = RouteConfigurationResponseState(0);
+ const auto response_state = RouteConfigurationResponseState(0);
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED);
}
@@ -5381,6 +5599,253 @@ TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) {
EXPECT_EQ(1, backends_[1]->backend_service2()->request_count());
}
+// Test that we NACK unknown filter types in VirtualHost.
+TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* per_filter_config =
+ route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+ (*per_filter_config)["unknown"].PackFrom(Listener());
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (RouteConfigurationResponseState(0).state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state = RouteConfigurationResponseState(0);
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(response_state.error_message,
+ ::testing::HasSubstr("no filter registered for config type "
+ "envoy.config.listener.v3.Listener"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we ignore optional unknown filter types in VirtualHost.
+TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* per_filter_config =
+ route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+ ::envoy::config::route::v3::FilterConfig filter_config;
+ filter_config.mutable_config()->PackFrom(Listener());
+ filter_config.set_is_optional(true);
+ (*per_filter_config)["unknown"].PackFrom(filter_config);
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ AdsServiceImpl::EdsResourceArgs args({
+ {"locality0", GetBackendPorts()},
+ });
+ balancers_[0]->ads_service()->SetEdsResource(
+ BuildEdsResource(args, DefaultEdsServiceName()));
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ WaitForAllBackends();
+ EXPECT_EQ(RouteConfigurationResponseState(0).state,
+ AdsServiceImpl::ResponseState::ACKED);
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK unparseable filter types in VirtualHost.
+TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* per_filter_config =
+ route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
+ (*per_filter_config)["unknown"].PackFrom(
+ envoy::extensions::filters::http::router::v3::Router());
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (RouteConfigurationResponseState(0).state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state = RouteConfigurationResponseState(0);
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(
+ response_state.error_message,
+ ::testing::HasSubstr("router filter does not support config override"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK unknown filter types in Route.
+TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+ ->mutable_routes(0)
+ ->mutable_typed_per_filter_config();
+ (*per_filter_config)["unknown"].PackFrom(Listener());
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (RouteConfigurationResponseState(0).state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state = RouteConfigurationResponseState(0);
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(response_state.error_message,
+ ::testing::HasSubstr("no filter registered for config type "
+ "envoy.config.listener.v3.Listener"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we ignore optional unknown filter types in Route.
+TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+ ->mutable_routes(0)
+ ->mutable_typed_per_filter_config();
+ ::envoy::config::route::v3::FilterConfig filter_config;
+ filter_config.mutable_config()->PackFrom(Listener());
+ filter_config.set_is_optional(true);
+ (*per_filter_config)["unknown"].PackFrom(filter_config);
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ AdsServiceImpl::EdsResourceArgs args({
+ {"locality0", GetBackendPorts()},
+ });
+ balancers_[0]->ads_service()->SetEdsResource(
+ BuildEdsResource(args, DefaultEdsServiceName()));
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ WaitForAllBackends();
+ EXPECT_EQ(RouteConfigurationResponseState(0).state,
+ AdsServiceImpl::ResponseState::ACKED);
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK unparseable filter types in Route.
+TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* per_filter_config = route_config.mutable_virtual_hosts(0)
+ ->mutable_routes(0)
+ ->mutable_typed_per_filter_config();
+ (*per_filter_config)["unknown"].PackFrom(
+ envoy::extensions::filters::http::router::v3::Router());
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (RouteConfigurationResponseState(0).state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state = RouteConfigurationResponseState(0);
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(
+ response_state.error_message,
+ ::testing::HasSubstr("router filter does not support config override"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK unknown filter types in ClusterWeight.
+TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+ ->mutable_routes(0)
+ ->mutable_route()
+ ->mutable_weighted_clusters()
+ ->add_clusters();
+ cluster_weight->set_name(kDefaultClusterName);
+ cluster_weight->mutable_weight()->set_value(100);
+ auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+ (*per_filter_config)["unknown"].PackFrom(Listener());
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (RouteConfigurationResponseState(0).state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state = RouteConfigurationResponseState(0);
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(response_state.error_message,
+ ::testing::HasSubstr("no filter registered for config type "
+ "envoy.config.listener.v3.Listener"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we ignore optional unknown filter types in ClusterWeight.
+TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+ ->mutable_routes(0)
+ ->mutable_route()
+ ->mutable_weighted_clusters()
+ ->add_clusters();
+ cluster_weight->set_name(kDefaultClusterName);
+ cluster_weight->mutable_weight()->set_value(100);
+ auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+ ::envoy::config::route::v3::FilterConfig filter_config;
+ filter_config.mutable_config()->PackFrom(Listener());
+ filter_config.set_is_optional(true);
+ (*per_filter_config)["unknown"].PackFrom(filter_config);
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ AdsServiceImpl::EdsResourceArgs args({
+ {"locality0", GetBackendPorts()},
+ });
+ balancers_[0]->ads_service()->SetEdsResource(
+ BuildEdsResource(args, DefaultEdsServiceName()));
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ WaitForAllBackends();
+ EXPECT_EQ(RouteConfigurationResponseState(0).state,
+ AdsServiceImpl::ResponseState::ACKED);
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// Test that we NACK unparseable filter types in ClusterWeight.
+TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInClusterWeight) {
+ if (GetParam().use_v2()) return; // Filters supported in v3 only.
+ gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true");
+ RouteConfiguration route_config = default_route_config_;
+ auto* cluster_weight = route_config.mutable_virtual_hosts(0)
+ ->mutable_routes(0)
+ ->mutable_route()
+ ->mutable_weighted_clusters()
+ ->add_clusters();
+ cluster_weight->set_name(kDefaultClusterName);
+ cluster_weight->mutable_weight()->set_value(100);
+ auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config();
+ (*per_filter_config)["unknown"].PackFrom(
+ envoy::extensions::filters::http::router::v3::Router());
+ SetListenerAndRouteConfiguration(0, default_listener_, route_config);
+ SetNextResolution({});
+ SetNextResolutionForLbChannelAllBalancers();
+ // Wait until xDS server sees NACK.
+ do {
+ CheckRpcSendFailure();
+ } while (RouteConfigurationResponseState(0).state ==
+ AdsServiceImpl::ResponseState::SENT);
+ const auto response_state = RouteConfigurationResponseState(0);
+ EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
+ EXPECT_THAT(
+ response_state.error_message,
+ ::testing::HasSubstr("router filter does not support config override"));
+ gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION");
+}
+
+// TODO(lidiz): As part of adding the fault injection filter, add tests
+// for overriding filter configs in the typed_per_filter_config fields in
+// each of VirtualHost, Route, and ClusterWeight.
+
using CdsTest = BasicTest;
// Tests that CDS client should send an ACK upon correct CDS response.
@@ -5590,7 +6055,7 @@ TEST_P(CdsTest, LogicalDNSClusterTypeDisabled) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5612,7 +6077,7 @@ TEST_P(CdsTest, AggregateClusterTypeDisabled) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5628,7 +6093,7 @@ TEST_P(CdsTest, UnsupportedClusterType) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5655,7 +6120,7 @@ TEST_P(CdsTest, MultipleBadResources) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5675,7 +6140,7 @@ TEST_P(CdsTest, WrongEdsConfig) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5691,7 +6156,7 @@ TEST_P(CdsTest, WrongLbPolicy) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5707,7 +6172,7 @@ TEST_P(CdsTest, WrongLrsServer) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5875,7 +6340,7 @@ TEST_P(XdsSecurityTest,
transport_socket->set_name("envoy.transport_sockets.tls");
balancers_[0]->ads_service()->SetCdsResource(cluster);
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5898,7 +6363,7 @@ TEST_P(
transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
balancers_[0]->ads_service()->SetCdsResource(cluster);
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5920,7 +6385,7 @@ TEST_P(
transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
balancers_[0]->ads_service()->SetCdsResource(cluster);
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -5950,7 +6415,7 @@ TEST_P(XdsSecurityTest, RegexSanMatcherDoesNotAllowIgnoreCase) {
transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context);
balancers_[0]->ads_service()->SetCdsResource(cluster);
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -6379,7 +6844,7 @@ TEST_P(XdsEnabledServerTest, BadLdsUpdateNoApiListenerNorAddress) {
listener.add_filter_chains();
balancers_[0]->ads_service()->SetLdsResource(listener);
CheckRpcSendFailure(1, RpcOptions().set_wait_for_ready(true));
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
@@ -6403,7 +6868,7 @@ TEST_P(XdsEnabledServerTest, BadLdsUpdateBothApiListenerAndAddress) {
listener.mutable_api_listener();
balancers_[0]->ads_service()->SetLdsResource(listener);
CheckRpcSendFailure(1, RpcOptions().set_wait_for_ready(true));
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(
@@ -6663,7 +7128,7 @@ TEST_P(XdsServerSecurityTest, TlsConfigurationWithoutRootProviderInstance) {
transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
balancers_[0]->ads_service()->SetLdsResource(listener);
CheckRpcSendFailure(1, RpcOptions().set_wait_for_ready(true));
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
@@ -6926,7 +7391,7 @@ TEST_P(EdsTest, NacksSparsePriorityList) {
});
balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args));
CheckRpcSendFailure();
- const auto& response_state =
+ const auto response_state =
balancers_[0]->ads_service()->eds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
diff --git a/tools/codegen/core/gen_upb_api.sh b/tools/codegen/core/gen_upb_api.sh
index f7d62490af8..40b4c4c6126 100755
--- a/tools/codegen/core/gen_upb_api.sh
+++ b/tools/codegen/core/gen_upb_api.sh
@@ -76,6 +76,7 @@ proto_files=( \
"envoy/config/route/v3/scoped_route.proto" \
"envoy/config/trace/v3/http_tracer.proto" \
"envoy/extensions/clusters/aggregate/v3/cluster.proto" \
+ "envoy/extensions/filters/http/router/v3/router.proto" \
"envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto" \
"envoy/extensions/transport_sockets/tls/v3/cert.proto" \
"envoy/extensions/transport_sockets/tls/v3/common.proto" \
@@ -126,6 +127,7 @@ proto_files=( \
"udpa/annotations/sensitive.proto" \
"udpa/annotations/status.proto" \
"udpa/annotations/versioning.proto" \
+ "udpa/type/v1/typed_struct.proto" \
"xds/core/v3/authority.proto" \
"xds/core/v3/collection_entry.proto" \
"xds/core/v3/context_params.proto" \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 83db1fdac7a..7f56903de8a 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1292,6 +1292,8 @@ src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c \
src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h \
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c \
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h \
+src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \
+src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h \
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \
@@ -1386,6 +1388,8 @@ src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/annotations/versioning.upb.h \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
+src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
+src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h \
src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/validate/validate.upb.h \
src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
@@ -1464,6 +1468,8 @@ src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h \
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h \
+src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c \
+src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h \
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \
@@ -1542,6 +1548,8 @@ src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h \
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h \
+src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
+src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h \
src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
src/core/ext/upbdefs-generated/validate/validate.upbdefs.h \
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
@@ -1574,6 +1582,8 @@ src/core/ext/xds/xds_client.cc \
src/core/ext/xds/xds_client.h \
src/core/ext/xds/xds_client_stats.cc \
src/core/ext/xds/xds_client_stats.h \
+src/core/ext/xds/xds_http_filters.cc \
+src/core/ext/xds/xds_http_filters.h \
src/core/ext/xds/xds_server_config_fetcher.cc \
src/core/lib/avl/avl.cc \
src/core/lib/avl/avl.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 852a6472ada..479c14784a8 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1128,6 +1128,8 @@ src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c \
src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h \
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c \
src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h \
+src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \
+src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h \
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \
src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h \
src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \
@@ -1222,6 +1224,8 @@ src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/annotations/versioning.upb.h \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
+src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c \
+src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h \
src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/validate/validate.upb.h \
src/core/ext/upb-generated/xds/core/v3/authority.upb.c \
@@ -1300,6 +1304,8 @@ src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h \
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h \
+src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c \
+src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h \
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \
src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h \
src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \
@@ -1378,6 +1384,8 @@ src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/status.upbdefs.h \
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.c \
src/core/ext/upbdefs-generated/udpa/annotations/versioning.upbdefs.h \
+src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c \
+src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h \
src/core/ext/upbdefs-generated/validate/validate.upbdefs.c \
src/core/ext/upbdefs-generated/validate/validate.upbdefs.h \
src/core/ext/upbdefs-generated/xds/core/v3/authority.upbdefs.c \
@@ -1410,6 +1418,8 @@ src/core/ext/xds/xds_client.cc \
src/core/ext/xds/xds_client.h \
src/core/ext/xds/xds_client_stats.cc \
src/core/ext/xds/xds_client_stats.h \
+src/core/ext/xds/xds_http_filters.cc \
+src/core/ext/xds/xds_http_filters.h \
src/core/ext/xds/xds_server_config_fetcher.cc \
src/core/lib/README.md \
src/core/lib/avl/avl.cc \