@@ -146,11 +146,11 @@ static EnvoyServerProtoData.Listener parseServerSideListener(
146146 Listener proto , TlsContextManager tlsContextManager ,
147147 FilterRegistry filterRegistry , Set <String > certProviderInstances , XdsResourceType .Args args )
148148 throws ResourceInvalidException {
149- if (!proto .getTrafficDirection ().equals (TrafficDirection .INBOUND )
150- && !proto .getTrafficDirection ().equals (TrafficDirection .UNSPECIFIED )) {
149+ TrafficDirection trafficDirection = proto .getTrafficDirection ();
150+ if (!trafficDirection .equals (TrafficDirection .INBOUND )
151+ && !trafficDirection .equals (TrafficDirection .UNSPECIFIED )) {
151152 throw new ResourceInvalidException (
152- "Listener " + proto .getName () + " with invalid traffic direction: "
153- + proto .getTrafficDirection ());
153+ "Listener " + proto .getName () + " with invalid traffic direction: " + trafficDirection );
154154 }
155155 if (!proto .getListenerFiltersList ().isEmpty ()) {
156156 throw new ResourceInvalidException (
@@ -178,16 +178,29 @@ static EnvoyServerProtoData.Listener parseServerSideListener(
178178 }
179179
180180 ImmutableList .Builder <FilterChain > filterChains = ImmutableList .builder ();
181- Set <FilterChainMatch > uniqueSet = new HashSet <>();
181+ Set <FilterChainMatch > filterChainMatchSet = new HashSet <>();
182+ int i = 0 ;
182183 for (io .envoyproxy .envoy .config .listener .v3 .FilterChain fc : proto .getFilterChainsList ()) {
184+ // May be empty. If it's not empty, required to be unique.
185+ String filterChainName = fc .getName ();
186+ if (filterChainName .isEmpty ()) {
187+ // Generate a name, so we can identify it in the logs.
188+ filterChainName = "chain_" + i ;
189+ }
183190 filterChains .add (
184- parseFilterChain (fc , tlsContextManager , filterRegistry , uniqueSet ,
185- certProviderInstances , args ));
191+ parseFilterChain (fc , filterChainName , tlsContextManager , filterRegistry ,
192+ filterChainMatchSet , certProviderInstances , args ));
193+ i ++;
186194 }
195+
187196 FilterChain defaultFilterChain = null ;
188197 if (proto .hasDefaultFilterChain ()) {
198+ String defaultFilterChainName = proto .getDefaultFilterChain ().getName ();
199+ if (defaultFilterChainName .isEmpty ()) {
200+ defaultFilterChainName = "chain_default" ;
201+ }
189202 defaultFilterChain = parseFilterChain (
190- proto .getDefaultFilterChain (), tlsContextManager , filterRegistry ,
203+ proto .getDefaultFilterChain (), defaultFilterChainName , tlsContextManager , filterRegistry ,
191204 null , certProviderInstances , args );
192205 }
193206
@@ -198,36 +211,44 @@ static EnvoyServerProtoData.Listener parseServerSideListener(
198211 @ VisibleForTesting
199212 static FilterChain parseFilterChain (
200213 io .envoyproxy .envoy .config .listener .v3 .FilterChain proto ,
201- TlsContextManager tlsContextManager , FilterRegistry filterRegistry ,
202- Set <FilterChainMatch > uniqueSet , Set <String > certProviderInstances , XdsResourceType .Args args )
214+ String filterChainName ,
215+ TlsContextManager tlsContextManager ,
216+ FilterRegistry filterRegistry ,
217+ // null disables FilterChainMatch uniqueness check, used for defaultFilterChain
218+ @ Nullable Set <FilterChainMatch > filterChainMatchSet ,
219+ Set <String > certProviderInstances ,
220+ XdsResourceType .Args args )
203221 throws ResourceInvalidException {
222+ // FilterChain contains L4 filters, so we ensure it contains only HCM.
204223 if (proto .getFiltersCount () != 1 ) {
205- throw new ResourceInvalidException ("FilterChain " + proto . getName ()
224+ throw new ResourceInvalidException ("FilterChain " + filterChainName
206225 + " should contain exact one HttpConnectionManager filter" );
207226 }
208- io .envoyproxy .envoy .config .listener .v3 .Filter filter = proto .getFiltersList ().get (0 );
209- if (!filter .hasTypedConfig ()) {
227+ io .envoyproxy .envoy .config .listener .v3 .Filter l4Filter = proto .getFiltersList ().get (0 );
228+ if (!l4Filter .hasTypedConfig ()) {
210229 throw new ResourceInvalidException (
211- "FilterChain " + proto . getName () + " contains filter " + filter .getName ()
230+ "FilterChain " + filterChainName + " contains filter " + l4Filter .getName ()
212231 + " without typed_config" );
213232 }
214- Any any = filter .getTypedConfig ();
215- // HttpConnectionManager is the only supported network filter at the moment.
233+ Any any = l4Filter .getTypedConfig ();
216234 if (!any .getTypeUrl ().equals (TYPE_URL_HTTP_CONNECTION_MANAGER )) {
217235 throw new ResourceInvalidException (
218- "FilterChain " + proto . getName () + " contains filter " + filter .getName ()
236+ "FilterChain " + filterChainName + " contains filter " + l4Filter .getName ()
219237 + " with unsupported typed_config type " + any .getTypeUrl ());
220238 }
239+
240+ // Parse HCM.
221241 HttpConnectionManager hcmProto ;
222242 try {
223243 hcmProto = any .unpack (HttpConnectionManager .class );
224244 } catch (InvalidProtocolBufferException e ) {
225- throw new ResourceInvalidException ("FilterChain " + proto . getName () + " with filter "
226- + filter .getName () + " failed to unpack message" , e );
245+ throw new ResourceInvalidException ("FilterChain " + filterChainName + " with filter "
246+ + l4Filter .getName () + " failed to unpack message" , e );
227247 }
228248 io .grpc .xds .HttpConnectionManager httpConnectionManager = parseHttpConnectionManager (
229249 hcmProto , filterRegistry , false /* isForClient */ , args );
230250
251+ // Parse Transport Socket.
231252 EnvoyServerProtoData .DownstreamTlsContext downstreamTlsContext = null ;
232253 if (proto .hasTransportSocket ()) {
233254 if (!TRANSPORT_SOCKET_NAME_TLS .equals (proto .getTransportSocket ().getName ())) {
@@ -239,18 +260,23 @@ static FilterChain parseFilterChain(
239260 downstreamTlsContextProto =
240261 proto .getTransportSocket ().getTypedConfig ().unpack (DownstreamTlsContext .class );
241262 } catch (InvalidProtocolBufferException e ) {
242- throw new ResourceInvalidException ("FilterChain " + proto . getName ()
263+ throw new ResourceInvalidException ("FilterChain " + filterChainName
243264 + " failed to unpack message" , e );
244265 }
245266 downstreamTlsContext =
246267 EnvoyServerProtoData .DownstreamTlsContext .fromEnvoyProtoDownstreamTlsContext (
247268 validateDownstreamTlsContext (downstreamTlsContextProto , certProviderInstances ));
248269 }
249270
271+ // Parse FilterChainMatch.
250272 FilterChainMatch filterChainMatch = parseFilterChainMatch (proto .getFilterChainMatch ());
251- checkForUniqueness (uniqueSet , filterChainMatch );
273+ // null used to skip this check for defaultFilterChain.
274+ if (filterChainMatchSet != null ) {
275+ validateFilterChainMatchForUniqueness (filterChainMatchSet , filterChainMatch );
276+ }
277+
252278 return FilterChain .create (
253- proto . getName () ,
279+ filterChainName ,
254280 filterChainMatch ,
255281 httpConnectionManager ,
256282 downstreamTlsContext ,
@@ -284,15 +310,15 @@ static DownstreamTlsContext validateDownstreamTlsContext(
284310 return downstreamTlsContext ;
285311 }
286312
287- private static void checkForUniqueness (Set <FilterChainMatch > uniqueSet ,
313+ private static void validateFilterChainMatchForUniqueness (
314+ Set <FilterChainMatch > filterChainMatchSet ,
288315 FilterChainMatch filterChainMatch ) throws ResourceInvalidException {
289- if (uniqueSet != null ) {
290- List <FilterChainMatch > crossProduct = getCrossProduct (filterChainMatch );
291- for (FilterChainMatch cur : crossProduct ) {
292- if (!uniqueSet .add (cur )) {
293- throw new ResourceInvalidException ("FilterChainMatch must be unique. "
294- + "Found duplicate: " + cur );
295- }
316+ // Flattens complex FilterChainMatch into a list of simple FilterChainMatch'es.
317+ List <FilterChainMatch > crossProduct = getCrossProduct (filterChainMatch );
318+ for (FilterChainMatch cur : crossProduct ) {
319+ if (!filterChainMatchSet .add (cur )) {
320+ throw new ResourceInvalidException ("FilterChainMatch must be unique. "
321+ + "Found duplicate: " + cur );
296322 }
297323 }
298324 }
0 commit comments