Skip to content

Commit 1c0bb03

Browse files
committed
types: split SubnetRoutes and ExitRoutes
There are situations where the subnet routes and exit nodes must be treated differently. This splits it so SubnetRoutes only returns routes that are not exit routes. It adds `IsExitRoutes` and `AllApprovedRoutes` for convenience. Signed-off-by: Kristoffer Dalby <[email protected]>
1 parent c649c89 commit 1c0bb03

File tree

1 file changed

+42
-8
lines changed

1 file changed

+42
-8
lines changed

hscontrol/types/node.go

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,19 @@ func (node *Node) Prefixes() []netip.Prefix {
269269
// node has any exit routes enabled.
270270
// If none are enabled, it will return nil.
271271
func (node *Node) ExitRoutes() []netip.Prefix {
272-
if slices.ContainsFunc(node.SubnetRoutes(), tsaddr.IsExitRoute) {
273-
return tsaddr.ExitRoutes()
272+
var routes []netip.Prefix
273+
274+
for _, route := range node.AnnouncedRoutes() {
275+
if tsaddr.IsExitRoute(route) && slices.Contains(node.ApprovedRoutes, route) {
276+
routes = append(routes, route)
277+
}
274278
}
275279

276-
return nil
280+
return routes
281+
}
282+
283+
func (node *Node) IsExitNode() bool {
284+
return len(node.ExitRoutes()) > 0
277285
}
278286

279287
func (node *Node) IPsAsString() []string {
@@ -440,16 +448,22 @@ func (node *Node) AnnouncedRoutes() []netip.Prefix {
440448
return node.Hostinfo.RoutableIPs
441449
}
442450

443-
// SubnetRoutes returns the list of routes that the node announces and are approved.
451+
// SubnetRoutes returns the list of routes (excluding exit routes) that the node
452+
// announces and are approved.
444453
//
445-
// IMPORTANT: This method is used for internal data structures and should NOT be used
446-
// for the gRPC Proto conversion. For Proto, SubnetRoutes must be populated manually
447-
// with PrimaryRoutes to ensure it includes only routes actively served by the node.
448-
// See the comment in Proto() method and the implementation in grpcv1.go/nodesToProto.
454+
// IMPORTANT: This method is used for internal data structures and should NOT be
455+
// used for the gRPC Proto conversion. For Proto, SubnetRoutes must be populated
456+
// manually with PrimaryRoutes to ensure it includes only routes actively served
457+
// by the node. See the comment in Proto() method and the implementation in
458+
// grpcv1.go/nodesToProto.
449459
func (node *Node) SubnetRoutes() []netip.Prefix {
450460
var routes []netip.Prefix
451461

452462
for _, route := range node.AnnouncedRoutes() {
463+
if tsaddr.IsExitRoute(route) {
464+
continue
465+
}
466+
453467
if slices.Contains(node.ApprovedRoutes, route) {
454468
routes = append(routes, route)
455469
}
@@ -463,6 +477,11 @@ func (node *Node) IsSubnetRouter() bool {
463477
return len(node.SubnetRoutes()) > 0
464478
}
465479

480+
// AllApprovedRoutes returns the combination of SubnetRoutes and ExitRoutes
481+
func (node *Node) AllApprovedRoutes() []netip.Prefix {
482+
return append(node.SubnetRoutes(), node.ExitRoutes()...)
483+
}
484+
466485
func (node *Node) String() string {
467486
return node.Hostname
468487
}
@@ -653,6 +672,7 @@ func (node Node) DebugString() string {
653672
fmt.Fprintf(&sb, "\tApprovedRoutes: %v\n", node.ApprovedRoutes)
654673
fmt.Fprintf(&sb, "\tAnnouncedRoutes: %v\n", node.AnnouncedRoutes())
655674
fmt.Fprintf(&sb, "\tSubnetRoutes: %v\n", node.SubnetRoutes())
675+
fmt.Fprintf(&sb, "\tExitRoutes: %v\n", node.ExitRoutes())
656676
sb.WriteString("\n")
657677

658678
return sb.String()
@@ -730,6 +750,13 @@ func (v NodeView) IsSubnetRouter() bool {
730750
return v.ж.IsSubnetRouter()
731751
}
732752

753+
func (v NodeView) AllApprovedRoutes() []netip.Prefix {
754+
if !v.Valid() {
755+
return nil
756+
}
757+
return v.ж.AllApprovedRoutes()
758+
}
759+
733760
func (v NodeView) AppendToIPSet(build *netipx.IPSetBuilder) {
734761
if !v.Valid() {
735762
return
@@ -808,6 +835,13 @@ func (v NodeView) ExitRoutes() []netip.Prefix {
808835
return v.ж.ExitRoutes()
809836
}
810837

838+
func (v NodeView) IsExitNode() bool {
839+
if !v.Valid() {
840+
return false
841+
}
842+
return v.ж.IsExitNode()
843+
}
844+
811845
// RequestTags returns the ACL tags that the node is requesting.
812846
func (v NodeView) RequestTags() []string {
813847
if !v.Valid() || !v.Hostinfo().Valid() {

0 commit comments

Comments
 (0)