| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- package routing
- import (
- "fmt"
- "net/netip"
- "strings"
- )
- const (
- // Sentinel value
- BucketNotCalculated = -1
- )
- type Gateways []Gateway
- func (g Gateways) String() string {
- var str strings.Builder
- for i, gw := range g {
- str.WriteString(gw.String())
- if i < len(g)-1 {
- str.WriteString(", ")
- }
- }
- return str.String()
- }
- type Gateway struct {
- addr netip.Addr
- weight int
- bucketUpperBound int
- }
- func NewGateway(addr netip.Addr, weight int) Gateway {
- return Gateway{addr: addr, weight: weight, bucketUpperBound: BucketNotCalculated}
- }
- func (g *Gateway) BucketUpperBound() int {
- return g.bucketUpperBound
- }
- func (g *Gateway) Addr() netip.Addr {
- return g.addr
- }
- func (g *Gateway) String() string {
- return fmt.Sprintf("{addr: %s, weight: %d}", g.addr, g.weight)
- }
- // Divide and round to nearest integer
- func divideAndRound(v uint64, d uint64) uint64 {
- var tmp uint64 = v + d/2
- return tmp / d
- }
- // Implements Hash-Threshold mapping, equivalent to the implementation in the linux kernel.
- // After this function returns each gateway will have a
- // positive bucketUpperBound with a maximum value of 2147483647 (INT_MAX)
- func CalculateBucketsForGateways(gateways []Gateway) {
- var totalWeight int = 0
- for i := range gateways {
- totalWeight += gateways[i].weight
- }
- var loopWeight int = 0
- for i := range gateways {
- loopWeight += gateways[i].weight
- gateways[i].bucketUpperBound = int(divideAndRound(uint64(loopWeight)<<31, uint64(totalWeight))) - 1
- }
- }
|