Skip to content
Snippets Groups Projects
bgp.go 3.09 KiB
Newer Older
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
}