Skip to content

Commit 4454e87

Browse files
committed
fix: calculate HTTPRoute Priority
Signed-off-by: ashing <[email protected]>
1 parent 8ba5d71 commit 4454e87

File tree

1 file changed

+49
-27
lines changed

1 file changed

+49
-27
lines changed

internal/provider/adc/translator/httproute.go

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package translator
33
import (
44
"encoding/json"
55
"fmt"
6-
"sort"
76
"strings"
87

98
"github.com/api7/gopkg/pkg/log"
@@ -342,31 +341,59 @@ func (t *Translator) translateBackendRef(tctx *provider.TranslateContext, ref ga
342341
return t.translateEndpointSlice(portName, weight, endpointSlices)
343342
}
344343

345-
// calculateMatchPriority calculate the priority of HTTPRouteMatch, according to the Gateway API specification
346-
// the higher the return value, the higher the priority
347-
func calculateMatchPriority(match *gatewayv1.HTTPRouteMatch) int64 {
348-
var score int64 = 0
344+
func calculateHTTPRoutePriority(match *gatewayv1.HTTPRouteMatch, ruleIndex int) uint64 {
345+
const (
346+
// ExactPathShiftBits assigns bit 34 to mark if the match is exact path match.
347+
ExactPathShiftBits = 34
348+
// PathLengthShiftBits assigns bits 23-32 to path length. (max length = 1024, but must start with /)
349+
PathLengthShiftBits = 23
350+
// MethodMatchShiftBits assigns bit 22 to mark if method is specified.
351+
MethodMatchShiftBits = 22
352+
// HeaderNumberShiftBits assign bits 17-21 to number of headers. (max number of headers = 16)
353+
HeaderNumberShiftBits = 17
354+
// QueryParamNumberShiftBits makes bits 12-16 used for number of query params (max number of query params = 16)
355+
QueryParamNumberShiftBits = 12
356+
// RuleIndexShiftBits assigns bits 7-11 to rule index. (max number of rules = 16)
357+
RuleIndexShiftBits = 7
358+
)
359+
360+
var priority uint64 = 0
349361

350-
// 1. Exact path matches have the highest priority
362+
// ExactPathShiftBits
351363
if match.Path != nil && match.Path.Type != nil && *match.Path.Type == gatewayv1.PathMatchExact {
352-
score += 10000
353-
} else if match.Path != nil && match.Path.Type != nil && *match.Path.Type == gatewayv1.PathMatchPathPrefix && match.Path.Value != nil {
354-
// 2. Prefix path matches, the longer the string, the higher the priority
355-
score += 1000 + int64(len(*match.Path.Value))
364+
priority |= (1 << ExactPathShiftBits)
365+
}
366+
367+
// PathLengthShiftBits
368+
// max length of path is 1024, but path must start with /, so we use PathLength-1 to fill the bits.
369+
if match.Path != nil && match.Path.Value != nil {
370+
pathLength := len(*match.Path.Value)
371+
if pathLength > 0 {
372+
priority |= (uint64(pathLength-1) << PathLengthShiftBits)
373+
}
356374
}
357375

358-
// 3. Method matching
376+
// MethodMatchShiftBits
359377
if match.Method != nil {
360-
score += 100
378+
priority |= (1 << MethodMatchShiftBits)
361379
}
362380

363-
// 4. Header matching, the more headers, the higher the priority
364-
score += int64(len(match.Headers) * 10)
381+
// HeaderNumberShiftBits
382+
headerCount := len(match.Headers)
383+
priority |= (uint64(headerCount) << HeaderNumberShiftBits)
365384

366-
// 5. Query parameter matching, the more query parameters, the higher the priority
367-
score += int64(len(match.QueryParams))
385+
// QueryParamNumberShiftBits
386+
queryParamCount := len(match.QueryParams)
387+
priority |= (uint64(queryParamCount) << QueryParamNumberShiftBits)
368388

369-
return score
389+
// RuleIndexShiftBits
390+
index := 16 - ruleIndex
391+
if index < 0 {
392+
index = 0
393+
}
394+
priority |= (uint64(index) << RuleIndexShiftBits)
395+
396+
return priority
370397
}
371398

372399
func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRoute *gatewayv1.HTTPRoute) (*TranslateResult, error) {
@@ -381,7 +408,7 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
381408

382409
labels := label.GenLabel(httpRoute)
383410

384-
for i, rule := range rules {
411+
for ruleIndex, rule := range rules {
385412
upstream := adctypes.NewDefaultUpstream()
386413
for _, backend := range rule.BackendRefs {
387414
if backend.Namespace == nil {
@@ -398,7 +425,7 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
398425
service := adctypes.NewDefaultService()
399426
service.Labels = labels
400427

401-
service.Name = adctypes.ComposeServiceNameWithRule(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d", i))
428+
service.Name = adctypes.ComposeServiceNameWithRule(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d", ruleIndex))
402429
service.ID = id.GenID(service.Name)
403430
service.Hosts = hosts
404431
service.Upstream = upstream
@@ -416,11 +443,6 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
416443
},
417444
},
418445
}
419-
} else {
420-
// Sort the matches by priority
421-
sort.Slice(matches, func(a, b int) bool {
422-
return calculateMatchPriority(&matches[a]) > calculateMatchPriority(&matches[b])
423-
})
424446
}
425447

426448
routes := []*adctypes.Route{}
@@ -430,15 +452,15 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
430452
return nil, err
431453
}
432454

433-
name := adctypes.ComposeRouteName(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d-%d", i, j))
455+
name := adctypes.ComposeRouteName(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d-%d", ruleIndex, j))
434456
route.Name = name
435457
route.ID = id.GenID(name)
436458
route.Labels = labels
437459
route.EnableWebsocket = ptr.To(true)
438460

439461
// Set the route priority
440-
priority := calculateMatchPriority(&match)
441-
route.Priority = &priority
462+
priority := calculateHTTPRoutePriority(&match, ruleIndex)
463+
route.Priority = ptr.To(int64(priority))
442464

443465
routes = append(routes, route)
444466
}

0 commit comments

Comments
 (0)