summaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/peer.go181
-rw-r--r--server/server.go51
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: