diff options
Diffstat (limited to 'table/path.go')
-rw-r--r-- | table/path.go | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/table/path.go b/table/path.go new file mode 100644 index 00000000..93d09d8f --- /dev/null +++ b/table/path.go @@ -0,0 +1,339 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package table + +import ( + "fmt" + "github.com/osrg/gobgp/packet" + "github.com/osrg/gobgp/utils" + "net" +) + +type Path interface { + String() string + getPathAttributeMap() *utils.OrderedMap + getPathAttribute(int) bgp.PathAttributeInterface + clone(forWithdrawal bool) Path + setRouteFamily(ROUTE_FAMILY RouteFamily) + getRouteFamily() RouteFamily + setSource(source *Peer) + getSource() *Peer + setNexthop(nexthop net.IP) + getNexthop() net.IP + setSourceVerNum(sourceVerNum int) + getSourceVerNum() int + setWithdraw(withdraw bool) + isWithdraw() bool + setNlri(nlri bgp.AddrPrefixInterface) + getNlri() bgp.AddrPrefixInterface + getPrefix() net.IP + setMedSetByTargetNeighbor(medSetByTargetNeighbor bool) + getMedSetByTargetNeighbor() bool +} + +type PathDefault struct { + ROUTE_FAMILY RouteFamily + source *Peer + nexthop net.IP + sourceVerNum int + withdraw bool + nlri bgp.AddrPrefixInterface + pattrMap *utils.OrderedMap + medSetByTargetNeighbor bool +} + +func NewPathDefault(source *Peer, nlri bgp.AddrPrefixInterface, sourceVerNum int, nexthop net.IP, + isWithdraw bool, pattr *utils.OrderedMap, medSetByTargetNeighbor bool) *PathDefault { + if source == nil { + logger.Error("Need to provide source") + return nil + } + + if !isWithdraw && (pattr == nil || nexthop == nil) { + logger.Error("Need to provide nexthop and patattrs for path that is not a withdraw.") + return nil + } + + path := &PathDefault{} + path.ROUTE_FAMILY = RF_IPv4_UC + path.pattrMap = utils.NewOrderedMap() + if pattr != nil { + keyList := pattr.KeyLists() + for key := keyList.Front(); key != nil; key = key.Next() { + key := key.Value + val := pattr.Get(key) + e := path.pattrMap.Append(key, val) + if e != nil { + logger.Error(e) + } + } + } + path.nlri = nlri + path.source = source + path.nexthop = nexthop + path.sourceVerNum = sourceVerNum + path.withdraw = isWithdraw + path.medSetByTargetNeighbor = medSetByTargetNeighbor + + return path +} + +func (pd *PathDefault) setRouteFamily(ROUTE_FAMILY RouteFamily) { + pd.ROUTE_FAMILY = ROUTE_FAMILY +} +func (pd *PathDefault) getRouteFamily() RouteFamily { + return pd.ROUTE_FAMILY +} + +func (pd *PathDefault) setSource(source *Peer) { + pd.source = source +} +func (pd *PathDefault) getSource() *Peer { + return pd.source +} + +func (pd *PathDefault) setNexthop(nexthop net.IP) { + pd.nexthop = nexthop +} + +func (pd *PathDefault) getNexthop() net.IP { + return pd.nexthop +} + +func (pd *PathDefault) setSourceVerNum(sourceVerNum int) { + pd.sourceVerNum = sourceVerNum +} + +func (pd *PathDefault) getSourceVerNum() int { + return pd.sourceVerNum +} + +func (pd *PathDefault) setWithdraw(withdraw bool) { + pd.withdraw = withdraw +} + +func (pd *PathDefault) isWithdraw() bool { + return pd.withdraw +} + +func (pd *PathDefault) setNlri(nlri bgp.AddrPrefixInterface) { + pd.nlri = nlri +} + +func (pd *PathDefault) getNlri() bgp.AddrPrefixInterface { + return pd.nlri +} + +func (pd *PathDefault) setMedSetByTargetNeighbor(medSetByTargetNeighbor bool) { + pd.medSetByTargetNeighbor = medSetByTargetNeighbor +} + +func (pd *PathDefault) getMedSetByTargetNeighbor() bool { + return pd.medSetByTargetNeighbor +} + +//Copy the entity +func (pd *PathDefault) getPathAttributeMap() *utils.OrderedMap { + cpPattr := utils.NewOrderedMap() + keyList := pd.pattrMap.KeyLists() + for key := keyList.Front(); key != nil; key = key.Next() { + key := key.Value + val := pd.pattrMap.Get(key) + e := cpPattr.Append(key, val) + if e != nil { + logger.Error(e) + } + } + return cpPattr +} + +func (pd *PathDefault) getPathAttribute(pattrType int) bgp.PathAttributeInterface { + attr := pd.pattrMap.Get(pattrType) + if attr == nil { + logger.Debugf("Attribute Type %s is not found", AttributeType(pattrType)) + return nil + } + return attr.(bgp.PathAttributeInterface) +} + +func (pi *PathDefault) clone(forWithdrawal bool) Path { + pathAttrs := utils.NewOrderedMap() + if !forWithdrawal { + pathAttrs = pi.getPathAttributeMap() + } + clone := NewPathDefault(pi.getSource(), pi.getNlri(), pi.getSourceVerNum(), + pi.getNexthop(), forWithdrawal, pathAttrs, pi.getMedSetByTargetNeighbor()) + return clone +} + +// return Path's string representation +func (pi *PathDefault) String() string { + str := fmt.Sprintf("IPv4Path Source: %d, ", pi.getSourceVerNum()) + str = str + fmt.Sprintf(" NLRI: %s, ", pi.getPrefix().String()) + str = str + fmt.Sprintf(" nexthop: %s, ", pi.getNexthop().String()) + str = str + fmt.Sprintf(" withdraw: %s, ", pi.isWithdraw()) + str = str + fmt.Sprintf(" path attributes: %s, ", pi.getPathAttributeMap()) + return str +} + +func (pi *PathDefault) getPrefix() net.IP { + addrPrefix := pi.nlri.(*bgp.NLRInfo) + return addrPrefix.Prefix +} + +func getNextHop(pathAttributes []bgp.PathAttributeInterface) net.IP { + + for _, pathAttr := range pathAttributes { + switch p := pathAttr.(type) { + case *bgp.PathAttributeNextHop: + return p.Value + } + } + return nil + +} + +func createPathAttributeMap(pathAttributes []bgp.PathAttributeInterface) *utils.OrderedMap { + + pathAttrMap := utils.NewOrderedMap() + for _, attr := range pathAttributes { + var err error + switch a := attr.(type) { + case *bgp.PathAttributeOrigin: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_ORIGIN, a) + case *bgp.PathAttributeAsPath: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_AS_PATH, a) + case *bgp.PathAttributeNextHop: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_NEXT_HOP, a) + case *bgp.PathAttributeMultiExitDisc: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC, a) + case *bgp.PathAttributeLocalPref: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_LOCAL_PREF, a) + case *bgp.PathAttributeAtomicAggregate: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_ATOMIC_AGGREGATE, a) + case *bgp.PathAttributeAggregator: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_AGGREGATOR, a) + case *bgp.PathAttributeCommunities: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_COMMUNITIES, a) + case *bgp.PathAttributeOriginatorId: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID, a) + case *bgp.PathAttributeClusterList: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_CLUSTER_LIST, a) + case *bgp.PathAttributeMpReachNLRI: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI, a) + case *bgp.PathAttributeMpUnreachNLRI: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI, a) + case *bgp.PathAttributeExtendedCommunities: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES, a) + case *bgp.PathAttributeAs4Path: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_AS4_PATH, a) + case *bgp.PathAttributeAs4Aggregator: + err = pathAttrMap.Append(bgp.BGP_ATTR_TYPE_AS4_AGGREGATOR, a) + } + if err != nil { + return nil + } + } + return pathAttrMap +} + +// create Path object based on route family +func CreatePath(source *Peer, nlri bgp.AddrPrefixInterface, + pathAttributes []bgp.PathAttributeInterface, isWithdraw bool) Path { + + rf := RouteFamily(int(nlri.AFI())<<16 | int(nlri.SAFI())) + logger.Debugf("afi: %d, safi: %d ", int(nlri.AFI()), nlri.SAFI()) + pathAttrMap := createPathAttributeMap(pathAttributes) + var path Path + + switch rf { + case RF_IPv4_UC: + logger.Debugf("RouteFamily : %s", RF_IPv4_UC.String()) + nexthop := getNextHop(pathAttributes) + path = NewIPv4Path(source, nlri, source.VersionNum, nexthop, isWithdraw, pathAttrMap, false) + case RF_IPv6_UC: + logger.Debugf("RouteFamily : %s", RF_IPv6_UC.String()) + var mpattr *bgp.PathAttributeMpReachNLRI + var nexthop net.IP + + if !isWithdraw { + mpattr = pathAttrMap.Get(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI).(*bgp.PathAttributeMpReachNLRI) + nexthop = mpattr.Nexthop + } else { + nexthop = nil + } + + path = NewIPv6Path(source, nlri, source.VersionNum, nexthop, isWithdraw, pathAttrMap, false) + } + return path +} + +/* +* Definition of inherited Path interface + */ +type IPv4Path struct { + *PathDefault +} + +func NewIPv4Path(source *Peer, nlri bgp.AddrPrefixInterface, sourceVerNum int, nexthop net.IP, + isWithdraw bool, pattr *utils.OrderedMap, medSetByTargetNeighbor bool) *IPv4Path { + ipv4Path := &IPv4Path{} + ipv4Path.PathDefault = NewPathDefault(source, nlri, sourceVerNum, nexthop, isWithdraw, pattr, medSetByTargetNeighbor) + ipv4Path.PathDefault.ROUTE_FAMILY = RF_IPv4_UC + return ipv4Path +} + +func (ipv4p *IPv4Path) setPathDefault(pd *PathDefault) { + ipv4p.PathDefault = pd +} +func (ipv4p *IPv4Path) getPathDefault() *PathDefault { + return ipv4p.PathDefault +} + +type IPv6Path struct { + *PathDefault +} + +func NewIPv6Path(source *Peer, nlri bgp.AddrPrefixInterface, sourceVerNum int, nexthop net.IP, + isWithdraw bool, pattr *utils.OrderedMap, medSetByTargetNeighbor bool) *IPv6Path { + ipv6Path := &IPv6Path{} + ipv6Path.PathDefault = NewPathDefault(source, nlri, sourceVerNum, nexthop, isWithdraw, pattr, medSetByTargetNeighbor) + ipv6Path.PathDefault.ROUTE_FAMILY = RF_IPv6_UC + return ipv6Path +} + +func (ipv6p *IPv6Path) setPathDefault(pd *PathDefault) { + ipv6p.PathDefault = pd +} + +func (ipv6p *IPv6Path) getPathDefault() *PathDefault { + return ipv6p.PathDefault +} + +func (ipv6p *IPv6Path) getPrefix() net.IP { + addrPrefix := ipv6p.nlri.(*bgp.IPv6AddrPrefix) + return addrPrefix.Prefix +} + +// return IPv6Path's string representation +func (ipv6p *IPv6Path) String() string { + str := fmt.Sprintf("IPv6Path Source: %d, ", ipv6p.getSourceVerNum()) + str = str + fmt.Sprintf(" NLRI: %s, ", ipv6p.getPrefix().String()) + str = str + fmt.Sprintf(" nexthop: %s, ", ipv6p.getNexthop().String()) + str = str + fmt.Sprintf(" withdraw: %s, ", ipv6p.isWithdraw()) + str = str + fmt.Sprintf(" path attributes: %s, ", ipv6p.getPathAttributeMap()) + return str +} |