Skip to content

Commit 4c51b05

Browse files
authored
Modify listener isolation rules for routes (#3159)
Problem: Users are unable to configure server blocks with listener sharing the same hostname with another listener but on a different port. Solution: Modify rules for listener isolation
1 parent 3914e8f commit 4c51b05

File tree

2 files changed

+437
-121
lines changed

2 files changed

+437
-121
lines changed

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

+42-21
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,8 @@ func bindRoutesToListeners(
342342
routes = append(routes, r)
343343
}
344344

345-
isolateL7RouteListeners(routes, gw.Listeners)
345+
listenerMap := getListenerHostPortMap(gw.Listeners)
346+
isolateL7RouteListeners(routes, listenerMap)
346347

347348
l4RouteSlice := make([]*L4Route, 0, len(l4Routes))
348349
for _, r := range l4Routes {
@@ -361,53 +362,73 @@ func bindRoutesToListeners(
361362
bindL4RouteToListeners(r, gw, namespaces, portHostnamesMap)
362363
}
363364

364-
isolateL4RouteListeners(l4RouteSlice, gw.Listeners)
365+
isolateL4RouteListeners(l4RouteSlice, listenerMap)
365366
}
366367

367-
// isolateL7RouteListeners ensures listener isolation for all L7Routes.
368-
func isolateL7RouteListeners(routes []*L7Route, listeners []*Listener) {
369-
listenerHostnameMap := make(map[string]string, len(listeners))
368+
type hostPort struct {
369+
hostname string
370+
port v1.PortNumber
371+
}
372+
373+
func getListenerHostPortMap(listeners []*Listener) map[string]hostPort {
374+
listenerHostPortMap := make(map[string]hostPort, len(listeners))
370375
for _, l := range listeners {
371-
listenerHostnameMap[l.Name] = getHostname(l.Source.Hostname)
376+
listenerHostPortMap[l.Name] = hostPort{
377+
hostname: getHostname(l.Source.Hostname),
378+
port: l.Source.Port,
379+
}
372380
}
381+
return listenerHostPortMap
382+
}
373383

384+
// isolateL7RouteListeners ensures listener isolation for all L7Routes.
385+
func isolateL7RouteListeners(routes []*L7Route, listenerHostPortMap map[string]hostPort) {
386+
isL4Route := false
374387
for _, route := range routes {
375-
isolateHostnamesForParentRefs(route.ParentRefs, listenerHostnameMap)
388+
isolateHostnamesForParentRefs(route.ParentRefs, listenerHostPortMap, isL4Route)
376389
}
377390
}
378391

379392
// 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-
393+
func isolateL4RouteListeners(routes []*L4Route, listenerHostPortMap map[string]hostPort) {
394+
isL4Route := true
386395
for _, route := range routes {
387-
isolateHostnamesForParentRefs(route.ParentRefs, listenerHostnameMap)
396+
isolateHostnamesForParentRefs(route.ParentRefs, listenerHostPortMap, isL4Route)
388397
}
389398
}
390399

391400
// 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,
401+
// for each listener. If any accepted hostname belongs to another listener with the same port, then
393402
// it removes those hostnames to ensure listener isolation.
394-
func isolateHostnamesForParentRefs(parentRef []ParentRef, listenerHostnameMap map[string]string) {
403+
func isolateHostnamesForParentRefs(parentRef []ParentRef, listenerHostnameMap map[string]hostPort, isL4Route bool) {
395404
for _, ref := range parentRef {
396-
acceptedHostnames := ref.Attachment.AcceptedHostnames
405+
// when sectionName is nil we allow all listeners to attach to the route
406+
if ref.SectionName == nil {
407+
continue
408+
}
397409

410+
acceptedHostnames := ref.Attachment.AcceptedHostnames
398411
hostnamesToRemoves := make(map[string]struct{})
399412
for listenerName, hostnames := range acceptedHostnames {
400413
if len(hostnames) == 0 {
401414
continue
402415
}
403416
for _, h := range hostnames {
404-
for lName, lHostname := range listenerHostnameMap {
417+
for lName, lHostPort := range listenerHostnameMap {
405418
// skip comparison if it is a catch all listener block
406-
if lHostname == "" {
419+
if lHostPort.hostname == "" {
407420
continue
408421
}
409-
if h == lHostname && listenerName != lName {
410-
hostnamesToRemoves[h] = struct{}{}
422+
423+
// for L7Routes, we compare the hostname, port and listener name combination
424+
// to identify if hostname needs to be isolated.
425+
if h == lHostPort.hostname && listenerName != lName {
426+
// for L4Routes, we only compare the hostname and listener name combination
427+
// because we do not allow l4Routes to attach to the same listener
428+
// if they share the same port and hostname.
429+
if isL4Route || lHostPort.port == ref.Attachment.ListenerPort {
430+
hostnamesToRemoves[h] = struct{}{}
431+
}
411432
}
412433
}
413434
}

0 commit comments

Comments
 (0)