Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use only 46 bits for priorities of Kong routes #5024

Merged
merged 2 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@ Adding a new version? You'll need three changes:
[#4928](https://github.com/Kong/kubernetes-ingress-controller/pull/4928)
- Fixed a panic when receiving broken configuration from Kong Gateway.
[#5003](https://github.com/Kong/kubernetes-ingress-controller/pull/5003)
- Use 46 bits in values of priorities of generated Kong routes when expression
rotuer is enabled to limit the priorities to be less than `1e14`. This
prevents them to be encoded into scientific notation when dumping
configurations from admin API that brings precision loss and type
inconsistency in decoding JSON/YAML data to `uint64`.
This change will limit number of `HTTPRoute`s that can be
deterministically sorted by their creation timestamps, names and internal
rule orders to `2^12=4096` and number of `GRPCRoutes` can be sorted to `2^8=256`.
[#5024](https://github.com/Kong/kubernetes-ingress-controller/pull/5024)

### Changed

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/dataplane/parser/translators/atc_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
)

const (
// FromResourceKindPriorityShiftBits is the highest 2 bits 51-50 used in priority field of Kong route
// FromResourceKindPriorityShiftBits is the highest 2 bits 45-44 used in priority field of Kong route
// to note the kind of the resource from which the route is translated.
// 11 - routes from Ingress.
// 10 - routes from HTTPRoute.
// 01 - routes from GRPCRoute.
FromResourceKindPriorityShiftBits = 50
FromResourceKindPriorityShiftBits = 44
// ResourceKindBitsIngress is the value of highest 2 bits for routes from ingresses.
ResourceKindBitsIngress = 3
// ResourceKindBitsHTTPRoute is the value of highest 2 bits for routes from HTTPRoutes.
Expand Down
44 changes: 22 additions & 22 deletions internal/dataplane/parser/translators/grpcroute_atc.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,11 @@ func CalculateGRCPRouteMatchPriorityTraits(match SplitGRPCRouteMatch) GRPCRouteP

// EncodeToPriority turns GRPCRoute priority traits into the integer expressed priority.
//
// 4 3 2 1
// 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +-+---------------+---------------------+---------------------+---------+---------------------------+
// |P| host len | GRPC service length | GRPC method length |Header No| relative order |
// +-+---------------+---------------------+---------------------+---------+---------------------------+
// 4 3 2 1
// 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +-+---------------+---------------------+---------------------+---------+----------------+
// |P| host len | GRPC service length | GRPC method length |Header No| relative order |
// +-+---------------+---------------------+---------------------+---------+----------------+
//
// Where:
// P: set to 1 if the hostname is non-wildcard.
Expand All @@ -303,17 +303,17 @@ func CalculateGRCPRouteMatchPriorityTraits(match SplitGRPCRouteMatch) GRPCRouteP
// to assign higher priority for method match with `Exact` match?
func (t GRPCRoutePriorityTraits) EncodeToPriority() RoutePriorityType {
const (
// PreciseHostnameShiftBits assigns bit 49 for marking if the hostname is non-wildcard.
PreciseHostnameShiftBits = 49
// HostnameLengthShiftBits assigns bits 41-48 for the length of hostname.
HostnameLengthShiftBits = 41
// ServiceLengthShiftBits assigns bits 30-40 for the length of `Service` in method match.
ServiceLengthShiftBits = 30
// MethodLengthShiftBits assigns bits 19-29 for the length of `Method` in method match.
MethodLengthShiftBits = 19
// HeaderCountShiftBits assigns bits 14-18 for the number of header matches.
HeaderCountShiftBits = 14
// bits 0-13 are used for relative order of creation timestamp, namespace/name, and internal order of rules and matches.
// PreciseHostnameShiftBits assigns bit 43 for marking if the hostname is non-wildcard.
PreciseHostnameShiftBits = 43
// HostnameLengthShiftBits assigns bits 35-42 for the length of hostname.
HostnameLengthShiftBits = 35
// ServiceLengthShiftBits assigns bits 24-34 for the length of `Service` in method match.
ServiceLengthShiftBits = 24
// MethodLengthShiftBits assigns bits 13-23 for the length of `Method` in method match.
MethodLengthShiftBits = 13
// HeaderCountShiftBits assigns bits 8-12 for the number of header matches.
HeaderCountShiftBits = 8
// bits 0-7 are used for relative order of creation timestamp, namespace/name, and internal order of rules and matches.
// the bits are calculated by sorting GRPCRoutes with the same priority calculated from the fields above
// and start from all 1s, then decrease by one for each GRPCRoute.
)
Expand Down Expand Up @@ -365,11 +365,11 @@ func AssignRoutePriorityToSplitGRPCRouteMatches(

splitGRPCRoutesToPriority := make([]SplitGRPCRouteMatchToPriority, 0, len(splitGRPCouteMatches))

// Bits 0-13 (14 bits) are assigned for relative order of GRPCRoutes.
// Bits 0-7 (8 bits) are assigned for relative order of GRPCRoutes.
// If multiple GRPCRoutes are assigned to the same priority in the previous step,
// sort them then starts with 2^14 -1 and decrease by one for each GRPCRoute;
// sort them then starts with 2^8 -1 and decrease by one for each GRPCRoute;
// If only one GRPCRoute occupies the priority, fill the relative order bits with all 1s.
const relativeOrderAssignedBits = 14
const relativeOrderAssignedBits = 8
const defaultRelativeOrderPriorityBits RoutePriorityType = (1 << relativeOrderAssignedBits) - 1

for priority, matches := range priorityToSplitGRPCRouteMatches {
Expand All @@ -388,7 +388,7 @@ func AssignRoutePriorityToSplitGRPCRouteMatches(

for i, match := range matches {
relativeOrderBits := defaultRelativeOrderPriorityBits - RoutePriorityType(i)
// Although it is very unlikely that there are 2^14 = 16384 GRPCRoutes
// Although it is very unlikely that there are 2^8 = 256 GRPCRoutes
// should be given priority by their relative order, here we limit the
// relativeOrderBits to be at least 0.
if relativeOrderBits <= 0 {
Expand All @@ -400,9 +400,9 @@ func AssignRoutePriorityToSplitGRPCRouteMatches(
})
}

// Just in case, log a very unlikely scenario where we have more than 2^14 routes with the same base
// Just in case, log a very unlikely scenario where we have more than 2^8 routes with the same base
// priority and we have no bit space for them to be deterministically ordered.
if len(matches) > (1 << 14) {
if len(matches) > (1 << 8) {
logger.Error(nil, "Too many GRPCRoute matches to be deterministically ordered", "grpcroute_number", len(matches))
}
}
Expand Down
18 changes: 9 additions & 9 deletions internal/dataplane/parser/translators/grpcroute_atc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ func TestGRPCRouteTraitsEncodeToPriority(t *testing.T) {
HostnameLength: 15,
ServiceLength: 7,
},
exprectedPriority: (1 << 50) | (1 << 49) | (15 << 41) | (7 << 30),
exprectedPriority: (1 << 44) | (1 << 43) | (15 << 35) | (7 << 24),
},
{
name: "non precise hostname",
Expand All @@ -624,7 +624,7 @@ func TestGRPCRouteTraitsEncodeToPriority(t *testing.T) {
MethodLength: 7,
HeaderCount: 3,
},
exprectedPriority: (1 << 50) | (15 << 41) | (7 << 30) | (7 << 19) | (3 << 14),
exprectedPriority: (1 << 44) | (15 << 35) | (7 << 24) | (7 << 13) | (3 << 8),
},
}

Expand All @@ -647,7 +647,7 @@ func TestAssignRoutePriorityToSplitGRPCRouteMatches(t *testing.T) {
matchIndex int
}
now := time.Now()
const maxRelativeOrderPriorityBits = (1 << 14) - 1
const maxRelativeOrderPriorityBits = (1 << 8) - 1

testCases := []struct {
name string
Expand Down Expand Up @@ -1123,14 +1123,14 @@ func TestKongExpressionRouteFromSplitGRPCRouteWithPriority(t *testing.T) {
RuleIndex: 0,
MatchIndex: 0,
},
Priority: 1024,
Priority: 1 << 14,
},
expectedRoute: kongstate.Route{
Route: kong.Route{
Name: kong.String("grpcroute.default.no-hostname-exact-method._.0.0"),
PreserveHost: kong.Bool(true),
Expression: kong.String(`http.path == "/pets/list"`),
Priority: kong.Uint64(1024),
Priority: kong.Uint64(1 << 14),
},
ExpressionRoutes: true,
},
Expand Down Expand Up @@ -1175,14 +1175,14 @@ func TestKongExpressionRouteFromSplitGRPCRouteWithPriority(t *testing.T) {
RuleIndex: 0,
MatchIndex: 0,
},
Priority: 1024,
Priority: (1 << 31) + 1,
},
expectedRoute: kongstate.Route{
Route: kong.Route{
Name: kong.String("grpcroute.default.precise-hostname-regex-method.foo.com.0.0"),
Expression: kong.String(`(http.path ~ "^/name/[a-z0-9]+") && (http.host == "foo.com")`),
PreserveHost: kong.Bool(true),
Priority: kong.Uint64(1024),
Priority: kong.Uint64((1 << 31) + 1),
},
ExpressionRoutes: true,
},
Expand Down Expand Up @@ -1244,14 +1244,14 @@ func TestKongExpressionRouteFromSplitGRPCRouteWithPriority(t *testing.T) {
RuleIndex: 0,
MatchIndex: 1,
},
Priority: 1024,
Priority: (1 << 42) + 1,
},
expectedRoute: kongstate.Route{
Route: kong.Route{
Name: kong.String("grpcroute.default.wildcard-hostname-header-match._.foo.com.0.1"),
Expression: kong.String(`(http.path ^= "/name/") && (http.headers.foo == "bar") && (http.host =^ ".foo.com")`),
PreserveHost: kong.Bool(true),
Priority: kong.Uint64(1024),
Priority: kong.Uint64((1 << 42) + 1),
},
ExpressionRoutes: true,
},
Expand Down
Loading
Loading