Skip to content
Snippets Groups Projects
path_id_manager.go 1.29 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Herms's avatar
    Oliver Herms committed
    package adjRIBOut
    
    import (
    	"fmt"
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    	"github.com/bio-routing/bio-rd/route"
    
    Oliver Herms's avatar
    Oliver Herms committed
    )
    
    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 {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	ids      map[uint32]uint64
    
    	idByPath map[string]uint32
    
    Oliver Herms's avatar
    Oliver Herms committed
    	last     uint32
    	used     uint32
    
    Oliver Herms's avatar
    Oliver Herms committed
    }
    
    func newPathIDManager() *pathIDManager {
    	return &pathIDManager{
    
    Oliver Herms's avatar
    Oliver Herms committed
    		ids:      make(map[uint32]uint64),
    
    		idByPath: make(map[string]uint32),
    
    Oliver Herms's avatar
    Oliver Herms committed
    func (fm *pathIDManager) addPath(p *route.Path) (uint32, error) {
    
    	hash := p.BGPPath.ComputeHash()
    
    	if _, exists := fm.idByPath[hash]; exists {
    		id := fm.idByPath[hash]
    
    Oliver Herms's avatar
    Oliver Herms committed
    		fm.ids[id]++
    		return id, nil
    	}
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if fm.used == maxUint32 {
    		return 0, fmt.Errorf("Out of path IDs")
    	}
    
    	fm.last++
    	for {
    		if _, exists := fm.ids[fm.last]; exists {
    			fm.last++
    			continue
    		}
    		break
    	}
    
    
    	fm.idByPath[hash] = fm.last
    
    Oliver Herms's avatar
    Oliver Herms committed
    	fm.ids[fm.last] = 1
    
    Oliver Herms's avatar
    Oliver Herms committed
    	fm.used++
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    	return fm.last, nil
    
    Oliver Herms's avatar
    Oliver Herms committed
    func (fm *pathIDManager) releasePath(p *route.Path) (uint32, error) {
    
    	hash := p.BGPPath.ComputeHash()
    
    	if _, exists := fm.idByPath[hash]; !exists {
    
    Oliver Herms's avatar
    Oliver Herms committed
    		return 0, fmt.Errorf("ID not found for path: %s", p.Print())
    
    Oliver Herms's avatar
    Oliver Herms committed
    	}
    
    	id := fm.idByPath[hash]
    
    Oliver Herms's avatar
    Oliver Herms committed
    	fm.ids[id]--
    	if fm.ids[id] == 0 {
    
    		delete(fm.ids, fm.idByPath[hash])
    		delete(fm.idByPath, hash)
    
    Oliver Herms's avatar
    Oliver Herms committed
    	fm.used--
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    	return id, nil
    
    Oliver Herms's avatar
    Oliver Herms committed
    }