alice-lg/pkg/pools/communities.go

128 lines
3.1 KiB
Go
Raw Permalink Normal View History

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