From 28feabe1ef3961e05e0e109551021f0bc8902abe Mon Sep 17 00:00:00 2001 From: Yuji Oshima Date: Sat, 21 Mar 2015 08:08:43 +0900 Subject: table: add EVPN route family support Signed-off-by: FUJITA Tomonori --- table/destination.go | 13 ++++++++++ table/message.go | 2 +- table/path.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ table/table.go | 40 +++++++++++++++++++++++++++++ table/table_manager.go | 3 +++ 5 files changed, 126 insertions(+), 1 deletion(-) diff --git a/table/destination.go b/table/destination.go index edcda695..f805d5e3 100644 --- a/table/destination.go +++ b/table/destination.go @@ -992,3 +992,16 @@ func (ipv4vpnd *IPv4VPNDestination) MarshalJSON() ([]byte, error) { BestPathIdx: idx, }) } + +type EVPNDestination struct { + *DestinationDefault + //need structure +} + +func NewEVPNDestination(nlri bgp.AddrPrefixInterface) *EVPNDestination { + EVPNDestination := &EVPNDestination{} + EVPNDestination.DestinationDefault = NewDestinationDefault(nlri) + EVPNDestination.DestinationDefault.ROUTE_FAMILY = bgp.RF_EVPN + //need Processing + return EVPNDestination +} diff --git a/table/message.go b/table/message.go index b19bcec2..10bf0afd 100644 --- a/table/message.go +++ b/table/message.go @@ -161,7 +161,7 @@ func createUpdateMsgFromPath(path Path, msg *bgp.BGPMessage) *bgp.BGPMessage { return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{*nlri}) } } - } else if rf == bgp.RF_IPv6_UC { + } else if rf == bgp.RF_IPv6_UC || rf == bgp.RF_EVPN { if path.IsWithdraw() { if msg != nil { idx, _ := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) diff --git a/table/path.go b/table/path.go index 5ff4ca2a..73475e98 100644 --- a/table/path.go +++ b/table/path.go @@ -318,6 +318,9 @@ func CreatePath(source *PeerInfo, nlri bgp.AddrPrefixInterface, attrs []bgp.Path case bgp.RF_IPv4_VPN: log.Debugf("CreatePath RouteFamily : %s", bgp.RF_IPv4_VPN.String()) path = NewIPv4VPNPath(source, nlri, isWithdraw, attrs, false, now) + case bgp.RF_EVPN: + log.Debugf("CreatePath RouteFamily : %s", bgp.RF_EVPN.String()) + path = NewEVPNPath(source, nlri, isWithdraw, attrs, false, now) } return path } @@ -466,3 +469,69 @@ func (ipv4vpnp *IPv4VPNPath) MarshalJSON() ([]byte, error) { Age: time.Now().Sub(ipv4vpnp.PathDefault.timestamp).Seconds(), }) } + +type EVPNPath struct { + *PathDefault +} + +func NewEVPNPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, medSetByTargetNeighbor bool, now time.Time) *EVPNPath { + EVPNPath := &EVPNPath{} + EVPNPath.PathDefault = NewPathDefault(bgp.RF_EVPN, source, nlri, nil, isWithdraw, attrs, medSetByTargetNeighbor, now) + if !isWithdraw { + _, mpattr := EVPNPath.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) + EVPNPath.nexthop = mpattr.(*bgp.PathAttributeMpReachNLRI).Nexthop + } + + return EVPNPath +} + +func (evpnp *EVPNPath) clone(isWithdraw bool) Path { + nlri := evpnp.nlri + if isWithdraw { + if evpnp.IsWithdraw() { + log.WithFields(log.Fields{ + "Topic": "Table", + "Key": evpnp.getNlri().String(), + "Peer": evpnp.getSource().Address.String(), + }).Fatal("Withdraw path is not supposed to be cloned") + } + } + return CreatePath(evpnp.source, nlri, evpnp.pathAttrs, isWithdraw, evpnp.PathDefault.timestamp) +} + +func (evpnp *EVPNPath) setPathDefault(pd *PathDefault) { + evpnp.PathDefault = pd +} + +func (evpnp *EVPNPath) getPathDefault() *PathDefault { + return evpnp.PathDefault +} + +func (evpnp *EVPNPath) getPrefix() string { + addrPrefix := evpnp.nlri.(*bgp.EVPNNLRI) + return addrPrefix.String() +} + +// return EVPNPath's string representation +func (evpnp *EVPNPath) String() string { + str := fmt.Sprintf("EVPNPath Source: %v, ", evpnp.getSource()) + str = str + fmt.Sprintf(" NLRI: %s, ", evpnp.getPrefix()) + str = str + fmt.Sprintf(" nexthop: %s, ", evpnp.GetNexthop().String()) + str = str + fmt.Sprintf(" withdraw: %s, ", evpnp.IsWithdraw()) + //str = str + fmt.Sprintf(" path attributes: %s, ", evpnp.getPathAttributeMap()) + return str +} + +func (evpnp *EVPNPath) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Network string + Nexthop string + Attrs []bgp.PathAttributeInterface + Age float64 + }{ + Network: evpnp.getPrefix(), + Nexthop: evpnp.PathDefault.nexthop.String(), + Attrs: evpnp.PathDefault.getPathAttrs(), + Age: time.Now().Sub(evpnp.PathDefault.timestamp).Seconds(), + }) +} diff --git a/table/table.go b/table/table.go index c5ce287a..47e42fbb 100644 --- a/table/table.go +++ b/table/table.go @@ -381,3 +381,43 @@ func (ipv4vpnt *IPv4VPNTable) MarshalJSON() ([]byte, error) { }) } + +type EVPNTable struct { + *TableDefault + //need structure +} + +func NewEVPNTable(scope_id int) *EVPNTable { + EVPNTable := &EVPNTable{} + EVPNTable.TableDefault = NewTableDefault(scope_id) + EVPNTable.TableDefault.ROUTE_FAMILY = bgp.RF_EVPN + //need Processing + return EVPNTable +} + +//Creates destination +//Implements interface +func (ipv4vpnt *EVPNTable) createDest(nlri bgp.AddrPrefixInterface) Destination { + return Destination(NewEVPNDestination(nlri)) +} + +//make tablekey +//Implements interface +func (ipv4vpnt *EVPNTable) tableKey(nlri bgp.AddrPrefixInterface) string { + + addrPrefix := nlri.(*bgp.EVPNNLRI) + return addrPrefix.String() +} + +func ParseEVPNPrefix(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]) +} diff --git a/table/table_manager.go b/table/table_manager.go index 23c233b1..7722ce19 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -140,6 +140,9 @@ func NewTableManager(owner string, rfList []bgp.RouteFamily) *TableManager { t.Tables[bgp.RF_IPv6_UC] = NewIPv6Table(0) case bgp.RF_IPv4_VPN: t.Tables[bgp.RF_IPv4_VPN] = NewIPv4VPNTable(0) + case bgp.RF_EVPN: + t.Tables[bgp.RF_EVPN] = NewEVPNTable(0) + } } t.owner = owner -- cgit v1.2.3