Skip to content
Snippets Groups Projects
path.go 3.08 KiB
Newer Older
Oliver Herms's avatar
Oliver Herms committed
import (
	"fmt"
cedi's avatar
cedi committed

	bnet "github.com/bio-routing/bio-rd/net"
Oliver Herms's avatar
Oliver Herms committed
)
Oliver Herms's avatar
Oliver Herms committed

Oliver Herms's avatar
Oliver Herms committed
// Path represents a network path
type Path struct {
cedi's avatar
cedi committed
	Type        uint8
	StaticPath  *StaticPath
	BGPPath     *BGPPath
	NetlinkPath *NetlinkPath
// Select returns negative if p < q, 0 if paths are equal, positive if p > q
func (p *Path) Select(q *Path) int8 {
	switch {
	case p == nil && q == nil:
		return 0
	case p == nil:
		return -1
	case q == nil:
		return 1
	default:
	}

Oliver Herms's avatar
Oliver Herms committed
	if p.Type > q.Type {
		return 1
	}

	if p.Type < q.Type {
		return -1
	}

	switch p.Type {
	case BGPPathType:
		return p.BGPPath.Select(q.BGPPath)
Oliver Herms's avatar
Oliver Herms committed
	case StaticPathType:
		return p.StaticPath.Select(q.StaticPath)
cedi's avatar
cedi committed
	case NetlinkPathType:
		return p.NetlinkPath.Select(q.NetlinkPath)
Oliver Herms's avatar
Oliver Herms committed
	}

	panic("Unknown path type")
}

Oliver Herms's avatar
Oliver Herms committed
// ECMP checks if path p and q are equal enough to be considered for ECMP usage
Oliver Herms's avatar
Oliver Herms committed
func (p *Path) ECMP(q *Path) bool {
	switch p.Type {
	case BGPPathType:
		return p.BGPPath.ECMP(q.BGPPath)
	case StaticPathType:
		return p.StaticPath.ECMP(q.StaticPath)
cedi's avatar
cedi committed
	case NetlinkPathType:
		return p.NetlinkPath.ECMP(q.NetlinkPath)
Oliver Herms's avatar
Oliver Herms committed
	}

	panic("Unknown path type")
}

Oliver Herms's avatar
Oliver Herms committed
// Equal checks if paths p and q are equal
func (p *Path) Equal(q *Path) bool {
	if p == nil || q == nil {
		return false
	}

	if p.Type != q.Type {
		return false
	}

	switch p.Type {
	case BGPPathType:
		return p.BGPPath.Equal(q.BGPPath)
	case StaticPathType:
		return p.StaticPath.Equal(q.StaticPath)
	}

	return p.Select(q) == 0
Oliver Herms's avatar
Oliver Herms committed

// PathsDiff gets the list of elements contained by a but not b
func PathsDiff(a, b []*Path) []*Path {
	ret := make([]*Path, 0)

	for _, pa := range a {
		if !pathsContains(pa, b) {
			ret = append(ret, pa)
		}
	}

	return ret
}

func pathsContains(needle *Path, haystack []*Path) bool {
	for _, p := range haystack {
		if p == needle {
			return true
		}
	}

	return false
}

cedi's avatar
cedi committed
// Print all known information about a route in logfile friendly format
cedi's avatar
cedi committed
func (p *Path) String() string {
	switch p.Type {
	case StaticPathType:
		return "not implemented yet"
	case BGPPathType:
		return p.BGPPath.String()
	case NetlinkPathType:
		return p.NetlinkPath.String()
	default:
		return "Unknown paty type. Probably not implemented yet"
	}
}

cedi's avatar
cedi committed
// Print all known information about a route in human readable form
Oliver Herms's avatar
Oliver Herms committed
func (p *Path) Print() string {
	protocol := ""
	switch p.Type {
	case StaticPathType:
		protocol = "static"
	case BGPPathType:
		protocol = "BGP"
cedi's avatar
cedi committed
	case NetlinkPathType:
		protocol = "Netlink"
Oliver Herms's avatar
Oliver Herms committed
	}

	ret := fmt.Sprintf("\tProtocol: %s\n", protocol)
	switch p.Type {
	case StaticPathType:
		ret += "Not implemented yet"
	case BGPPathType:
		ret += p.BGPPath.Print()
cedi's avatar
cedi committed
	case NetlinkPathType:
		ret += p.NetlinkPath.Print()
Oliver Herms's avatar
Oliver Herms committed
	}

	return ret
}
cedi's avatar
cedi committed
// Copy a route
func (p *Path) Copy() *Path {
	if p == nil {
		return nil
	}

	cp := *p
	cp.BGPPath = cp.BGPPath.Copy()
	cp.StaticPath = cp.StaticPath.Copy()

	return &cp
}
cedi's avatar
cedi committed

cedi's avatar
cedi committed
// NextHop returns the next hop IP Address
cedi's avatar
cedi committed
func (p *Path) NextHop() bnet.IP {
	switch p.Type {
	case BGPPathType:
		return p.BGPPath.NextHop
	case StaticPathType:
		return p.StaticPath.NextHop
	case NetlinkPathType:
		return p.NetlinkPath.NextHop
	}

Oliver Herms's avatar
Oliver Herms committed
	panic("Unknown path type")
cedi's avatar
cedi committed
}