128 lines
3.1 KiB
Go
128 lines
3.1 KiB
Go
package pools
|
|
|
|
import (
|
|
"math"
|
|
"reflect"
|
|
"sync"
|
|
"unsafe"
|
|
|
|
"github.com/alice-lg/alice-lg/pkg/api"
|
|
)
|
|
|
|
// CommunitiesPool is for deduplicating a single BGP community.
|
|
// This works with large and standard communities. For extended
|
|
// communities, use the ExtCommunityPool.
|
|
type CommunitiesPool struct {
|
|
root *Node[int, api.Community]
|
|
sync.RWMutex
|
|
}
|
|
|
|
// NewCommunitiesPool creates a new pool for a single BGP community
|
|
func NewCommunitiesPool() *CommunitiesPool {
|
|
return &CommunitiesPool{
|
|
root: NewNode[int, api.Community](api.Community{}),
|
|
}
|
|
}
|
|
|
|
// Acquire a single bgp community
|
|
func (p *CommunitiesPool) Acquire(c api.Community) api.Community {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
if len(c) == 0 {
|
|
return p.root.value
|
|
}
|
|
return p.root.traverse(c, c)
|
|
}
|
|
|
|
// Read a single bgp community
|
|
func (p *CommunitiesPool) Read(c api.Community) api.Community {
|
|
p.RLock()
|
|
defer p.RUnlock()
|
|
if len(c) == 0 {
|
|
return p.root.value
|
|
}
|
|
return p.root.read(c)
|
|
}
|
|
|
|
// CommunitiesSetPool is for deduplicating a list of BGP communities
|
|
// (Large and default. The ext communities representation right now
|
|
// makes problems and need to be fixed. TODO.)
|
|
type CommunitiesSetPool struct {
|
|
root *Node[unsafe.Pointer, []api.Community]
|
|
sync.Mutex
|
|
}
|
|
|
|
// NewCommunitiesSetPool creates a new pool for lists
|
|
// of BGP communities.
|
|
func NewCommunitiesSetPool() *CommunitiesSetPool {
|
|
return &CommunitiesSetPool{
|
|
root: NewNode[unsafe.Pointer, []api.Community]([]api.Community{}),
|
|
}
|
|
}
|
|
|
|
// Acquire a list of bgp communities
|
|
func (p *CommunitiesSetPool) Acquire(
|
|
communities []api.Community,
|
|
) []api.Community {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
// Make identification list by using the pointer address
|
|
// of the deduplicated community as ID
|
|
ids := make([]unsafe.Pointer, len(communities))
|
|
set := make([]api.Community, len(communities))
|
|
for i, comm := range communities {
|
|
ptr := Communities.Acquire(comm)
|
|
ids[i] = reflect.ValueOf(ptr).UnsafePointer()
|
|
set[i] = ptr
|
|
}
|
|
if len(ids) == 0 {
|
|
return p.root.value
|
|
}
|
|
return p.root.traverse(set, ids)
|
|
}
|
|
|
|
// ExtCommunitiesSetPool is for deduplicating a list of ext. BGP communities
|
|
type ExtCommunitiesSetPool struct {
|
|
root *Node[unsafe.Pointer, []api.ExtCommunity]
|
|
sync.Mutex
|
|
}
|
|
|
|
// NewExtCommunitiesSetPool creates a new pool for lists
|
|
// of BGP communities.
|
|
func NewExtCommunitiesSetPool() *ExtCommunitiesSetPool {
|
|
return &ExtCommunitiesSetPool{
|
|
root: NewNode[unsafe.Pointer, []api.ExtCommunity]([]api.ExtCommunity{}),
|
|
}
|
|
}
|
|
|
|
func extPrefixToInt(s string) int {
|
|
v := 0
|
|
for i, c := range s {
|
|
v += int(math.Pow(1000.0, float64(i))) * int(c)
|
|
}
|
|
return v
|
|
}
|
|
|
|
// Acquire a list of ext bgp communities
|
|
func (p *ExtCommunitiesSetPool) Acquire(
|
|
communities []api.ExtCommunity,
|
|
) []api.ExtCommunity {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
// Make identification list
|
|
ids := make([]unsafe.Pointer, len(communities))
|
|
for i, comm := range communities {
|
|
r := extPrefixToInt(comm[0].(string))
|
|
icomm := []int{r, comm[1].(int), comm[2].(int)}
|
|
|
|
// get community identifier
|
|
ptr := ExtCommunities.Acquire(icomm)
|
|
ids[i] = reflect.ValueOf(ptr).UnsafePointer()
|
|
}
|
|
if len(ids) == 0 {
|
|
return p.root.value
|
|
}
|
|
return p.root.traverse(communities, ids)
|
|
}
|