@@ -15,7 +15,6 @@ package translator
1515import (
1616 "encoding/json"
1717 "fmt"
18- "sort"
1918 "strings"
2019
2120 "github.com/api7/gopkg/pkg/log"
@@ -354,31 +353,61 @@ func (t *Translator) translateBackendRef(tctx *provider.TranslateContext, ref ga
354353 return t .translateEndpointSlice (portName , weight , endpointSlices )
355354}
356355
357- // calculateMatchPriority calculate the priority of HTTPRouteMatch, according to the Gateway API specification
358- // the higher the return value, the higher the priority
359- func calculateMatchPriority (match * gatewayv1.HTTPRouteMatch ) int64 {
360- var score int64 = 0
356+ // calculateHTTPRoutePriority calculates the priority of the HTTP route.
357+ // ref: https://github.com/Kong/kubernetes-ingress-controller/blob/57472721319e2c63e56cb8540425257e8e02520f/internal/dataplane/translator/subtranslator/httproute_atc.go#L279-L296
358+ func calculateHTTPRoutePriority (match * gatewayv1.HTTPRouteMatch , ruleIndex int ) uint64 {
359+ const (
360+ // ExactPathShiftBits assigns bit 34 to mark if the match is exact path match.
361+ ExactPathShiftBits = 34
362+ // PathLengthShiftBits assigns bits 23-32 to path length. (max length = 1024, but must start with /)
363+ PathLengthShiftBits = 23
364+ // MethodMatchShiftBits assigns bit 22 to mark if method is specified.
365+ MethodMatchShiftBits = 22
366+ // HeaderNumberShiftBits assign bits 17-21 to number of headers. (max number of headers = 16)
367+ HeaderNumberShiftBits = 17
368+ // QueryParamNumberShiftBits makes bits 12-16 used for number of query params (max number of query params = 16)
369+ QueryParamNumberShiftBits = 12
370+ // RuleIndexShiftBits assigns bits 7-11 to rule index. (max number of rules = 16)
371+ RuleIndexShiftBits = 7
372+ )
373+
374+ var priority uint64 = 0
361375
362- // 1. Exact path matches have the highest priority
376+ // ExactPathShiftBits
363377 if match .Path != nil && match .Path .Type != nil && * match .Path .Type == gatewayv1 .PathMatchExact {
364- score += 10000
365- } else if match .Path != nil && match .Path .Type != nil && * match .Path .Type == gatewayv1 .PathMatchPathPrefix && match .Path .Value != nil {
366- // 2. Prefix path matches, the longer the string, the higher the priority
367- score += 1000 + int64 (len (* match .Path .Value ))
378+ priority |= (1 << ExactPathShiftBits )
379+ }
380+
381+ // PathLengthShiftBits
382+ // max length of path is 1024, but path must start with /, so we use PathLength-1 to fill the bits.
383+ if match .Path != nil && match .Path .Value != nil {
384+ pathLength := len (* match .Path .Value )
385+ if pathLength > 0 {
386+ priority |= (uint64 (pathLength - 1 ) << PathLengthShiftBits )
387+ }
368388 }
369389
370- // 3. Method matching
390+ // MethodMatchShiftBits
371391 if match .Method != nil {
372- score += 100
392+ priority |= ( 1 << MethodMatchShiftBits )
373393 }
374394
375- // 4. Header matching, the more headers, the higher the priority
376- score += int64 (len (match .Headers ) * 10 )
395+ // HeaderNumberShiftBits
396+ headerCount := len (match .Headers )
397+ priority |= (uint64 (headerCount ) << HeaderNumberShiftBits )
377398
378- // 5. Query parameter matching, the more query parameters, the higher the priority
379- score += int64 (len (match .QueryParams ))
399+ // QueryParamNumberShiftBits
400+ queryParamCount := len (match .QueryParams )
401+ priority |= (uint64 (queryParamCount ) << QueryParamNumberShiftBits )
380402
381- return score
403+ // RuleIndexShiftBits
404+ index := 16 - ruleIndex
405+ if index < 0 {
406+ index = 0
407+ }
408+ priority |= (uint64 (index ) << RuleIndexShiftBits )
409+
410+ return priority
382411}
383412
384413func (t * Translator ) TranslateHTTPRoute (tctx * provider.TranslateContext , httpRoute * gatewayv1.HTTPRoute ) (* TranslateResult , error ) {
@@ -393,7 +422,7 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
393422
394423 labels := label .GenLabel (httpRoute )
395424
396- for i , rule := range rules {
425+ for ruleIndex , rule := range rules {
397426 upstream := adctypes .NewDefaultUpstream ()
398427 for _ , backend := range rule .BackendRefs {
399428 if backend .Namespace == nil {
@@ -410,7 +439,7 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
410439 service := adctypes .NewDefaultService ()
411440 service .Labels = labels
412441
413- service .Name = adctypes .ComposeServiceNameWithRule (httpRoute .Namespace , httpRoute .Name , fmt .Sprintf ("%d" , i ))
442+ service .Name = adctypes .ComposeServiceNameWithRule (httpRoute .Namespace , httpRoute .Name , fmt .Sprintf ("%d" , ruleIndex ))
414443 service .ID = id .GenID (service .Name )
415444 service .Hosts = hosts
416445 service .Upstream = upstream
@@ -428,11 +457,6 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
428457 },
429458 },
430459 }
431- } else {
432- // Sort the matches by priority
433- sort .Slice (matches , func (a , b int ) bool {
434- return calculateMatchPriority (& matches [a ]) > calculateMatchPriority (& matches [b ])
435- })
436460 }
437461
438462 routes := []* adctypes.Route {}
@@ -442,15 +466,15 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
442466 return nil , err
443467 }
444468
445- name := adctypes .ComposeRouteName (httpRoute .Namespace , httpRoute .Name , fmt .Sprintf ("%d-%d" , i , j ))
469+ name := adctypes .ComposeRouteName (httpRoute .Namespace , httpRoute .Name , fmt .Sprintf ("%d-%d" , ruleIndex , j ))
446470 route .Name = name
447471 route .ID = id .GenID (name )
448472 route .Labels = labels
449473 route .EnableWebsocket = ptr .To (true )
450474
451475 // Set the route priority
452- priority := calculateMatchPriority (& match )
453- route .Priority = & priority
476+ priority := calculateHTTPRoutePriority (& match , ruleIndex )
477+ route .Priority = ptr . To ( int64 ( priority ))
454478
455479 routes = append (routes , route )
456480 }
0 commit comments