diff options
Diffstat (limited to 'policy/policy.go')
-rw-r--r-- | policy/policy.go | 131 |
1 files changed, 129 insertions, 2 deletions
diff --git a/policy/policy.go b/policy/policy.go index 236ffa6d..b701bd4a 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -23,6 +23,7 @@ import ( "github.com/osrg/gobgp/packet" "github.com/osrg/gobgp/table" "net" + "regexp" "reflect" "strconv" "strings" @@ -59,11 +60,11 @@ type Policy struct { Statements []*Statement } -func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) *Policy { +func NewPolicy(pd config.PolicyDefinition, ds config.DefinedSets) *Policy { stmtList := pd.StatementList st := make([]*Statement, 0) p := &Policy{ - Name: name, + Name: pd.Name, } for _, statement := range stmtList { @@ -87,6 +88,13 @@ func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) * conditions = append(conditions, ac) } + // AsPathCondition + asPathSetName := statement.Conditions.BgpConditions.MatchAsPathSet + asc := NewAsPathCondition(asPathSetName, ds.BgpDefinedSets.AsPathSetList) + if asc != nil { + conditions = append(conditions, asc) + } + action := &RoutingActions{ AcceptRoute: false, } @@ -265,6 +273,7 @@ func (c *NeighborCondition) evaluate(path table.Path) bool { cAddr := neighbor pAddr := path.GetSource().Address if pAddr.Equal(cAddr) { + log.Debug("neighbor matched : ", pAddr.String()) return true } } @@ -325,6 +334,124 @@ func (c *AsPathLengthCondition) evaluate(path table.Path) bool { } +type AsPathCondition struct { + DefaultCondition + AsPathList []*AsPathElement +} + +type AsnPos int + +const ( + AS_FROM AsnPos = iota + AS_ANY + AS_ORIGIN + AS_ONLY +) + +type AsPathElement struct { + postiion AsnPos + asn uint32 +} + +// create AsPathCondition object +// AsPathCondition supports only following regexp: +// - ^100 (from as100) +// - ^100$ (from as100 and originated by as100) +// - 100$ (originated by as100) +// - 100 (from or through or originated by as100) +func NewAsPathCondition(asPathSetName string, defAsPathSetList []config.AsPathSet) *AsPathCondition { + + regAsn, _ := regexp.Compile("^(\\^?)([0-9]+)(\\$?)$") + + asPathList := make([]*AsPathElement, 0) + for _, asPathSet := range defAsPathSetList { + if asPathSet.AsPathSetName == asPathSetName { + for _, as := range asPathSet.AsPathSetMembers { + if regAsn.MatchString(as) { + + group := regAsn.FindStringSubmatch(as) + asn, err := strconv.Atoi(group[2]) + if err != nil { + log.WithFields(log.Fields{ + "Topic": "Policy", + "Type": "AsPath Condition", + }).Error("cannot parse AS Number.") + return nil + } + e := &AsPathElement{} + e.asn = uint32(asn) + + if len(group[1]) == 0 && len(group[3]) == 0 { + e.postiion = AS_ANY + } else if len(group[1]) == 1 && len(group[3]) == 0 { + e.postiion = AS_FROM + } else if len(group[1]) == 0 && len(group[3]) == 1 { + e.postiion = AS_ORIGIN + } else { + e.postiion = AS_ONLY + } + + asPathList = append(asPathList, e) + + } else { + log.WithFields(log.Fields{ + "Topic": "Policy", + "Type": "AsPath Condition", + }).Error("cannot parse AS_PATH condition value.") + + return nil + } + } + + c := &AsPathCondition{ + AsPathList: asPathList, + } + return c + } + } + return nil +} + +// compare AS_PATH in the message's AS_PATH attribute with +// the one in condition. +func (c *AsPathCondition) evaluate(path table.Path) bool { + + aspath := path.GetAsSeqList() + + if len(aspath) == 0 { + return false + } + + matched := false + for _, member := range c.AsPathList { + + switch member.postiion { + case AS_FROM: + matched = aspath[0] == member.asn + case AS_ANY: + for _, n := range aspath { + if n == member.asn { + matched = true + break + } + } + case AS_ORIGIN: + matched = aspath[len(aspath)-1] == member.asn + + case AS_ONLY: + matched = len(aspath) == 1 && aspath[0] == member.asn + + } + + if matched { + log.Debugf("aspath matched : asn=%d, pos=%v)", member.asn, member.postiion) + return true + } + + } + return false +} + type Actions interface { apply(table.Path) table.Path } |