diff options
-rw-r--r-- | table/destination.go | 56 | ||||
-rw-r--r-- | table/path.go | 68 | ||||
-rw-r--r-- | table/table.go | 66 | ||||
-rw-r--r-- | table/table_manager.go | 2 |
4 files changed, 192 insertions, 0 deletions
diff --git a/table/destination.go b/table/destination.go index 6734229a..edcda695 100644 --- a/table/destination.go +++ b/table/destination.go @@ -936,3 +936,59 @@ func (ipv6d *IPv6Destination) MarshalJSON() ([]byte, error) { BestPathIdx: idx, }) } + +type IPv4VPNDestination struct { + *DestinationDefault + //need structure +} + +func NewIPv4VPNDestination(nlri bgp.AddrPrefixInterface) *IPv4VPNDestination { + ipv4VPNDestination := &IPv4VPNDestination{} + ipv4VPNDestination.DestinationDefault = NewDestinationDefault(nlri) + ipv4VPNDestination.DestinationDefault.ROUTE_FAMILY = bgp.RF_IPv4_VPN + //need Processing + return ipv4VPNDestination +} + +func (ipv4vpnd *IPv4VPNDestination) String() string { + + str := fmt.Sprintf("Destination NLRI: %s", ipv4vpnd.getPrefix().String()) + return str +} + +func (ipv4vpnd *IPv4VPNDestination) getPrefix() net.IP { + var ip net.IP + log.Debugf("type %s", reflect.TypeOf(ipv4vpnd.nlri)) + switch p := ipv4vpnd.nlri.(type) { + case *bgp.IPv6AddrPrefix: + ip = p.IPAddrPrefix.IPAddrPrefixDefault.Prefix + case *bgp.WithdrawnRoute: + ip = p.IPAddrPrefix.IPAddrPrefixDefault.Prefix + } + return ip +} + +func (ipv4vpnd *IPv4VPNDestination) MarshalJSON() ([]byte, error) { + prefix := ipv4vpnd.getNlri().(*bgp.LabelledVPNIPAddrPrefix).Prefix + idx := func() int { + for i, p := range ipv4vpnd.DestinationDefault.knownPathList { + if p == ipv4vpnd.DestinationDefault.getBestPath() { + return i + } + } + log.WithFields(log.Fields{ + "Topic": "Table", + "Key": prefix.String(), + }).Panic("no best path") + return 0 + }() + return json.Marshal(struct { + Prefix string + Paths []Path + BestPathIdx int + }{ + Prefix: prefix.String(), + Paths: ipv4vpnd.knownPathList, + BestPathIdx: idx, + }) +} diff --git a/table/path.go b/table/path.go index 10374aa7..832a0ec6 100644 --- a/table/path.go +++ b/table/path.go @@ -224,6 +224,9 @@ func CreatePath(source *PeerInfo, nlri bgp.AddrPrefixInterface, attrs []bgp.Path case bgp.RF_IPv6_UC: log.Debugf("CreatePath RouteFamily : %s", bgp.RF_IPv6_UC.String()) path = NewIPv6Path(source, nlri, isWithdraw, attrs, false, now) + case bgp.RF_IPv4_VPN: + log.Debugf("CreatePath RouteFamily : %s", bgp.RF_IPv4_VPN.String()) + path = NewIPv4VPNPath(source, nlri, isWithdraw, attrs, false, now) } return path } @@ -316,3 +319,68 @@ func (ipv6p *IPv6Path) MarshalJSON() ([]byte, error) { Age: time.Now().Sub(ipv6p.PathDefault.timestamp).Seconds(), }) } + +type IPv4VPNPath struct { + *PathDefault +} + +func NewIPv4VPNPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, medSetByTargetNeighbor bool, now time.Time) *IPv4VPNPath { + ipv4VPNPath := &IPv4VPNPath{} + ipv4VPNPath.PathDefault = NewPathDefault(bgp.RF_IPv4_VPN, source, nlri, nil, isWithdraw, attrs, medSetByTargetNeighbor, now) + if !isWithdraw { + _, mpattr := ipv4VPNPath.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) + ipv4VPNPath.nexthop = mpattr.(*bgp.PathAttributeMpReachNLRI).Nexthop + } + return ipv4VPNPath +} + +func (ipv4vpnp *IPv4VPNPath) clone(isWithdraw bool) Path { + nlri := ipv4vpnp.nlri + if isWithdraw { + if ipv4vpnp.IsWithdraw() { + log.WithFields(log.Fields{ + "Topic": "Table", + "Key": ipv4vpnp.getNlri().String(), + "Peer": ipv4vpnp.getSource().Address.String(), + }).Fatal("Withdraw path is not supposed to be cloned") + } + } + return CreatePath(ipv4vpnp.source, nlri, ipv4vpnp.pathAttrs, isWithdraw, ipv4vpnp.PathDefault.timestamp) +} + +func (ipv4vpnp *IPv4VPNPath) setPathDefault(pd *PathDefault) { + ipv4vpnp.PathDefault = pd +} + +func (ipv4vpnp *IPv4VPNPath) getPathDefault() *PathDefault { + return ipv4vpnp.PathDefault +} + +func (ipv4vpnp *IPv4VPNPath) getPrefix() string { + addrPrefix := ipv4vpnp.nlri.(*bgp.LabelledVPNIPAddrPrefix) + return addrPrefix.IPAddrPrefixDefault.String() +} + +// return IPv4VPNPath's string representation +func (ipv4vpnp *IPv4VPNPath) String() string { + str := fmt.Sprintf("IPv4VPNPath Source: %v, ", ipv4vpnp.getSource()) + str = str + fmt.Sprintf(" NLRI: %s, ", ipv4vpnp.getPrefix()) + str = str + fmt.Sprintf(" nexthop: %s, ", ipv4vpnp.getNexthop().String()) + str = str + fmt.Sprintf(" withdraw: %s, ", ipv4vpnp.IsWithdraw()) + //str = str + fmt.Sprintf(" path attributes: %s, ", ipv4vpnp.getPathAttributeMap()) + return str +} + +func (ipv4vpnp *IPv4VPNPath) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Network string + Nexthop string + Attrs []bgp.PathAttributeInterface + Age float64 + }{ + Network: ipv4vpnp.getPrefix(), + Nexthop: ipv4vpnp.PathDefault.nexthop.String(), + Attrs: ipv4vpnp.PathDefault.getPathAttrs(), + Age: time.Now().Sub(ipv4vpnp.PathDefault.timestamp).Seconds(), + }) +} diff --git a/table/table.go b/table/table.go index 2bc328d8..c5ce287a 100644 --- a/table/table.go +++ b/table/table.go @@ -24,6 +24,8 @@ import ( "github.com/tchap/go-patricia/patricia" "net" "reflect" + "strconv" + "strings" ) type Table interface { @@ -315,3 +317,67 @@ func (ipv6t *IPv6Table) tableKey(nlri bgp.AddrPrefixInterface) string { return addrPrefix.IPAddrPrefixDefault.String() } + +type IPv4VPNTable struct { + *TableDefault + //need structure +} + +func NewIPv4VPNTable(scope_id int) *IPv4VPNTable { + ipv4VPNTable := &IPv4VPNTable{} + ipv4VPNTable.TableDefault = NewTableDefault(scope_id) + ipv4VPNTable.TableDefault.ROUTE_FAMILY = bgp.RF_IPv4_VPN + //need Processing + return ipv4VPNTable +} + +//Creates destination +//Implements interface +func (ipv4vpnt *IPv4VPNTable) createDest(nlri bgp.AddrPrefixInterface) Destination { + return Destination(NewIPv4VPNDestination(nlri)) +} + +//make tablekey +//Implements interface +func (ipv4vpnt *IPv4VPNTable) tableKey(nlri bgp.AddrPrefixInterface) string { + + addrPrefix := nlri.(*bgp.LabelledVPNIPAddrPrefix) + return addrPrefix.IPAddrPrefixDefault.String() + +} + +func ParseLabbelledVpnPrefix(key string) patricia.Prefix { + vpnaddrprefix := strings.Split(key, "/") + length, _ := strconv.ParseInt(vpnaddrprefix[1], 10, 0) + _, n, _ := net.ParseCIDR(vpnaddrprefix[0] + "/" + strconv.FormatInt((int64(length)-88), 10)) + + var buffer bytes.Buffer + for i := 0; i < len(n.IP); i++ { + buffer.WriteString(fmt.Sprintf("%08b", n.IP[i])) + } + ones, _ := n.Mask.Size() + return patricia.Prefix(buffer.String()[:ones]) + +} + +func (ipv4vpnt *IPv4VPNTable) MarshalJSON() ([]byte, error) { + + trie := patricia.NewTrie() + for key, dest := range ipv4vpnt.destinations { + trie.Insert(ParseLabbelledVpnPrefix(key), dest) + } + + destList := make([]Destination, 0) + trie.Visit(func(prefix patricia.Prefix, item patricia.Item) error { + dest, _ := item.(Destination) + destList = append(destList, dest) + return nil + }) + + return json.Marshal(struct { + Destinations []Destination + }{ + Destinations: destList, + }) + +} diff --git a/table/table_manager.go b/table/table_manager.go index d0dd9f86..f2ff1ee6 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -138,6 +138,8 @@ func NewTableManager(owner string, rfList []bgp.RouteFamily) *TableManager { t.Tables[bgp.RF_IPv4_UC] = NewIPv4Table(0) case bgp.RF_IPv6_UC: t.Tables[bgp.RF_IPv6_UC] = NewIPv6Table(0) + case bgp.RF_IPv4_VPN: + t.Tables[bgp.RF_IPv4_VPN] = NewIPv4VPNTable(0) } } t.owner = owner |