You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.4 KiB
116 lines
3.4 KiB
// Package rings provides logic to work with the four rings |
|
// of a cluster |
|
package rings |
|
|
|
import ( |
|
"fmt" |
|
"strconv" |
|
"syscall" |
|
|
|
"darvaza.org/core" |
|
) |
|
|
|
const ( |
|
// UnspecifiedRingID is the zero value of RingID and not considered |
|
// valid. |
|
UnspecifiedRingID RingID = iota |
|
RingZeroID // RingZeroID is the RingID for RingZero (backbone) |
|
RingOneID // RingOneID is the RingID for RingOne (local zone) |
|
RingTwoID // RingTwoID is the RingID for RingTwo (region services) |
|
RingThreeID // RingThreeID is the RingID for RingThree (region cluster pods) |
|
|
|
// RingMax indicates the highest [Ring] identifier |
|
RingMax = RingThreeID |
|
|
|
// RegionMax indicates the highest number that can be used for a [RegionID]. |
|
RegionMax = (1 << 4) - 1 |
|
// ZoneMax indicates the highest number that can be used for a [ZoneID]. |
|
ZoneMax = (1 << 4) - 1 |
|
// NodeMax indicates the highest number that can be used for a [NodeID]. |
|
NodeMax = (1 << 12) - 2 |
|
// NodeZeroMax indicates the highest number that can be used for a [NodeID] |
|
// when its a gateway connected to Ring 0 (backbone). |
|
NodeZeroMax = (1 << 8) - 2 |
|
|
|
// RingZeroBits indicates the size of the prefix on the ring 0 (backbone) network. |
|
RingZeroBits = 16 |
|
// RingOneBits indicates the size of the prefix on the ring 1 (lan) network. |
|
RingOneBits = 20 |
|
// RingTwoBits indicates the size of the prefix on the ring 2 (services) network |
|
// of all kubernetes clusters. |
|
RingTwoBits = 20 |
|
// RingThreeBits indicates the size of the prefix on the ring 3 (pods) network |
|
// of the kubernetes cluster of a region. |
|
RingThreeBits = 12 |
|
) |
|
|
|
// RingID identifies a Ring |
|
type RingID int |
|
|
|
// Valid tells a [RingID] is within the valid range. |
|
func (n RingID) Valid() bool { return n > 0 && n <= RingMax } |
|
|
|
func (n RingID) String() string { |
|
return idString(n) |
|
} |
|
|
|
// A Ring identifies what ring an address belongs to |
|
type Ring interface { |
|
ID() RingID |
|
} |
|
|
|
// RegionID is the identifier of a region, valid between 1 and [RegionMax]. |
|
type RegionID int |
|
|
|
// Valid tells a [RegionID] is within the valid range. |
|
func (n RegionID) Valid() bool { return n > 0 && n <= RegionMax } |
|
|
|
func (n RegionID) String() string { |
|
return idString(n) |
|
} |
|
|
|
// ZoneID is the identifier of a zone within a region, valid between 1 and [ZoneMax]. |
|
type ZoneID int |
|
|
|
// Valid tells a [ZoneID] is within the valid range. |
|
func (n ZoneID) Valid() bool { return n > 0 && n <= ZoneMax } |
|
|
|
func (n ZoneID) String() string { |
|
return idString(n) |
|
} |
|
|
|
// NodeID is the identifier of a machine within a zone of a region, valid between |
|
// 1 and [NodeMax], but between 1 and [NodeZeroMax] if it will be a zone gateway. |
|
type NodeID int |
|
|
|
// Valid tells a [NodeID] is within the valid range. |
|
func (n NodeID) Valid() bool { return n > 0 && n <= NodeMax } |
|
|
|
// ValidZero tells a [NodeID] is within the valid range for a gateway. |
|
func (n NodeID) ValidZero() bool { return n > 0 && n <= NodeZeroMax } |
|
|
|
func (n NodeID) String() string { |
|
return idString(n) |
|
} |
|
|
|
// ErrOutOfRange is an error indicating the value of a field |
|
// is out of range. |
|
func ErrOutOfRange[T ~int | ~uint32](value T, field string) error { |
|
return core.Wrap(syscall.EINVAL, "%s out of range (%v)", field, value) |
|
} |
|
|
|
type intID interface { |
|
~int |
|
Valid() bool |
|
} |
|
|
|
func idString[T intID](p T) string { |
|
switch { |
|
case p == 0: |
|
return "unspecified" |
|
case p.Valid(): |
|
return strconv.Itoa(int(p)) |
|
default: |
|
return fmt.Sprintf("invalid (%v)", int(p)) |
|
} |
|
}
|
|
|