12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- package routing
- import (
- "fmt"
- "net/netip"
- )
- const (
- // Sentinal value
- BucketNotCalculated = -1
- )
- type Gateways []Gateway
- func (g Gateways) String() string {
- str := ""
- for i, gw := range g {
- str += gw.String()
- if i < len(g)-1 {
- str += ", "
- }
- }
- return str
- }
- 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
- }
- }
|