alice-lg/pkg/pools/communities.go

78 lines
2.0 KiB
Go
Raw Normal View History

2022-11-16 10:51:49 +01:00
package pools
import (
"reflect"
"sync"
"github.com/alice-lg/alice-lg/pkg/api"
)
2022-11-16 11:12:09 +01:00
// CommunitiesPool 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.)
2022-11-16 11:12:09 +01:00
type CommunitiesPool struct {
communitiesRoot *Node
root *Node
2022-11-16 10:51:49 +01:00
sync.Mutex
}
2022-11-16 11:12:09 +01:00
// NewCommunitiesPool creates a new pool for lists
2022-11-16 10:51:49 +01:00
// of BGP communities.
2022-11-16 11:12:09 +01:00
func NewCommunitiesPool() *CommunitiesPool {
return &CommunitiesPool{
2022-11-16 11:20:54 +01:00
communitiesRoot: NewNode([]int{}),
root: NewNode([]api.Community{}),
2022-11-16 10:51:49 +01:00
}
}
// Acquire a list of bgp communities
2022-11-16 11:12:09 +01:00
func (p *CommunitiesPool) 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
2022-11-16 10:51:49 +01:00
ids := make([]int, len(communities))
for i, comm := range communities {
2022-11-16 11:12:09 +01:00
commPtr := p.communitiesRoot.traverse(comm, comm)
2022-11-16 10:51:49 +01:00
addr := reflect.ValueOf(commPtr).UnsafePointer()
ids[i] = int(uintptr(addr))
}
if len(ids) == 0 {
return p.root.ptr.([]api.Community)
}
return p.root.traverse(communities, ids).([]api.Community)
}
2022-11-16 13:30:44 +01:00
// NewExtCommunitiesPool creates a new pool for extended communities
func NewExtCommunitiesPool() *CommunitiesPool {
return &CommunitiesPool{
communitiesRoot: NewNode([]int{}),
root: NewNode([]api.ExtCommunity{}),
}
}
// AcquireExt a list of ext bgp communities
func (p *CommunitiesPool) AcquireExt(communities []api.ExtCommunity) []api.ExtCommunity {
p.Lock()
defer p.Unlock()
// Make identification list
ids := make([]int, len(communities))
for i, comm := range communities {
r := 0 // RO
if comm[0].(string) == "rt" {
r = 1
}
icomm := []int{r, comm[1].(int), comm[2].(int)}
// get community identifier
commPtr := p.communitiesRoot.traverse(icomm, icomm)
addr := reflect.ValueOf(commPtr).UnsafePointer()
ids[i] = int(uintptr(addr))
}
if len(ids) == 0 {
return p.root.ptr.([]api.ExtCommunity)
}
return p.root.traverse(communities, ids).([]api.ExtCommunity)
}