diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/peer.go | 181 | ||||
-rw-r--r-- | server/server.go | 51 |
2 files changed, 209 insertions, 23 deletions
diff --git a/server/peer.go b/server/peer.go index d76dd088..33ec9103 100644 --- a/server/peer.go +++ b/server/peer.go @@ -21,6 +21,7 @@ import ( "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet" + "github.com/osrg/gobgp/policy" "github.com/osrg/gobgp/table" "gopkg.in/tomb.v2" "net" @@ -57,16 +58,20 @@ type Peer struct { adjRib *table.AdjRib // peer and rib are always not one-to-one so should not be // here but it's the simplest and works our first target. - rib *table.TableManager - isGlobalRib bool - rfMap map[bgp.RouteFamily]bool - capMap map[bgp.BGPCapabilityCode]bgp.ParameterCapabilityInterface - peerInfo *table.PeerInfo - siblings map[string]*serverMsgDataPeer - outgoing chan *bgp.BGPMessage + rib *table.TableManager + isGlobalRib bool + rfMap map[bgp.RouteFamily]bool + capMap map[bgp.BGPCapabilityCode]bgp.ParameterCapabilityInterface + peerInfo *table.PeerInfo + siblings map[string]*serverMsgDataPeer + outgoing chan *bgp.BGPMessage + importPolicies []*policy.Policy + defaultImportPolicy config.DefaultPolicyType + exportPolicies []*policy.Policy + defaultExportPolicy config.DefaultPolicyType } -func NewPeer(g config.Global, peer config.Neighbor, serverMsgCh chan *serverMsg, peerMsgCh chan *peerMsg, peerList []*serverMsgDataPeer, isGlobalRib bool) *Peer { +func NewPeer(g config.Global, peer config.Neighbor, serverMsgCh chan *serverMsg, peerMsgCh chan *peerMsg, peerList []*serverMsgDataPeer, isGlobalRib bool, policyMap map[string]*policy.Policy) *Peer { p := &Peer{ globalConfig: g, peerConfig: peer, @@ -96,10 +101,40 @@ func NewPeer(g config.Global, peer config.Neighbor, serverMsgCh chan *serverMsg, rfList := p.configuredRFlist() p.adjRib = table.NewAdjRib(rfList) p.rib = table.NewTableManager(p.peerConfig.NeighborAddress.String(), rfList) + p.setPolicy(policyMap) p.t.Go(p.loop) return p } +func (peer *Peer) setPolicy(policyMap map[string]*policy.Policy) { + // configure import policy + policyConfig := peer.peerConfig.ApplyPolicy + inPolicies := make([]*policy.Policy, 0) + for _, policyName := range policyConfig.ImportPolicies { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.peerConfig.NeighborAddress, + "PolicyName": policyName, + }).Info("import policy installed") + log.Debug("import policy : ", policyMap[policyName]) + inPolicies = append(inPolicies, policyMap[policyName]) + } + peer.importPolicies = inPolicies + + // configure export policy + outPolicies := make([]*policy.Policy, 0) + for _, policyName := range policyConfig.ExportPolicies { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.peerConfig.NeighborAddress, + "PolicyName": policyName, + }).Info("export policy installed") + log.Debug("export policy : ", policyMap[policyName]) + outPolicies = append(outPolicies, policyMap[policyName]) + } + peer.exportPolicies = outPolicies +} + func (peer *Peer) configuredRFlist() []bgp.RouteFamily { rfList := []bgp.RouteFamily{} for _, rf := range peer.peerConfig.AfiSafiList { @@ -317,9 +352,44 @@ func (peer *Peer) handleREST(restReq *api.RestRequest) { func (peer *Peer) sendUpdateMsgFromPaths(pList []table.Path) { pList = table.CloneAndUpdatePathAttrs(pList, &peer.globalConfig, &peer.peerConfig) - peer.adjRib.UpdateOut(pList) - sendpathList := []table.Path{} + paths := []table.Path{} + policies := peer.exportPolicies + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.peerConfig.NeighborAddress, + }).Debug("Export Policies :", policies) for _, p := range pList { + if p.IsWithdraw() { + paths = append(paths, p) + continue + } + log.Debug("p: ", p) + if len(policies) != 0 { + applied, newPath := applyPolicies(policies, &p) + + if applied { + if newPath != nil { + log.Debug("path accepted") + paths = append(paths, *newPath) + } else { + log.Debug("path was rejected: ", p) + } + + } else { + if peer.defaultExportPolicy == config.DEFAULT_POLICY_TYPE_ACCEPT_ROUTE { + paths = append(paths, p) + log.Debug("path is emitted by default export policy: ", p) + } + } + } else { + paths = append(paths, p) + } + + } + + peer.adjRib.UpdateOut(paths) + sendpathList := []table.Path{} + for _, p := range paths { _, ok := peer.rfMap[p.GetRouteFamily()] if peer.peerConfig.NeighborAddress.Equal(p.GetNexthop()) { @@ -337,18 +407,99 @@ func (peer *Peer) sendUpdateMsgFromPaths(pList []table.Path) { peer.sendMessages(table.CreateUpdateMsgFromPaths(sendpathList)) } +// apply policies to the path +// if multiple policies are defined, +// this function applies each policy to the path in the order that +// policies are stored in the array passed to this function. +// +// the way of applying statements inside a single policy +// - apply statement until the condition in the statement matches. +// if the condition matches the path, apply the action on the statement and +// return value that indicates 'applied' to caller of this function +// - if no statement applied, then process the next policy +// +// if no policy applied, return value that indicates 'not applied' to the caller of this function +// +// return values: +// bool -- indicates that any of policy applied to the path that is passed to this function +// table.Path -- indicates new path object that is the result of modification according to +// policy's action. +// If the applied policy doesn't have a modification action, +// then return the path itself that is passed to this function, otherwise return +// modified path. +// If action of the policy is 'reject', return nil +// +func applyPolicies(policies []*policy.Policy, original *table.Path) (bool, *table.Path) { + + var applied bool = true + + for _, pol := range policies { + if result, action, newpath := pol.Apply(*original); result { + log.Debug("newpath: ", newpath) + if action == policy.ROUTE_TYPE_REJECT { + log.Debug("path was rejected: ", original) + // return applied, nil, this means path was rejected + return applied, nil + } else { + // return applied, new path + return applied, &newpath + } + } + } + log.Debug("no policy applied.", original) + // return not applied, original path + return !applied, original +} + func (peer *Peer) handlePeerMsg(m *peerMsg) { switch m.msgType { case PEER_MSG_PATH: pList := m.msgData.([]table.Path) + paths := []table.Path{} + + policies := peer.importPolicies + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.peerConfig.NeighborAddress, + }).Debug("Import Policies :", policies) + + for _, p := range pList { + log.Debug("p: ", p) + if !p.IsWithdraw() { + log.Debug("is not withdraw") + + if len(policies) != 0 { + applied, newPath := applyPolicies(policies, &p) + + if applied { + if newPath != nil { + log.Debug("path accepted") + paths = append(paths, *newPath) + } + } else { + if peer.defaultImportPolicy == config.DEFAULT_POLICY_TYPE_ACCEPT_ROUTE { + paths = append(paths, p) + log.Debug("path accepted by default import policy: ", p) + } + } + } else { + paths = append(paths, p) + } + } else { + log.Debug("is withdraw") + paths = append(paths, p) + } + } + log.Debug("length of paths: ", len(paths)) + if peer.peerConfig.RouteServer.RouteServerClient || peer.isGlobalRib { - pList, _ = peer.rib.ProcessPaths(pList) + paths, _ = peer.rib.ProcessPaths(paths) } if peer.isGlobalRib { - peer.sendPathsToSiblings(pList) + peer.sendPathsToSiblings(paths) } else { - peer.sendUpdateMsgFromPaths(pList) + peer.sendUpdateMsgFromPaths(paths) } case PEER_MSG_PEER_DOWN: @@ -392,6 +543,10 @@ func (peer *Peer) handleServerMsg(m *serverMsg) { } case SRV_MSG_API: peer.handleREST(m.msgData.(*api.RestRequest)) + case SRV_MSG_POLICY_UPDATED: + log.Debug("policy updated") + d := m.msgData.(map[string]*policy.Policy) + peer.setPolicy(d) default: log.Fatal("unknown server msg type ", m.msgType) } diff --git a/server/server.go b/server/server.go index 27570d5a..22fb48c3 100644 --- a/server/server.go +++ b/server/server.go @@ -21,6 +21,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" + "github.com/osrg/gobgp/policy" "net" "os" "strconv" @@ -34,6 +35,7 @@ const ( SRV_MSG_PEER_ADDED SRV_MSG_PEER_DELETED SRV_MSG_API + SRV_MSG_POLICY_UPDATED ) type serverMsg struct { @@ -55,14 +57,16 @@ type peerMapInfo struct { } type BgpServer struct { - bgpConfig config.Bgp - globalTypeCh chan config.Global - addedPeerCh chan config.Neighbor - deletedPeerCh chan config.Neighbor - RestReqCh chan *api.RestRequest - listenPort int - peerMap map[string]peerMapInfo - globalRib *Peer + bgpConfig config.Bgp + globalTypeCh chan config.Global + addedPeerCh chan config.Neighbor + deletedPeerCh chan config.Neighbor + RestReqCh chan *api.RestRequest + listenPort int + peerMap map[string]peerMapInfo + globalRib *Peer + policyUpdateCh chan config.RoutingPolicy + policyMap map[string]*policy.Policy } func NewBgpServer(port int) *BgpServer { @@ -71,6 +75,7 @@ func NewBgpServer(port int) *BgpServer { b.addedPeerCh = make(chan config.Neighbor) b.deletedPeerCh = make(chan config.Neighbor) b.RestReqCh = make(chan *api.RestRequest, 1) + b.policyUpdateCh = make(chan config.RoutingPolicy) b.listenPort = port return &b } @@ -112,7 +117,7 @@ func (server *BgpServer) Serve() { NeighborAddress: g.RouterId, AfiSafiList: g.AfiSafiList, } - server.globalRib = NewPeer(g, neighConf, globalSch, globalPch, nil, true) + server.globalRib = NewPeer(g, neighConf, globalSch, globalPch, nil, true, make(map[string]*policy.Policy)) listenerMap := make(map[string]*net.TCPListener) acceptCh := make(chan *net.TCPConn) @@ -175,7 +180,7 @@ func (server *BgpServer) Serve() { } l = []*serverMsgDataPeer{globalRib} } - p := NewPeer(server.bgpConfig.Global, peer, sch, pch, l, false) + p := NewPeer(server.bgpConfig.Global, peer, sch, pch, l, false, server.policyMap) d := &serverMsgDataPeer{ address: peer.NeighborAddress, peerMsgCh: pch, @@ -219,10 +224,23 @@ func (server *BgpServer) Serve() { } case restReq := <-server.RestReqCh: server.handleRest(restReq) + case pl := <-server.policyUpdateCh: + server.SetPolicy(pl) + msg := &serverMsg{ + msgType: SRV_MSG_POLICY_UPDATED, + msgData: server.policyMap, + } + sendServerMsgToAll(server.peerMap, msg) } } } +func sendServerMsgToAll(peerMap map[string]peerMapInfo, msg *serverMsg) { + for _, info := range peerMap { + info.serverMsgCh <- msg + } +} + func sendServerMsgToRSClients(peerMap map[string]peerMapInfo, msg *serverMsg) { for _, info := range peerMap { if info.isRouteServerClient { @@ -243,6 +261,19 @@ func (server *BgpServer) PeerDelete(peer config.Neighbor) { server.deletedPeerCh <- peer } +func (server *BgpServer) UpdatePolicy(policy config.RoutingPolicy) { + server.policyUpdateCh <- policy +} + +func (server *BgpServer) SetPolicy(pl config.RoutingPolicy) { + pMap := make(map[string]*policy.Policy) + df := pl.DefinedSets + for _, p := range pl.PolicyDefinitionList { + pMap[p.Name] = policy.NewPolicy(p.Name, p, df) + } + server.policyMap = pMap +} + func (server *BgpServer) handleRest(restReq *api.RestRequest) { switch restReq.RequestType { case api.REQ_NEIGHBORS: |