@@ -3,7 +3,6 @@ package translator
33import (
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
372399func (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