Skip to content
Snippets Groups Projects
bgp.go 3.09 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Herms's avatar
    Oliver Herms committed
    import (
    	"fmt"
    
    	"strconv"
    	"strings"
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    	"github.com/taktv6/tflow2/convert"
    )
    
    
    // BGPPath represents a set of BGP path attributes
    type BGPPath struct {
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	PathIdentifier   uint32
    	NextHop          uint32
    	LocalPref        uint32
    	ASPath           string
    	ASPathLen        uint16
    	Origin           uint8
    	MED              uint32
    	EBGP             bool
    	BGPIdentifier    uint32
    	Source           uint32
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	Communities      string
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	LargeCommunities string
    
    Oliver Herms's avatar
    Oliver Herms committed
    // ECMP determines if routes b and c are euqal in terms of ECMP
    func (b *BGPPath) ECMP(c *BGPPath) bool {
    	return b.LocalPref == c.LocalPref && b.ASPathLen == c.ASPathLen && b.MED == c.MED && b.Origin == c.Origin
    }
    
    Oliver Herms's avatar
    Oliver Herms committed
    // Compare returns negative if b < c, 0 if paths are equal, positive if b > c
    func (b *BGPPath) Compare(c *BGPPath) int8 {
    	if c.LocalPref < b.LocalPref {
    		return 1
    	}
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if c.LocalPref > b.LocalPref {
    		return -1
    	}
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if c.ASPathLen > b.ASPathLen {
    		return 1
    	}
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if c.ASPathLen < b.ASPathLen {
    		return -1
    	}
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if c.Origin > b.Origin {
    		return 1
    	}
    
    	if c.Origin < b.Origin {
    		return -1
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if c.MED > b.MED {
    		return 1
    	}
    
    	if c.MED < b.MED {
    		return -1
    	}
    
    	if c.BGPIdentifier < b.BGPIdentifier {
    		return 1
    	}
    
    	if c.BGPIdentifier > b.BGPIdentifier {
    		return -1
    	}
    
    	if c.Source < b.Source {
    		return 1
    	}
    
    	if c.Source > b.Source {
    		return -1
    	}
    
    
    	if c.NextHop < b.NextHop {
    		return 1
    	}
    
    	if c.NextHop > b.NextHop {
    		return -1
    	}
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    	return 0
    
    }
    
    func (b *BGPPath) betterECMP(c *BGPPath) bool {
    	if c.LocalPref < b.LocalPref {
    		return false
    	}
    
    	if c.LocalPref > b.LocalPref {
    		return true
    	}
    
    	if c.ASPathLen > b.ASPathLen {
    		return false
    	}
    
    	if c.ASPathLen < b.ASPathLen {
    		return true
    	}
    
    	if c.Origin > b.Origin {
    		return false
    	}
    
    	if c.Origin < b.Origin {
    		return true
    	}
    
    	if c.MED > b.MED {
    		return false
    	}
    
    	if c.MED < b.MED {
    		return true
    	}
    
    	return false
    }
    
    func (b *BGPPath) better(c *BGPPath) bool {
    	if b.betterECMP(c) {
    		return true
    	}
    
    	if c.BGPIdentifier < b.BGPIdentifier {
    		return true
    	}
    
    	if c.Source < b.Source {
    		return true
    	}
    
    	return false
    }
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    func (b *BGPPath) Print() string {
    	origin := ""
    	switch b.Origin {
    	case 0:
    		origin = "Incomplete"
    	case 1:
    		origin = "EGP"
    	case 2:
    		origin = "IGP"
    	}
    	ret := fmt.Sprintf("\t\tLocal Pref: %d\n", b.LocalPref)
    	ret += fmt.Sprintf("\t\tOrigin: %s\n", origin)
    	ret += fmt.Sprintf("\t\tAS Path: %s\n", b.ASPath)
    	nh := uint32To4Byte(b.NextHop)
    	ret += fmt.Sprintf("\t\tNEXT HOP: %d.%d.%d.%d\n", nh[0], nh[1], nh[2], nh[3])
    	ret += fmt.Sprintf("\t\tMED: %d\n", b.MED)
    
    	return ret
    }
    
    
    func (b *BGPPath) Prepend(asn uint32, times uint16) {
    
    	if times == 0 {
    		return
    	}
    
    	asnStr := strconv.FormatUint(uint64(asn), 10)
    
    	path := make([]string, times+1)
    
    	for i := 0; uint16(i) < times; i++ {
    
    		path[i] = asnStr
    
    	path[times] = b.ASPath
    
    	b.ASPath = strings.TrimSuffix(strings.Join(path, " "), " ")
    	b.ASPathLen = b.ASPathLen + times
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    func (p *BGPPath) Copy() *BGPPath {
    	if p == nil {
    		return nil
    	}
    
    	cp := *p
    	return &cp
    }
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    func uint32To4Byte(addr uint32) [4]byte {
    	slice := convert.Uint32Byte(addr)
    	ret := [4]byte{
    		slice[0],
    		slice[1],
    		slice[2],
    		slice[3],
    	}
    	return ret
    }