Skip to content

Commit

Permalink
fix: use only 46 bits for priorities of Kong routes (#5024)
Browse files Browse the repository at this point in the history
* fix: use only 46 bits for priorities of Kong routes
  • Loading branch information
randmonkey authored Oct 31, 2023
1 parent 0422f3b commit b2475f3
Show file tree
Hide file tree
Showing 18 changed files with 92 additions and 83 deletions.
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:/Kong/kubernetes-ingress-controller/pull/4928)
- Fixed a panic when receiving broken configuration from Kong Gateway.
[#5003](https:/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:/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

0 comments on commit b2475f3

Please sign in to comment.