summaryrefslogtreecommitdiffhomepage
path: root/policy/policy.go
diff options
context:
space:
mode:
Diffstat (limited to 'policy/policy.go')
-rw-r--r--policy/policy.go138
1 files changed, 94 insertions, 44 deletions
diff --git a/policy/policy.go b/policy/policy.go
index 0ea3d373..70d1bbc3 100644
--- a/policy/policy.go
+++ b/policy/policy.go
@@ -397,8 +397,9 @@ const (
)
type AsPathElement struct {
- postiion AsnPos
- asn uint32
+ postiion AsnPos
+ asStr string
+ asRegExps []*regexp.Regexp
}
// create AsPathCondition object
@@ -412,48 +413,69 @@ func NewAsPathCondition(matchSet config.MatchAsPathSet, defAsPathSetList []confi
asPathSetName := matchSet.AsPathSet
options := matchSet.MatchSetOptions
- regAsn, _ := regexp.Compile("^(\\^?)([0-9]+)(\\$?)$")
asPathList := make([]*AsPathElement, 0)
for _, asPathSet := range defAsPathSetList {
if asPathSet.AsPathSetName == asPathSetName {
for _, aspath := range asPathSet.AsPathList {
a := aspath.AsPath
- if regAsn.MatchString(a) {
-
- group := regAsn.FindStringSubmatch(a)
- 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
+ if len(a) != 0 {
+ isTop := a[:1] == "^"
+ if isTop {
+ a = a[1:]
+ }
+ isEnd := a[len(a)-1:] == "$"
+ if isEnd {
+ a = a[:len(a)-1]
+ }
+ elems := strings.Split(a, "_")
+ asRegExps := make([]*regexp.Regexp, 0)
+ for _, el := range elems {
+ if len(el) == 0 {
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Type": "AsPath Condition",
+ "Value": aspath.AsPath,
+ "Elem": el,
+ }).Error("invalid element. do not enter a blank.")
+ return nil
+ }
+ regElem, err := regexp.Compile(el)
+ if err != nil {
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Type": "AsPath Condition",
+ "Value": aspath.AsPath,
+ "Elem": el,
+ "Error": err,
+ }).Error("can not comple AS_PATH values to Regular expressions.")
+ return nil
+ }
+ asRegExps = append(asRegExps, regElem)
}
- 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 := &AsPathElement{}
+ e.asRegExps = asRegExps
+ e.asStr = a
+ if isTop && isEnd {
+ e.postiion = AS_ONLY
+ } else if isTop && !isEnd {
e.postiion = AS_FROM
- } else if len(group[1]) == 0 && len(group[3]) == 1 {
+ } else if !isTop && isEnd {
e.postiion = AS_ORIGIN
} else {
- e.postiion = AS_ONLY
+ e.postiion = AS_ANY
}
-
asPathList = append(asPathList, e)
} else {
log.WithFields(log.Fields{
"Topic": "Policy",
"Type": "AsPath Condition",
- }).Error("cannot parse AS_PATH condition value.")
+ }).Error("does not parse AS_PATH condition value.")
return nil
}
}
-
c := &AsPathCondition{
AsPathList: asPathList,
MatchOption: options,
@@ -465,36 +487,64 @@ func NewAsPathCondition(matchSet config.MatchAsPathSet, defAsPathSetList []confi
}
func (c *AsPathCondition) checkMembers(aspath []uint32, checkAll bool) bool {
- result := false
- if checkAll {
- result = true
- }
- for _, member := range c.AsPathList {
- matched := false
- switch member.postiion {
+ checkElem := func(checkType AsnPos, regElems []*regexp.Regexp) bool {
+ aslen := len(aspath)
+ reglen := len(regElems)
+
+ if aslen < reglen {
+ return false
+ }
+
+ switch checkType {
+ case AS_ONLY:
+ if aslen != reglen {
+ return false
+ }
+ fallthrough
case AS_FROM:
- matched = aspath[0] == member.asn
+ for i := 0; i < reglen; i++ {
+ if !regElems[i].MatchString(fmt.Sprintf("%d", aspath[i])) {
+ return false
+ }
+ }
+ case AS_ORIGIN:
+ for i := 0; i < reglen; i++ {
+ if !regElems[reglen-i-1].MatchString(fmt.Sprintf("%d", aspath[aslen-i-1])) {
+ return false
+ }
+ }
case AS_ANY:
- for _, n := range aspath {
- if n == member.asn {
- matched = true
+ for i := 0; i < aslen; i++ {
+ eMatched := true
+ if aslen < i+reglen {
break
}
+ for j := 0; j < reglen; j++ {
+ if !regElems[j].MatchString(fmt.Sprintf("%d", aspath[i+j])) {
+ eMatched = false
+ break
+ }
+ }
+ if eMatched {
+ return true
+ }
}
- case AS_ORIGIN:
- matched = aspath[len(aspath)-1] == member.asn
-
- case AS_ONLY:
- matched = len(aspath) == 1 && aspath[0] == member.asn
-
+ return false
}
+ return true
+ }
- if matched {
+ result := false
+ if checkAll {
+ result = true
+ }
+ for _, member := range c.AsPathList {
+ if checkElem(member.postiion, member.asRegExps) {
log.WithFields(log.Fields{
"Topic": "Policy",
"Condition": "aspath length",
- "ASN": member.asn,
+ "ASN": member.asStr,
"Position": member.postiion,
}).Debug("aspath condition matched")
@@ -520,7 +570,7 @@ func (c *AsPathCondition) evaluate(path *table.Path) bool {
aspath := path.GetAsSeqList()
- if len(aspath) == 0 {
+ if c == nil || len(aspath) == 0 {
return false
}
@@ -1635,7 +1685,7 @@ func PrefixSetToApiStruct(ps config.PrefixSet) *api.PrefixSet {
resPrefixList := make([]*api.Prefix, 0)
for _, p := range ps.PrefixList {
resPrefix := &api.Prefix{
- IpPrefix: p.IpPrefix,
+ IpPrefix: p.IpPrefix,
MaskLengthRange: p.MasklengthRange,
}
resPrefixList = append(resPrefixList, resPrefix)