Skip to content
Snippets Groups Projects
path.go 2.98 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Herms's avatar
    Oliver Herms committed
    import (
    	"fmt"
    
    cedi's avatar
    cedi committed
    	"log"
    
    	bnet "github.com/bio-routing/bio-rd/net"
    
    Oliver Herms's avatar
    Oliver Herms committed
    )
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    
    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")
    }
    
    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")
    }
    
    
    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
    	default:
    		log.Panic("Type %d not implemented (yet)", p.Type)
    	}
    
    	return bnet.IP{}
    }