summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/peer.go2
-rw-r--r--server/server.go102
-rw-r--r--table/table_manager.go61
3 files changed, 162 insertions, 3 deletions
diff --git a/server/peer.go b/server/peer.go
index 39859c3c..4bda6c9d 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -195,7 +195,7 @@ func (peer *Peer) handleBGPmessage(m *bgp.BGPMessage) ([]*table.Path, bool, []*b
func (peer *Peer) getBests(loc *LocalRib) []*table.Path {
pathList := []*table.Path{}
for _, rf := range peer.configuredRFlist() {
- for _, paths := range loc.rib.GetPathList(rf) {
+ for _, paths := range loc.rib.GetBestPathList(rf) {
pathList = append(pathList, paths)
}
}
diff --git a/server/server.go b/server/server.go
index 984762e6..78a15da9 100644
--- a/server/server.go
+++ b/server/server.go
@@ -16,6 +16,7 @@
package server
import (
+ "bytes"
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/api"
@@ -584,6 +585,9 @@ func (server *BgpServer) propagateUpdate(neighborAddress string, RouteServerClie
continue
}
f := filterpath(targetPeer, sendPathList)
+ if len(f) == 0 {
+ continue
+ }
for _, path := range f {
path.UpdatePathAttrs(&server.bgpConfig.Global, &targetPeer.conf)
}
@@ -735,12 +739,84 @@ func (server *BgpServer) checkNeighborRequest(grpcReq *GrpcRequest) (*Peer, erro
return peer, nil
}
-func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*table.Path {
+// EVPN MAC MOBILITY HANDLING
+//
+// We don't have multihoming function now, so ignore
+// ESI comparison.
+//
+// RFC7432 15. MAC Mobility
+//
+// A PE detecting a locally attached MAC address for which it had
+// previously received a MAC/IP Advertisement route with the same zero
+// Ethernet segment identifier (single-homed scenarios) advertises it
+// with a MAC Mobility extended community attribute with the sequence
+// number set properly. In the case of single-homed scenarios, there
+// is no need for ESI comparison.
+
+func getMacMobilityExtendedCommunity(etag uint32, mac net.HardwareAddr, evpnPaths []*table.Path) *bgp.MacMobilityExtended {
+ seqs := make([]struct {
+ seq int
+ isLocal bool
+ }, 0)
+
+ for _, path := range evpnPaths {
+ nlri := path.GetNlri().(*bgp.EVPNNLRI)
+ target, ok := nlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
+ if !ok {
+ continue
+ }
+ if target.ETag == etag && bytes.Equal(target.MacAddress, mac) {
+ found := false
+ for _, ec := range path.GetExtCommunities() {
+ if t, st := ec.GetTypes(); t == bgp.EC_TYPE_EVPN && st == bgp.EC_SUBTYPE_MAC_MOBILITY {
+ seqs = append(seqs, struct {
+ seq int
+ isLocal bool
+ }{int(ec.(*bgp.MacMobilityExtended).Sequence), path.IsLocal()})
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ seqs = append(seqs, struct {
+ seq int
+ isLocal bool
+ }{-1, path.IsLocal()})
+ }
+ }
+ }
+
+ if len(seqs) > 0 {
+ newSeq := -2
+ var isLocal bool
+ for _, seq := range seqs {
+ if seq.seq > newSeq {
+ newSeq = seq.seq
+ isLocal = seq.isLocal
+ }
+ }
+
+ if !isLocal {
+ newSeq += 1
+ }
+
+ if newSeq != -1 {
+ return &bgp.MacMobilityExtended{
+ Sequence: uint32(newSeq),
+ }
+ }
+ }
+ return nil
+}
+
+func (server *BgpServer) handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*table.Path {
var isWithdraw bool
var nlri bgp.AddrPrefixInterface
result := &GrpcResponse{}
pattr := make([]bgp.PathAttributeInterface, 0)
+ extcomms := make([]bgp.ExtendedCommunityInterface, 0)
args, ok := grpcReq.Data.(*api.ModPathArguments)
if !ok {
@@ -774,6 +850,11 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
}
switch p.GetType() {
+ case bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES:
+ value := p.(*bgp.PathAttributeExtendedCommunities).Value
+ if len(value) > 0 {
+ extcomms = append(extcomms, value...)
+ }
case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
value := p.(*bgp.PathAttributeMpReachNLRI).Value
if len(value) != 1 {
@@ -792,6 +873,23 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
goto ERR
}
+ if bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()) == bgp.RF_EVPN {
+ evpnNlri := nlri.(*bgp.EVPNNLRI)
+ if evpnNlri.RouteType == bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
+ macIpAdv := evpnNlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
+ etag := macIpAdv.ETag
+ mac := macIpAdv.MacAddress
+ paths := server.localRibMap[GLOBAL_RIB_NAME].rib.GetBestPathList(bgp.RF_EVPN)
+ if m := getMacMobilityExtendedCommunity(etag, mac, paths); m != nil {
+ extcomms = append(extcomms, m)
+ }
+ }
+ }
+
+ if len(extcomms) > 0 {
+ pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities(extcomms))
+ }
+
return []*table.Path{table.NewPath(peerInfo, nlri, isWithdraw, pattr, false, time.Now(), args.NoImplicitWithdraw)}
ERR:
grpcReq.ResponseCh <- result
@@ -819,7 +917,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
AS: server.bgpConfig.Global.GlobalConfig.As,
LocalID: server.bgpConfig.Global.GlobalConfig.RouterId,
}
- pathList := handleGlobalRibRequest(grpcReq, pi)
+ pathList := server.handleGlobalRibRequest(grpcReq, pi)
if len(pathList) > 0 {
msgs = append(msgs, server.propagateUpdate("", false, pathList)...)
grpcReq.ResponseCh <- &GrpcResponse{}
diff --git a/table/table_manager.go b/table/table_manager.go
index 4b164228..2b34f2c6 100644
--- a/table/table_manager.go
+++ b/table/table_manager.go
@@ -16,8 +16,10 @@
package table
import (
+ "bytes"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/packet"
+ "net"
"reflect"
"time"
)
@@ -236,11 +238,58 @@ func (manager *TableManager) ProcessPaths(pathList []*Path) ([]*Path, error) {
rf := path.GetRouteFamily()
if t, ok := manager.Tables[rf]; ok {
destinationList = append(destinationList, t.insert(path))
+ if rf == bgp.RF_EVPN {
+ dsts := manager.handleMacMobility(path)
+ if len(dsts) > 0 {
+ destinationList = append(destinationList, dsts...)
+ }
+ }
}
}
return manager.calculate(destinationList)
}
+// EVPN MAC MOBILITY HANDLING
+//
+// RFC7432 15. MAC Mobility
+//
+// A PE receiving a MAC/IP Advertisement route for a MAC address with a
+// different Ethernet segment identifier and a higher sequence number
+// than that which it had previously advertised withdraws its MAC/IP
+// Advertisement route.
+func (manager *TableManager) handleMacMobility(path *Path) []*Destination {
+ dsts := make([]*Destination, 0)
+ nlri := path.GetNlri().(*bgp.EVPNNLRI)
+ if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
+ return nil
+ }
+ for _, path2 := range manager.GetPathList(bgp.RF_EVPN) {
+ if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
+ continue
+ }
+ f := func(p *Path) (uint32, net.HardwareAddr, int) {
+ nlri := p.GetNlri().(*bgp.EVPNNLRI)
+ d := nlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
+ ecs := p.GetExtCommunities()
+ seq := -1
+ for _, ec := range ecs {
+ if t, st := ec.GetTypes(); t == bgp.EC_TYPE_EVPN && st == bgp.EC_SUBTYPE_MAC_MOBILITY {
+ seq = int(ec.(*bgp.MacMobilityExtended).Sequence)
+ break
+ }
+ }
+ return d.ETag, d.MacAddress, seq
+ }
+ e1, m1, s1 := f(path)
+ e2, m2, s2 := f(path2)
+ if e1 == e2 && bytes.Equal(m1, m2) && s1 > s2 {
+ path2.IsWithdraw = true
+ dsts = append(dsts, manager.Tables[bgp.RF_EVPN].insert(path2))
+ }
+ }
+ return dsts
+}
+
func (manager *TableManager) GetPathList(rf bgp.RouteFamily) []*Path {
if _, ok := manager.Tables[rf]; !ok {
return []*Path{}
@@ -248,6 +297,18 @@ func (manager *TableManager) GetPathList(rf bgp.RouteFamily) []*Path {
destinations := manager.Tables[rf].GetDestinations()
paths := make([]*Path, 0, len(destinations))
for _, dest := range destinations {
+ paths = append(paths, dest.knownPathList...)
+ }
+ return paths
+}
+
+func (manager *TableManager) GetBestPathList(rf bgp.RouteFamily) []*Path {
+ if _, ok := manager.Tables[rf]; !ok {
+ return []*Path{}
+ }
+ destinations := manager.Tables[rf].GetDestinations()
+ paths := make([]*Path, 0, len(destinations))
+ for _, dest := range destinations {
paths = append(paths, dest.GetBestPath())
}
return paths