Skip to content

Commit 7a08f11

Browse files
authored
Listener Isolation for hostnames occupied by other listeners (#3067)
Listener Isolation for hostnames occupied by other listeners Problem: Users want to be able to isolate listeners for routes. Solution: Adds functionality to filter out listener hostnames from the accepted hostnames of a route which belong to another listener.
1 parent 6dc85d7 commit 7a08f11

File tree

3 files changed

+628
-6
lines changed

3 files changed

+628
-6
lines changed

internal/mode/static/state/graph/route_common.go

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,22 +337,96 @@ func bindRoutesToListeners(
337337
bindL7RouteToListeners(r, gw, namespaces)
338338
}
339339

340-
var routes []*L4Route
341-
for _, r := range l4Routes {
340+
routes := make([]*L7Route, 0, len(l7Routes))
341+
for _, r := range l7Routes {
342342
routes = append(routes, r)
343343
}
344344

345+
isolateL7RouteListeners(routes, gw.Listeners)
346+
347+
l4RouteSlice := make([]*L4Route, 0, len(l4Routes))
348+
for _, r := range l4Routes {
349+
l4RouteSlice = append(l4RouteSlice, r)
350+
}
351+
345352
// Sort the slice by timestamp and name so that we process the routes in the priority order
346-
sort.Slice(routes, func(i, j int) bool {
347-
return ngfSort.LessClientObject(routes[i].Source, routes[j].Source)
353+
sort.Slice(l4RouteSlice, func(i, j int) bool {
354+
return ngfSort.LessClientObject(l4RouteSlice[i].Source, l4RouteSlice[j].Source)
348355
})
349356

350357
// portHostnamesMap exists to detect duplicate hostnames on the same port
351358
portHostnamesMap := make(map[string]struct{})
352359

353-
for _, r := range routes {
360+
for _, r := range l4RouteSlice {
354361
bindL4RouteToListeners(r, gw, namespaces, portHostnamesMap)
355362
}
363+
364+
isolateL4RouteListeners(l4RouteSlice, gw.Listeners)
365+
}
366+
367+
// isolateL7RouteListeners ensures listener isolation for all L7Routes.
368+
func isolateL7RouteListeners(routes []*L7Route, listeners []*Listener) {
369+
listenerHostnameMap := make(map[string]string, len(listeners))
370+
for _, l := range listeners {
371+
listenerHostnameMap[l.Name] = getHostname(l.Source.Hostname)
372+
}
373+
374+
for _, route := range routes {
375+
isolateHostnamesForParentRefs(route.ParentRefs, listenerHostnameMap)
376+
}
377+
}
378+
379+
// isolateL4RouteListeners ensures listener isolation for all L4Routes.
380+
func isolateL4RouteListeners(routes []*L4Route, listeners []*Listener) {
381+
listenerHostnameMap := make(map[string]string, len(listeners))
382+
for _, l := range listeners {
383+
listenerHostnameMap[l.Name] = getHostname(l.Source.Hostname)
384+
}
385+
386+
for _, route := range routes {
387+
isolateHostnamesForParentRefs(route.ParentRefs, listenerHostnameMap)
388+
}
389+
}
390+
391+
// isolateHostnamesForParentRefs iterates through the parentRefs of a route to identify the list of accepted hostnames
392+
// for each listener. If any accepted hostname belongs to another listener,
393+
// it removes those hostnames to ensure listener isolation.
394+
func isolateHostnamesForParentRefs(parentRef []ParentRef, listenerHostnameMap map[string]string) {
395+
for _, ref := range parentRef {
396+
acceptedHostnames := ref.Attachment.AcceptedHostnames
397+
398+
hostnamesToRemoves := make(map[string]struct{})
399+
for listenerName, hostnames := range acceptedHostnames {
400+
if len(hostnames) == 0 {
401+
continue
402+
}
403+
for _, h := range hostnames {
404+
for lName, lHostname := range listenerHostnameMap {
405+
// skip comparison if it is a catch all listener block
406+
if lHostname == "" {
407+
continue
408+
}
409+
if h == lHostname && listenerName != lName {
410+
hostnamesToRemoves[h] = struct{}{}
411+
}
412+
}
413+
}
414+
415+
isolatedHostnames := removeHostnames(hostnames, hostnamesToRemoves)
416+
ref.Attachment.AcceptedHostnames[listenerName] = isolatedHostnames
417+
}
418+
}
419+
}
420+
421+
// removeHostnames removes the hostnames that are part of toRemove slice.
422+
func removeHostnames(hostnames []string, toRemove map[string]struct{}) []string {
423+
result := make([]string, 0, len(hostnames))
424+
for _, hostname := range hostnames {
425+
if _, exists := toRemove[hostname]; !exists {
426+
result = append(result, hostname)
427+
}
428+
}
429+
return result
356430
}
357431

358432
func validateParentRef(

0 commit comments

Comments
 (0)