Skip to content
Snippets Groups Projects
Commit 826e7afd authored by Daniel Czerwonk's avatar Daniel Czerwonk
Browse files

added hash computation for BGPPath

parent 0d2c721d
No related branches found
No related tags found
No related merge requests found
package route
import (
"crypto/sha256"
"fmt"
"strconv"
"strings"
......@@ -192,6 +193,28 @@ func (p *BGPPath) Copy() *BGPPath {
return &cp
}
// ComputeHash computes an hash over all attributes of the path
func (b *BGPPath) ComputeHash() string {
s := fmt.Sprintf("%d\t%d\t%s\t%d\t%d\t%v\t%d\t%d\t%s\t%s\t%d",
b.NextHop,
b.LocalPref,
b.ASPath,
b.Origin,
b.MED,
b.EBGP,
b.BGPIdentifier,
b.Source,
b.Communities,
b.LargeCommunities,
b.PathIdentifier)
r := strings.NewReader(s)
h := sha256.New()
r.WriteTo(h)
return fmt.Sprintf("%x", h.Sum(nil))
}
func uint32To4Byte(addr uint32) [4]byte {
slice := convert.Uint32Byte(addr)
ret := [4]byte{
......
......@@ -7,7 +7,7 @@ import (
// BGPPathManager is a component used to deduplicate BGP Path objects
type BGPPathManager struct {
paths map[BGPPath]*BGPPathCounter
paths map[string]*BGPPathCounter
mu sync.Mutex
}
......@@ -24,7 +24,7 @@ func NewBGPPathManager() *BGPPathManager {
}
func (m *BGPPathManager) lookup(p BGPPath) *BGPPath {
pathCounter, ok := m.paths[p]
pathCounter, ok := m.paths[p.ComputeHash()]
if !ok {
return nil
}
......@@ -37,15 +37,17 @@ func (m *BGPPathManager) AddPath(p BGPPath) *BGPPath {
m.mu.Lock()
defer m.mu.Unlock()
hash := p.ComputeHash()
q := m.lookup(p)
if q == nil {
m.paths[p] = &BGPPathCounter{
m.paths[hash] = &BGPPathCounter{
path: &p,
}
}
m.paths[p].usageCount++
return m.paths[p].path
m.paths[hash].usageCount++
return m.paths[hash].path
}
// RemovePath notifies us that there is one user less for path p
......@@ -58,8 +60,10 @@ func (m *BGPPathManager) RemovePath(p BGPPath) {
return
}
m.paths[p].usageCount--
if m.paths[p].usageCount == 0 {
delete(m.paths, p)
hash := p.ComputeHash()
m.paths[hash].usageCount--
if m.paths[hash].usageCount == 0 {
delete(m.paths, hash)
}
}
package route
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestComputeHash(t *testing.T) {
p := &BGPPath{
ASPath: "123 456",
BGPIdentifier: 1,
Communities: "(123, 456)",
EBGP: false,
LargeCommunities: "(1, 2, 3)",
LocalPref: 100,
MED: 1,
NextHop: 100,
PathIdentifier: 5,
Source: 4,
}
assert.Equal(t, "24d5b7681ab221b464a2c772e828628482cbfa4d5c6aac7a8285d33ef99b868a", p.ComputeHash())
p.LocalPref = 150
assert.NotEqual(t, "24d5b7681ab221b464a2c772e828628482cbfa4d5c6aac7a8285d33ef99b868a", p.ComputeHash())
}
......@@ -11,7 +11,7 @@ var maxUint32 = ^uint32(0)
// pathIDManager manages BGP path identifiers for add-path. This is no thread safe (and doesn't need to be).
type pathIDManager struct {
ids map[uint32]uint64
idByPath map[route.BGPPath]uint32
idByPath map[string]uint32
last uint32
used uint32
}
......@@ -19,13 +19,15 @@ type pathIDManager struct {
func newPathIDManager() *pathIDManager {
return &pathIDManager{
ids: make(map[uint32]uint64),
idByPath: make(map[route.BGPPath]uint32),
idByPath: make(map[string]uint32),
}
}
func (fm *pathIDManager) addPath(p *route.Path) (uint32, error) {
if _, exists := fm.idByPath[*p.BGPPath]; exists {
id := fm.idByPath[*p.BGPPath]
hash := p.BGPPath.ComputeHash()
if _, exists := fm.idByPath[hash]; exists {
id := fm.idByPath[hash]
fm.ids[id]++
return id, nil
}
......@@ -43,7 +45,7 @@ func (fm *pathIDManager) addPath(p *route.Path) (uint32, error) {
break
}
fm.idByPath[*p.BGPPath] = fm.last
fm.idByPath[hash] = fm.last
fm.ids[fm.last] = 1
fm.used++
......@@ -51,15 +53,17 @@ func (fm *pathIDManager) addPath(p *route.Path) (uint32, error) {
}
func (fm *pathIDManager) releasePath(p *route.Path) (uint32, error) {
if _, exists := fm.idByPath[*p.BGPPath]; !exists {
hash := p.BGPPath.ComputeHash()
if _, exists := fm.idByPath[hash]; !exists {
return 0, fmt.Errorf("ID not found for path: %s", p.Print())
}
id := fm.idByPath[*p.BGPPath]
id := fm.idByPath[hash]
fm.ids[id]--
if fm.ids[id] == 0 {
delete(fm.ids, fm.idByPath[*p.BGPPath])
delete(fm.idByPath, *p.BGPPath)
delete(fm.ids, fm.idByPath[hash])
delete(fm.idByPath, hash)
}
return id, nil
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment