summaryrefslogtreecommitdiffhomepage
path: root/table
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-10-15 21:12:40 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-10-20 10:33:10 +0900
commit7937d8ddb6f8f82c593fb3b019d1fc618dc89f48 (patch)
tree853aa4860dd2a392cb7692c4b13741e2db1a0e26 /table
parent473f5b6ff32be2829dac2a19bd63df19a7efd4ec (diff)
policy: clean up
remove redundant api structures and shorten valiable names re-implement *ToApiStruct functions as a method of each structures Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'table')
-rw-r--r--table/path.go11
-rw-r--r--table/policy.go2796
-rw-r--r--table/policy_test.go503
3 files changed, 1459 insertions, 1851 deletions
diff --git a/table/path.go b/table/path.go
index b45b7f68..bcf5b4ce 100644
--- a/table/path.go
+++ b/table/path.go
@@ -556,16 +556,7 @@ func (path *Path) GetExtCommunities() []bgp.ExtendedCommunityInterface {
return eCommunityList
}
-func (path *Path) SetExtCommunities(values []byte, doReplace bool) {
- exts := []bgp.ExtendedCommunityInterface{}
- for len(values) >= 8 {
- e := &bgp.UnknownExtended{
- Type: bgp.BGPAttrType(values[0]),
- Value: values[1:8],
- }
- exts = append(exts, e)
- values = values[8:]
- }
+func (path *Path) SetExtCommunities(exts []bgp.ExtendedCommunityInterface, doReplace bool) {
idx, attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
if attr != nil {
l := attr.(*bgp.PathAttributeExtendedCommunities).Value
diff --git a/table/policy.go b/table/policy.go
index bec56e07..6d33a35f 100644
--- a/table/policy.go
+++ b/table/policy.go
@@ -24,11 +24,22 @@ import (
"strings"
log "github.com/Sirupsen/logrus"
- "github.com/osrg/gobgp/api"
+ api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet"
)
+type DefinedType int
+
+const (
+ DEFINED_TYPE_PREFIX DefinedType = iota
+ DEFINED_TYPE_NEIGHBOR
+ DEFINED_TYPE_TAG
+ DEFINED_TYPE_AS_PATH
+ DEFINED_TYPE_COMMUNITY
+ DEFINED_TYPE_EXT_COMMUNITY
+)
+
type RouteType int
const (
@@ -37,38 +48,76 @@ const (
ROUTE_TYPE_REJECT
)
-func (t RouteType) String() string {
- switch t {
- case ROUTE_TYPE_NONE:
- return "NONE"
- case ROUTE_TYPE_ACCEPT:
- return "ACCEPT"
- case ROUTE_TYPE_REJECT:
- return "REJECT"
- default:
- return fmt.Sprintf("Unknown(%d)", t)
- }
-}
+type PolicyDirection int
+
+const (
+ POLICY_DIRECTION_IMPORT PolicyDirection = iota
+ POLICY_DIRECTION_EXPORT
+ POLICY_DIRECTION_IN
+)
-func (t RouteType) ToApiStruct() gobgpapi.RouteAction {
- switch t {
- case ROUTE_TYPE_ACCEPT:
- return gobgpapi.RouteAction_ACCEPT
- case ROUTE_TYPE_REJECT:
- return gobgpapi.RouteAction_REJECT
+type MatchOption int
+
+const (
+ MATCH_OPTION_ANY MatchOption = iota
+ MATCH_OPTION_ALL
+ MATCH_OPTION_INVERT
+)
+
+func (o MatchOption) String() string {
+ switch o {
+ case MATCH_OPTION_ANY:
+ return "any"
+ case MATCH_OPTION_ALL:
+ return "all"
+ case MATCH_OPTION_INVERT:
+ return "invert"
default:
- return gobgpapi.RouteAction_NONE
+ return fmt.Sprintf("MatchOption(%d)", o)
}
}
-type PolicyDirection int
+type MedActionType int
const (
- POLICY_DIRECTION_IN = iota
- POLICY_DIRECTION_IMPORT = iota
- POLICY_DIRECTION_EXPORT
+ MED_ACTION_MOD MedActionType = iota
+ MED_ACTION_REPLACE
)
+var CommunityOptionNameMap = map[config.BgpSetCommunityOptionType]string{
+ config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD: "add",
+ config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE: "remove",
+ config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: "replace",
+}
+
+var CommunityOptionValueMap = map[string]config.BgpSetCommunityOptionType{
+ CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD]: config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD,
+ CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE,
+ CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE,
+}
+
+func NewMatchOption(c interface{}) (MatchOption, error) {
+ switch c.(type) {
+ case config.MatchSetOptionsType:
+ switch c.(config.MatchSetOptionsType) {
+ case config.MATCH_SET_OPTIONS_TYPE_ANY:
+ return MATCH_OPTION_ANY, nil
+ case config.MATCH_SET_OPTIONS_TYPE_ALL:
+ return MATCH_OPTION_ALL, nil
+ case config.MATCH_SET_OPTIONS_TYPE_INVERT:
+ return MATCH_OPTION_INVERT, nil
+ }
+ case config.MatchSetOptionsRestrictedType:
+ switch c.(config.MatchSetOptionsRestrictedType) {
+ case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY:
+ return MATCH_OPTION_ANY, nil
+ case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT:
+ return MATCH_OPTION_INVERT, nil
+ }
+ }
+ return MATCH_OPTION_ANY, fmt.Errorf("invalid argument to create match option: %v", c)
+}
+
type AttributeComparison int
const (
@@ -80,196 +129,411 @@ const (
ATTRIBUTE_LE
)
-type Policy struct {
- Name string
- Statements []*Statement
+const (
+ ASPATH_REGEXP_MAGIC = "(^|[,{}() ]|$)"
+)
+
+type DefinedSet interface {
+ Type() DefinedType
+ Name() string
+}
+
+type DefinedSetMap map[DefinedType]map[string]DefinedSet
+
+type Prefix struct {
+ Prefix *net.IPNet
+ AddressFamily bgp.RouteFamily
+ MasklengthRangeMax uint8
+ MasklengthRangeMin uint8
}
-func NewPolicy(pd config.PolicyDefinition, ds config.DefinedSets) *Policy {
- stmtList := pd.Statements.StatementList
- st := make([]*Statement, 0)
- p := &Policy{
- Name: pd.Name,
+func (p *Prefix) Match(path *Path) bool {
+ rf := path.GetRouteFamily()
+ if rf != p.AddressFamily {
+ return false
}
- for _, statement := range stmtList {
- conditions := make([]Condition, 0)
+ var pAddr net.IP
+ var pMasklen uint8
+ switch rf {
+ case bgp.RF_IPv4_UC:
+ pAddr = path.GetNlri().(*bgp.IPAddrPrefix).Prefix
+ pMasklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
+ case bgp.RF_IPv6_UC:
+ pAddr = path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix
+ pMasklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
+ default:
+ return false
+ }
- // prefix match
- pc := NewPrefixCondition(statement.Conditions.MatchPrefixSet, ds.PrefixSets.PrefixSetList)
- if pc != nil {
- conditions = append(conditions, pc)
- }
+ return (p.MasklengthRangeMin <= pMasklen && pMasklen <= p.MasklengthRangeMax) && p.Prefix.Contains(pAddr)
+}
- // neighbor match
- nc := NewNeighborCondition(statement.Conditions.MatchNeighborSet, ds.NeighborSets.NeighborSetList)
- if nc != nil {
- conditions = append(conditions, nc)
- }
+func (p *Prefix) ToApiStruct() *api.Prefix {
+ return &api.Prefix{
+ IpPrefix: p.Prefix.String(),
+ MaskLengthRange: fmt.Sprintf("%d..%d", p.MasklengthRangeMin, p.MasklengthRangeMax),
+ }
+}
- // AsPathLengthCondition
- c := statement.Conditions.BgpConditions.AsPathLength
- ac := NewAsPathLengthCondition(c)
- if ac != nil {
- conditions = append(conditions, ac)
- }
+func NewPrefix(c config.Prefix) (*Prefix, error) {
+ addr, prefix, err := net.ParseCIDR(c.IpPrefix)
+ if err != nil {
+ return nil, err
+ }
- if statement.Conditions.BgpConditions.RpkiValidationResult != config.RPKI_VALIDATION_RESULT_TYPE_NONE {
- conditions = append(conditions, NewRPKIValidationCondition(statement.Conditions.BgpConditions.RpkiValidationResult))
+ rf := bgp.RF_IPv4_UC
+ if addr.To4() == nil {
+ rf = bgp.RF_IPv6_UC
+ }
+ p := &Prefix{
+ Prefix: prefix,
+ AddressFamily: rf,
+ }
+ maskRange := c.MasklengthRange
+ if maskRange == "" {
+ l, _ := prefix.Mask.Size()
+ maskLength := uint8(l)
+ p.MasklengthRangeMax = maskLength
+ p.MasklengthRangeMin = maskLength
+ } else {
+ exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)")
+ elems := exp.FindStringSubmatch(maskRange)
+ if len(elems) != 3 {
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Type": "Prefix",
+ "MaskRangeFormat": maskRange,
+ }).Warn("mask length range format is invalid.")
+ return nil, fmt.Errorf("mask length range format is invalid")
}
+ // we've already checked the range is sane by regexp
+ min, _ := strconv.Atoi(elems[1])
+ max, _ := strconv.Atoi(elems[2])
+ p.MasklengthRangeMin = uint8(min)
+ p.MasklengthRangeMax = uint8(max)
+ }
+ return p, nil
+}
- bgpDefset := &ds.BgpDefinedSets
- bgpConditions := &statement.Conditions.BgpConditions
- // AsPathCondition
- asc := NewAsPathCondition(bgpConditions.MatchAsPathSet, bgpDefset.AsPathSets.AsPathSetList)
- if asc != nil {
- conditions = append(conditions, asc)
- }
+type PrefixSet struct {
+ name string
+ list []*Prefix
+}
- // CommunityCondition
- cc := NewCommunityCondition(bgpConditions.MatchCommunitySet, bgpDefset.CommunitySets.CommunitySetList)
- if cc != nil {
- conditions = append(conditions, cc)
- }
+func (s *PrefixSet) Name() string {
+ return s.name
+}
- // ExtendedCommunityCondition
- ecc := NewExtCommunityCondition(bgpConditions.MatchExtCommunitySet, bgpDefset.ExtCommunitySets.ExtCommunitySetList)
- if ecc != nil {
- conditions = append(conditions, ecc)
- }
+func (s *PrefixSet) Type() DefinedType {
+ return DEFINED_TYPE_PREFIX
+}
- // routing action
- ra := NewRoutingAction(statement.Actions)
+func (s *PrefixSet) ToApiStruct() *api.PrefixSet {
+ list := make([]*api.Prefix, 0, len(s.list))
+ for _, p := range s.list {
+ list = append(list, p.ToApiStruct())
+ }
+ return &api.PrefixSet{
+ Name: s.name,
+ List: list,
+ }
+}
- // Community action
- mda := make([]Action, 0)
- com := NewCommunityAction(statement.Actions.BgpActions.SetCommunity)
- if com != nil {
- mda = append(mda, com)
+func NewPrefixSet(c config.PrefixSet) (*PrefixSet, error) {
+ name := c.PrefixSetName
+ if name == "" {
+ if len(c.PrefixList) == 0 {
+ return nil, nil
}
-
- ext := NewExtCommunityAction(statement.Actions.BgpActions.SetExtCommunity)
- if ext != nil {
- mda = append(mda, ext)
+ return nil, fmt.Errorf("empty prefix set name")
+ }
+ list := make([]*Prefix, 0, len(c.PrefixList))
+ for _, x := range c.PrefixList {
+ y, err := NewPrefix(x)
+ if err != nil {
+ return nil, err
}
+ list = append(list, y)
+ }
+ return &PrefixSet{
+ name: name,
+ list: list,
+ }, nil
+}
- // Med Action
- med := NewMedAction(statement.Actions.BgpActions.SetMed)
- if med != nil {
- mda = append(mda, med)
- }
+type NeighborSet struct {
+ name string
+ list []net.IP
+}
- //AsPathPrependAction
- ppa := NewAsPathPrependAction(statement.Actions.BgpActions.SetAsPathPrepend)
- if ppa != nil {
- mda = append(mda, ppa)
- }
+func (s *NeighborSet) Name() string {
+ return s.name
+}
+
+func (s *NeighborSet) Type() DefinedType {
+ return DEFINED_TYPE_NEIGHBOR
+}
+
+func (s *NeighborSet) ToApiStruct() *api.MatchSet {
+ list := make([]string, 0, len(s.list))
+ for _, n := range s.list {
+ list = append(list, n.String())
+ }
+ return &api.MatchSet{
+ Name: s.name,
+ List: list,
+ }
+}
- s := &Statement{
- Name: statement.Name,
- Conditions: conditions,
- routingAction: ra,
- modificationActions: mda,
+func NewNeighborSet(c config.NeighborSet) (*NeighborSet, error) {
+ name := c.NeighborSetName
+ if name == "" {
+ if len(c.NeighborInfoList) == 0 {
+ return nil, nil
}
+ return nil, fmt.Errorf("empty neighbor set name")
+ }
+ list := make([]net.IP, 0, len(c.NeighborInfoList))
+ for _, x := range c.NeighborInfoList {
+ list = append(list, x.Address)
+ }
+ return &NeighborSet{
+ name: name,
+ list: list,
+ }, nil
+}
- st = append(st, s)
+type regExpSet struct {
+ name string
+ list []*regexp.Regexp
+}
+
+func (s *regExpSet) Name() string {
+ return s.name
+}
+
+func (s *regExpSet) ToApiStruct() *api.MatchSet {
+ list := make([]string, 0, len(s.list))
+ for _, exp := range s.list {
+ list = append(list, exp.String())
+ }
+ return &api.MatchSet{
+ Name: s.name,
+ List: list,
}
- p.Statements = st
- return p
}
-type Statement struct {
- Name string
- Conditions []Condition
- routingAction *RoutingAction
- modificationActions []Action
+type AsPathSet struct {
+ regExpSet
}
-// evaluate each condition in the statement according to MatchSetOptions
-func (s *Statement) evaluate(p *Path) bool {
+func (s *AsPathSet) Type() DefinedType {
+ return DEFINED_TYPE_AS_PATH
+}
- for _, condition := range s.Conditions {
- r := condition.evaluate(p)
- if !r {
- return false
+func NewAsPathSet(c config.AsPathSet) (*AsPathSet, error) {
+ name := c.AsPathSetName
+ if name == "" {
+ if len(c.AsPathList) == 0 {
+ return nil, nil
}
+ return nil, fmt.Errorf("empty as-path set name")
}
- return true
+ list := make([]*regexp.Regexp, 0, len(c.AsPathList))
+ for _, x := range c.AsPathList {
+ exp, err := regexp.Compile(strings.Replace(x.AsPath, "_", ASPATH_REGEXP_MAGIC, -1))
+ if err != nil {
+ return nil, fmt.Errorf("invalid regular expression: %s", x)
+ }
+ list = append(list, exp)
+ }
+ return &AsPathSet{
+ regExpSet: regExpSet{
+ name: name,
+ list: list,
+ },
+ }, nil
}
-type Condition interface {
- evaluate(*Path) bool
+type CommunitySet struct {
+ regExpSet
+}
+
+func (s *CommunitySet) Type() DefinedType {
+ return DEFINED_TYPE_COMMUNITY
}
-type DefaultCondition struct {
- CallPolicy string
+func ParseCommunity(arg string) (uint32, error) {
+ i, err := strconv.Atoi(arg)
+ if err == nil {
+ return uint32(i), nil
+ }
+ exp := regexp.MustCompile("(\\d+):(\\d+)")
+ elems := exp.FindStringSubmatch(arg)
+ if len(elems) == 3 {
+ fst, _ := strconv.Atoi(elems[1])
+ snd, _ := strconv.Atoi(elems[2])
+ return uint32(fst<<16 | snd), nil
+ }
+ for i, v := range bgp.WellKnownCommunityNameMap {
+ if arg == v {
+ return uint32(i), nil
+ }
+ }
+ return 0, fmt.Errorf("failed to parse %s as community", arg)
}
-func (c *DefaultCondition) evaluate(path *Path) bool {
- return false
+func parseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) {
+ var subtype bgp.ExtendedCommunityAttrSubType
+ elems := strings.SplitN(arg, ":", 2)
+ if len(elems) < 2 {
+ return nil, fmt.Errorf("invalid ext-community format([rt|soo]:<value>)")
+ }
+ switch strings.ToLower(elems[0]) {
+ case "rt":
+ subtype = bgp.EC_SUBTYPE_ROUTE_TARGET
+ case "soo":
+ subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN
+ default:
+ return nil, fmt.Errorf("unknown ext-community subtype. rt, soo is supported")
+ }
+ return bgp.ParseExtendedCommunity(subtype, elems[1])
}
-type PrefixCondition struct {
- DefaultCondition
- PrefixConditionName string
- PrefixList []Prefix
- MatchOption config.MatchSetOptionsRestrictedType
-}
-
-func NewPrefixCondition(matchPref config.MatchPrefixSet, defPrefixList []config.PrefixSet) *PrefixCondition {
-
- prefixSetName := matchPref.PrefixSet
- options := matchPref.MatchSetOptions
-
- prefixList := make([]Prefix, 0)
- for _, ps := range defPrefixList {
- if ps.PrefixSetName == prefixSetName {
- for _, prefix := range ps.PrefixList {
- prefix, e := NewPrefix(prefix.IpPrefix, prefix.MasklengthRange)
- if e != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "prefix": prefix,
- "msg": e,
- }).Error("failed to generate a NewPrefix from configration.")
- } else {
- prefixList = append(prefixList, prefix)
- }
- }
+func parseCommunityRegexp(arg string) (*regexp.Regexp, error) {
+ i, err := strconv.Atoi(arg)
+ if err == nil {
+ return regexp.MustCompile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)), nil
+ }
+ if regexp.MustCompile("(\\d+.)*\\d+:\\d+").MatchString(arg) {
+ return regexp.MustCompile(fmt.Sprintf("^%s$", arg)), nil
+ }
+ for i, v := range bgp.WellKnownCommunityNameMap {
+ if strings.Replace(strings.ToLower(arg), "_", "-", -1) == v {
+ return regexp.MustCompile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)), nil
}
}
+ exp, err := regexp.Compile(arg)
+ if err != nil {
+ return nil, fmt.Errorf("invalid community format: %s", arg)
+ }
+ return exp, nil
+}
+
+func parseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) {
+ var subtype bgp.ExtendedCommunityAttrSubType
+ elems := strings.SplitN(arg, ":", 2)
+ if len(elems) < 2 {
+ return subtype, nil, fmt.Errorf("invalid ext-community format([rt|soo]:<value>)")
+ }
+ switch strings.ToLower(elems[0]) {
+ case "rt":
+ subtype = bgp.EC_SUBTYPE_ROUTE_TARGET
+ case "soo":
+ subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN
+ default:
+ return subtype, nil, fmt.Errorf("unknown ext-community subtype. rt, soo is supported")
+ }
+ exp, err := parseCommunityRegexp(elems[1])
+ return subtype, exp, err
+}
- if len(prefixList) == 0 {
- return nil
+func NewCommunitySet(c config.CommunitySet) (*CommunitySet, error) {
+ name := c.CommunitySetName
+ if name == "" {
+ if len(c.CommunityList) == 0 {
+ return nil, nil
+ }
+ return nil, fmt.Errorf("empty community set name")
}
+ list := make([]*regexp.Regexp, 0, len(c.CommunityList))
+ for _, x := range c.CommunityList {
+ exp, err := parseCommunityRegexp(x.Community)
+ if err != nil {
+ return nil, err
+ }
+ list = append(list, exp)
+ }
+ return &CommunitySet{
+ regExpSet: regExpSet{
+ name: name,
+ list: list,
+ },
+ }, nil
+}
+
+type ExtCommunitySet struct {
+ regExpSet
+ subtypeList []bgp.ExtendedCommunityAttrSubType
+}
- pc := &PrefixCondition{
- PrefixConditionName: prefixSetName,
- PrefixList: prefixList,
- MatchOption: options,
+func (s *ExtCommunitySet) Type() DefinedType {
+ return DEFINED_TYPE_EXT_COMMUNITY
+}
+
+func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) {
+ name := c.ExtCommunitySetName
+ if name == "" {
+ if len(c.ExtCommunityList) == 0 {
+ return nil, nil
+ }
+ return nil, fmt.Errorf("empty ext-community set name")
+ }
+ list := make([]*regexp.Regexp, 0, len(c.ExtCommunityList))
+ subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.ExtCommunityList))
+ for _, x := range c.ExtCommunityList {
+ subtype, exp, err := parseExtCommunityRegexp(x.ExtCommunity)
+ if err != nil {
+ return nil, err
+ }
+ list = append(list, exp)
+ subtypeList = append(subtypeList, subtype)
}
+ return &ExtCommunitySet{
+ regExpSet: regExpSet{
+ name: name,
+ list: list,
+ },
+ subtypeList: subtypeList,
+ }, nil
+}
+
+type Condition interface {
+ Evaluate(*Path) bool
+}
+
+type PrefixCondition struct {
+ set *PrefixSet
+ option MatchOption
+}
+
+func (c *PrefixCondition) Set() DefinedSet {
+ return c.set
+}
- return pc
+func (c *PrefixCondition) Option() MatchOption {
+ return c.option
}
// compare prefixes in this condition and nlri of path and
// subsequent comparison is skipped if that matches the conditions.
// If PrefixList's length is zero, return true.
-func (c *PrefixCondition) evaluate(path *Path) bool {
+func (c *PrefixCondition) Evaluate(path *Path) bool {
- if len(c.PrefixList) == 0 {
+ if len(c.set.list) == 0 {
log.Debug("PrefixList doesn't have elements")
return true
}
result := false
- for _, cp := range c.PrefixList {
- if ipPrefixCalculate(path, cp) {
+ for _, p := range c.set.list {
+ if p.Match(path) {
result = true
break
}
}
- if c.MatchOption == config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT {
+ if c.option == MATCH_OPTION_INVERT {
result = !result
}
@@ -278,51 +542,58 @@ func (c *PrefixCondition) evaluate(path *Path) bool {
"Condition": "prefix",
"Path": path,
"Matched": result,
- }).Debug("evaluate prefix")
+ }).Debug("evaluation result")
return result
}
-type NeighborCondition struct {
- DefaultCondition
- NeighborConditionName string
- NeighborList []net.IP
- MatchOption config.MatchSetOptionsRestrictedType
+func (c *PrefixCondition) ToApiStruct() *api.PrefixSet {
+ s := c.set.ToApiStruct()
+ s.Option = int32(c.option)
+ return s
}
-func NewNeighborCondition(matchNeighborSet config.MatchNeighborSet, defNeighborSetList []config.NeighborSet) *NeighborCondition {
-
- neighborSetName := matchNeighborSet.NeighborSet
- options := matchNeighborSet.MatchSetOptions
-
- neighborList := make([]net.IP, 0)
- for _, neighborSet := range defNeighborSetList {
- if neighborSet.NeighborSetName == neighborSetName {
- for _, nl := range neighborSet.NeighborInfoList {
- neighborList = append(neighborList, nl.Address)
- }
- }
+func NewPrefixCondition(c config.MatchPrefixSet, m map[string]DefinedSet) (*PrefixCondition, error) {
+ if c.PrefixSet == "" {
+ return nil, nil
}
-
- if len(neighborList) == 0 {
- return nil
+ i, ok := m[c.PrefixSet]
+ if !ok {
+ return nil, fmt.Errorf("not found prefix set %s", c.PrefixSet)
}
-
- nc := &NeighborCondition{
- NeighborConditionName: neighborSetName,
- NeighborList: neighborList,
- MatchOption: options,
+ s, ok := i.(*PrefixSet)
+ if !ok {
+ return nil, fmt.Errorf("type assert from DefinedSet to *PrefixSet failed")
+ }
+ o, err := NewMatchOption(c.MatchSetOptions)
+ if err != nil {
+ return nil, err
}
+ return &PrefixCondition{
+ set: s,
+ option: o,
+ }, nil
+}
+
+type NeighborCondition struct {
+ set *NeighborSet
+ option MatchOption
+}
+
+func (c *NeighborCondition) Set() DefinedSet {
+ return c.set
+}
- return nc
+func (c *NeighborCondition) Option() MatchOption {
+ return c.option
}
// compare neighbor ipaddress of this condition and source address of path
// and, subsequent comparisons are skipped if that matches the conditions.
// If NeighborList's length is zero, return true.
-func (c *NeighborCondition) evaluate(path *Path) bool {
+func (c *NeighborCondition) Evaluate(path *Path) bool {
- if len(c.NeighborList) == 0 {
+ if len(c.set.list) == 0 {
log.Debug("NeighborList doesn't have elements")
return true
}
@@ -331,14 +602,14 @@ func (c *NeighborCondition) evaluate(path *Path) bool {
return false
}
result := false
- for _, neighbor := range c.NeighborList {
- if path.Owner.Equal(neighbor) {
+ for _, n := range c.set.list {
+ if path.Owner.Equal(n) {
result = true
break
}
}
- if c.MatchOption == config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT {
+ if c.option == MATCH_OPTION_INVERT {
result = !result
}
@@ -347,774 +618,370 @@ func (c *NeighborCondition) evaluate(path *Path) bool {
"Condition": "neighbor",
"NeighborAddress": path.Owner,
"Matched": result,
- }).Debug("evaluate neighbor")
+ }).Debug("evaluation result")
return result
}
-type AsPathLengthCondition struct {
- DefaultCondition
- Value uint32
- Operator AttributeComparison
+func (c *NeighborCondition) ToApiStruct() *api.MatchSet {
+ s := c.set.ToApiStruct()
+ s.Option = int32(c.option)
+ return s
}
-// create AsPathLengthCondition object
-func NewAsPathLengthCondition(defAsPathLength config.AsPathLength) *AsPathLengthCondition {
-
- value := defAsPathLength.Value
- var op AttributeComparison
-
- switch defAsPathLength.Operator {
- case "eq":
- op = ATTRIBUTE_EQ
-
- case "ge":
- op = ATTRIBUTE_GE
-
- case "le":
- op = ATTRIBUTE_LE
- default:
- return nil
+func NewNeighborCondition(c config.MatchNeighborSet, m map[string]DefinedSet) (*NeighborCondition, error) {
+ if c.NeighborSet == "" {
+ return nil, nil
}
-
- ac := &AsPathLengthCondition{
- Value: value,
- Operator: op,
+ i, ok := m[c.NeighborSet]
+ if !ok {
+ return nil, fmt.Errorf("not found neighbor set %s", c.NeighborSet)
}
-
- return ac
-}
-
-// compare AS_PATH length in the message's AS_PATH attribute with
-// the one in condition.
-func (c *AsPathLengthCondition) evaluate(path *Path) bool {
-
- length := uint32(path.GetAsPathLen())
- result := false
-
- switch c.Operator {
- case ATTRIBUTE_EQ:
- result = c.Value == length
-
- case ATTRIBUTE_GE:
- result = c.Value <= length
-
- case ATTRIBUTE_LE:
- result = c.Value >= length
- default:
- result = false
+ s, ok := i.(*NeighborSet)
+ if !ok {
+ return nil, fmt.Errorf("type assert from DefinedSet to *NeighborSet failed")
}
-
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Condition": "aspath length",
- "Reason": c.Operator,
- "Matched": result,
- }).Debug("evaluate aspath length")
-
- return result
+ o, err := NewMatchOption(c.MatchSetOptions)
+ if err != nil {
+ return nil, err
+ }
+ return &NeighborCondition{
+ set: s,
+ option: o,
+ }, nil
}
type AsPathCondition struct {
- DefaultCondition
- AsRegExpList []*regexp.Regexp
- MatchOption config.MatchSetOptionsType
+ set *AsPathSet
+ option MatchOption
}
-const (
- ASPATH_REGEXP_MAGIC = "(^|[,{}() ]|$)"
-)
-
-func NewAsPathCondition(matchSet config.MatchAsPathSet, defAsPathSetList []config.AsPathSet) *AsPathCondition {
- asPathSetName := matchSet.AsPathSet
- options := matchSet.MatchSetOptions
-
- asRegExpList := make([]*regexp.Regexp, 0)
- for _, asPathSet := range defAsPathSetList {
- if asPathSet.AsPathSetName == asPathSetName {
- for _, aspath := range asPathSet.AsPathList {
- a := aspath.AsPath
- if len(a) != 0 {
- r, err := regexp.Compile(strings.Replace(a, "_", ASPATH_REGEXP_MAGIC, -1))
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "AsPath Condition",
- "Value": aspath.AsPath,
- "Error": err,
- }).Error("can not comple AS_PATH values to Regular expressions.")
- return nil
- }
-
- asRegExpList = append(asRegExpList, r)
- } else {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "AsPath Condition",
- }).Error("does not parse AS_PATH condition value.")
- return nil
- }
- }
- c := &AsPathCondition{
- AsRegExpList: asRegExpList,
- MatchOption: options,
- }
- return c
- }
- }
- return nil
+func (c *AsPathCondition) Set() *AsPathSet {
+ return c.set
}
-func (c *AsPathCondition) checkMembers(aspathStr string, checkAll bool) bool {
- for _, r := range c.AsRegExpList {
- if r.MatchString(aspathStr) {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Condition": "aspath length",
- "AS": aspathStr,
- "ASN": r,
- }).Debug("aspath condition matched")
-
- if !checkAll {
- return true
- }
- } else {
- if checkAll {
- return false
- }
- }
- }
- return checkAll
+func (c *AsPathCondition) Option() MatchOption {
+ return c.option
}
-// compare AS_PATH in the message's AS_PATH attribute with
-// the one in condition.
-func (c *AsPathCondition) evaluate(path *Path) bool {
-
- aspathStr := path.GetAsString()
+func (c *AsPathCondition) ToApiStruct() *api.MatchSet {
+ s := c.set.ToApiStruct()
+ s.Option = int32(c.option)
+ return s
+}
+func (c *AsPathCondition) Evaluate(path *Path) bool {
+ aspath := path.GetAsString()
result := false
- if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ALL {
- result = c.checkMembers(aspathStr, true)
- } else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ANY {
- result = c.checkMembers(aspathStr, false)
- } else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_INVERT {
- result = !c.checkMembers(aspathStr, false)
+ for _, r := range c.set.list {
+ result = false
+ if r.MatchString(aspath) {
+ result = true
+ }
+ if c.option == MATCH_OPTION_ALL && !result {
+ break
+ }
+ if c.option == MATCH_OPTION_ANY && result {
+ break
+ }
+ }
+ if c.option == MATCH_OPTION_INVERT {
+ result = !result
}
-
log.WithFields(log.Fields{
"Topic": "Policy",
"Condition": "aspath",
- "MatchOption": c.MatchOption,
+ "MatchOption": c.option,
"Matched": result,
- }).Debug("evaluate aspath")
-
+ }).Debug("evaluation result")
return result
}
-type CommunityCondition struct {
- DefaultCondition
- CommunityList []*CommunityElement
- MatchOption config.MatchSetOptionsType
+func NewAsPathCondition(c config.MatchAsPathSet, m map[string]DefinedSet) (*AsPathCondition, error) {
+ if c.AsPathSet == "" {
+ return nil, nil
+ }
+ i, ok := m[c.AsPathSet]
+ if !ok {
+ return nil, fmt.Errorf("not found as path set %s", c.AsPathSet)
+ }
+ s, ok := i.(*AsPathSet)
+ if !ok {
+ return nil, fmt.Errorf("type assert from DefinedSet to *AsPathSet failed")
+ }
+ o, err := NewMatchOption(c.MatchSetOptions)
+ if err != nil {
+ return nil, err
+ }
+ return &AsPathCondition{
+ set: s,
+ option: o,
+ }, nil
}
-const (
- COMMUNITY_INTERNET string = "INTERNET"
- COMMUNITY_NO_EXPORT string = "NO_EXPORT"
- COMMUNITY_NO_ADVERTISE string = "NO_ADVERTISE"
- COMMUNITY_NO_EXPORT_SUBCONFED string = "NO_EXPORT_SUBCONFED"
-)
+type CommunityCondition struct {
+ set *CommunitySet
+ option MatchOption
+}
-const (
- COMMUNITY_INTERNET_VAL uint32 = 0x00000000
- COMMUNITY_NO_EXPORT_VAL = 0xFFFFFF01
- COMMUNITY_NO_ADVERTISE_VAL = 0xFFFFFF02
- COMMUNITY_NO_EXPORT_SUBCONFED_VAL = 0xFFFFFF03
-)
+func (c *CommunityCondition) Set() *CommunitySet {
+ return c.set
+}
-type CommunityElement struct {
- community uint32
- communityStr string
- isRegExp bool
- communityRegExp *regexp.Regexp
-}
-
-// create CommunityCondition object
-// CommunityCondition supports uint and string like 65000:100
-// and also supports regular expressions that are available in golang.
-// if GoBGP can't parse the regular expression, it return nil and an error message is logged.
-func NewCommunityCondition(matchSet config.MatchCommunitySet, defCommunitySetList []config.CommunitySet) *CommunityCondition {
-
- communitySetName := matchSet.CommunitySet
- options := matchSet.MatchSetOptions
-
- communityList := make([]*CommunityElement, 0)
- for _, communitySet := range defCommunitySetList {
- if communitySet.CommunitySetName == communitySetName {
- for _, community := range communitySet.CommunityList {
- c := community.Community
- e := &CommunityElement{
- isRegExp: false,
- communityStr: c,
- }
-
- if matched, v := getCommunityValue(c); matched {
- e.community = v
- } else {
- // specified by regular expression
- e.isRegExp = true
- reg, err := regexp.Compile(c)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Community Condition",
- }).Error("Regular expression can't be compiled.")
- return nil
- }
- e.communityRegExp = reg
- }
- communityList = append(communityList, e)
- }
+func (c *CommunityCondition) Option() MatchOption {
+ return c.option
+}
- c := &CommunityCondition{
- CommunityList: communityList,
- MatchOption: options,
- }
- return c
- }
- }
- return nil
+func (c *CommunityCondition) ToApiStruct() *api.MatchSet {
+ s := c.set.ToApiStruct()
+ s.Option = int32(c.option)
+ return s
}
-// getCommunityValue returns uint32 community value converted from the string.
-// if the string doesn't match a number or string like "65000:1000" or well known
-// community name, it returns false and 0, otherwise returns true and its uint32 value.
-func getCommunityValue(comStr string) (bool, uint32) {
- // community regexp
- regUint, _ := regexp.Compile("^([0-9]+)$")
- regString, _ := regexp.Compile("([0-9]+):([0-9]+)")
- regWellKnown, _ := regexp.Compile("^(" +
- COMMUNITY_INTERNET + "|" +
- COMMUNITY_NO_EXPORT + "|" +
- COMMUNITY_NO_ADVERTISE + "|" +
- COMMUNITY_NO_EXPORT_SUBCONFED + ")$")
-
- if regUint.MatchString(comStr) {
- // specified by Uint
- community, err := strconv.ParseUint(comStr, 10, 32)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Community Condition",
- }).Error("failed to parse the community value.")
+func (c *CommunityCondition) Evaluate(path *Path) bool {
+ cs := path.GetCommunities()
+ result := false
+ for _, x := range cs {
+ result = false
+ for _, y := range c.set.list {
+ if y.MatchString(fmt.Sprintf("%d:%d", x>>16, x&0x0000ffff)) {
+ result = true
+ break
+ }
}
- return true, uint32(community)
-
- } else if regString.MatchString(comStr) {
- // specified by string containing ":"
- group := regString.FindStringSubmatch(comStr)
- asn, errAsn := strconv.ParseUint(group[1], 10, 16)
- val, errVal := strconv.ParseUint(group[2], 10, 16)
-
- if errAsn != nil || errVal != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Community Condition",
- }).Error("failed to parser as number or community value.")
+ if c.option == MATCH_OPTION_ALL && !result {
+ break
}
- community := uint32(asn<<16 | val)
- return true, community
-
- } else if regWellKnown.MatchString(comStr) {
- // specified by well known community name
- var community uint32
- switch comStr {
- case COMMUNITY_INTERNET:
- community = COMMUNITY_INTERNET_VAL
- case COMMUNITY_NO_EXPORT:
- community = COMMUNITY_NO_EXPORT_VAL
- case COMMUNITY_NO_ADVERTISE:
- community = COMMUNITY_NO_ADVERTISE_VAL
- case COMMUNITY_NO_EXPORT_SUBCONFED:
- community = COMMUNITY_NO_EXPORT_SUBCONFED_VAL
+ if c.option == MATCH_OPTION_ANY && result {
+ break
}
- return true, community
}
- return false, 0
+ if c.option == MATCH_OPTION_INVERT {
+ result = !result
+ }
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Condition": "community",
+ "MatchOption": c.option,
+ "Matched": result,
+ }).Debug("evaluation result")
+ return result
}
-func (c *CommunityCondition) checkMembers(communities []uint32, checkAll bool) bool {
-
- result := false
- if checkAll {
- result = true
+func NewCommunityCondition(c config.MatchCommunitySet, m map[string]DefinedSet) (*CommunityCondition, error) {
+ if c.CommunitySet == "" {
+ return nil, nil
}
-
- makeStr := func(c uint32) string {
- upper := strconv.FormatUint(uint64(c&0xFFFF0000>>16), 10)
- lower := strconv.FormatUint(uint64(c&0x0000FFFF), 10)
- return upper + ":" + lower
+ i, ok := m[c.CommunitySet]
+ if !ok {
+ return nil, fmt.Errorf("not found community set %s", c.CommunitySet)
}
+ s, ok := i.(*CommunitySet)
+ if !ok {
+ return nil, fmt.Errorf("type assert from DefinedSet to *CommunitySet failed")
+ }
+ o, err := NewMatchOption(c.MatchSetOptions)
+ if err != nil {
+ return nil, err
+ }
+ return &CommunityCondition{
+ set: s,
+ option: o,
+ }, nil
+}
- var strCommunities []string = nil
- matched := false
- idx := -1
- for _, member := range c.CommunityList {
- if member.isRegExp {
-
- if strCommunities == nil {
- // create community string.
- strCommunities = make([]string, len(communities))
- for i, c := range communities {
- strCommunities[i] = makeStr(c)
- }
- }
+type ExtCommunityCondition struct {
+ set *ExtCommunitySet
+ option MatchOption
+}
- for i, c := range strCommunities {
- if member.communityRegExp.MatchString(c) {
- matched = true
- idx = i
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "RegExp": member.communityRegExp.String(),
- }).Debug("community regexp used")
- break
- }
- }
+func (c *ExtCommunityCondition) Set() *ExtCommunitySet {
+ return c.set
+}
- } else {
- for i, c := range communities {
- if c == member.community {
- matched = true
- idx = i
- break
- }
- }
- }
+func (c *ExtCommunityCondition) Option() MatchOption {
+ return c.option
+}
- if matched {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Condition": "Community",
- "Community": makeStr(communities[idx]),
- }).Debug("condition matched")
+func (c *ExtCommunityCondition) ToApiStruct() *api.MatchSet {
+ s := c.set.ToApiStruct()
+ s.Option = int32(c.option)
+ return s
+}
- if !checkAll {
+func (c *ExtCommunityCondition) Evaluate(path *Path) bool {
+ es := path.GetExtCommunities()
+ result := false
+ for _, x := range es {
+ result = false
+ typ, subtype := x.GetTypes()
+ // match only with transitive community. see RFC7153
+ if typ >= 0x3f {
+ continue
+ }
+ for idx, y := range c.set.list {
+ if subtype == c.set.subtypeList[idx] && y.MatchString(x.String()) {
result = true
break
}
-
- } else {
- if checkAll {
- result = false
- break
- }
+ }
+ if c.option == MATCH_OPTION_ALL && !result {
+ break
+ }
+ if c.option == MATCH_OPTION_ANY && result {
+ break
}
}
-
- return result
-
-}
-
-// compare community in the message's attribute with
-// the one in the condition.
-func (c *CommunityCondition) evaluate(path *Path) bool {
-
- communities := path.GetCommunities()
-
- if len(communities) == 0 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Condition": "community",
- "MatchOption": c.MatchOption,
- "Matched": false,
- }).Debug("community length is zero")
- return false
- }
-
- result := false
- if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ALL {
- result = c.checkMembers(communities, true)
- } else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ANY {
- result = c.checkMembers(communities, false)
- } else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_INVERT {
- result = !c.checkMembers(communities, false)
+ if c.option == MATCH_OPTION_INVERT {
+ result = !result
}
log.WithFields(log.Fields{
"Topic": "Policy",
"Condition": "community",
- "MatchOption": c.MatchOption,
+ "MatchOption": c.option,
"Matched": result,
- }).Debug("evaluate community")
-
+ }).Debug("evaluation result")
return result
}
-type ExtCommunityCondition struct {
- DefaultCondition
- ExtCommunityList []*ExtCommunityElement
- MatchOption config.MatchSetOptionsType
-}
-
-type ExtCommunityElement struct {
- ecType bgp.ExtendedCommunityAttrType
- ecSubType bgp.ExtendedCommunityAttrSubType
- globalAdmin interface{}
- localAdmin uint32
- comStr string
- isRegExp bool
- regExp *regexp.Regexp
-}
-
-func NewExtCommunityCondition(matchSet config.MatchExtCommunitySet, defExtComSetList []config.ExtCommunitySet) *ExtCommunityCondition {
-
- extComSetName := matchSet.ExtCommunitySet
- option := matchSet.MatchSetOptions
-
- extCommunityElemList := make([]*ExtCommunityElement, 0)
- for _, extComSet := range defExtComSetList {
- if extComSet.ExtCommunitySetName == extComSetName {
- for _, ecommunity := range extComSet.ExtCommunityList {
- matchAll := false
- ec := ecommunity.ExtCommunity
- e := &ExtCommunityElement{
- isRegExp: false,
- comStr: ec,
- }
- matchType, val := getECommunitySubType(ec)
- if !matchType {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Extended Community Condition",
- }).Error("failed to parse the sub type %s.", ec)
- return nil
- }
- switch val[1] {
- case "RT":
- e.ecSubType = bgp.EC_SUBTYPE_ROUTE_TARGET
- case "SoO":
- e.ecSubType = bgp.EC_SUBTYPE_ROUTE_ORIGIN
- default:
- e.ecSubType = bgp.ExtendedCommunityAttrSubType(0xFF)
- }
-
- if matchVal, elem := getECommunityValue(val[2]); matchVal {
- if matchElem, ecType, gAdmin := getECommunityElem(elem[1]); matchElem {
- e.ecType = ecType
- e.globalAdmin = gAdmin
- lAdmin, err := strconv.ParseUint(elem[2], 10, 32)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Extended Community Condition",
- }).Errorf("failed to parse the local administrator %d.", elem[2])
- return nil
- }
- e.localAdmin = uint32(lAdmin)
- matchAll = true
- }
- }
- if !matchAll {
- e.isRegExp = true
- reg, err := regexp.Compile(ec)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Extended Community Condition",
- }).Errorf("Regular expression can't be compiled %s.", val[2])
- return nil
- }
- e.regExp = reg
- }
- extCommunityElemList = append(extCommunityElemList, e)
- }
- ce := &ExtCommunityCondition{
- ExtCommunityList: extCommunityElemList,
- MatchOption: option,
- }
- return ce
- }
+func NewExtCommunityCondition(c config.MatchExtCommunitySet, m map[string]DefinedSet) (*ExtCommunityCondition, error) {
+ if c.ExtCommunitySet == "" {
+ return nil, nil
}
- return nil
-}
-
-func getECommunitySubType(eComStr string) (bool, []string) {
- regSubType, _ := regexp.Compile("^(RT|SoO):(.*)$")
- if regSubType.MatchString(eComStr) {
- eComVal := regSubType.FindStringSubmatch(eComStr)
- return true, eComVal
+ i, ok := m[c.ExtCommunitySet]
+ if !ok {
+ return nil, fmt.Errorf("not found ext-community set %s", c.ExtCommunitySet)
}
- return false, nil
-}
-
-func getECommunityValue(eComVal string) (bool, []string) {
- regVal, _ := regexp.Compile("^([0-9\\.]+):([0-9]+)$")
- if regVal.MatchString(eComVal) {
- eComElem := regVal.FindStringSubmatch(eComVal)
- return true, eComElem
+ s, ok := i.(*ExtCommunitySet)
+ if !ok {
+ return nil, fmt.Errorf("type assert from DefinedSet to *ExtCommunitySet failed")
}
- return false, nil
+ o, err := NewMatchOption(c.MatchSetOptions)
+ if err != nil {
+ return nil, err
+ }
+ return &ExtCommunityCondition{
+ set: s,
+ option: o,
+ }, nil
}
-func getECommunityElem(gAdmin string) (bool, bgp.ExtendedCommunityAttrType, interface{}) {
- addr := net.ParseIP(gAdmin)
- if addr.To4() != nil {
- return true, bgp.EC_TYPE_TRANSITIVE_IP4_SPECIFIC, addr
- }
- regAs, _ := regexp.Compile("^([0-9]+)$")
- if regAs.MatchString(gAdmin) {
- as, err := strconv.ParseUint(gAdmin, 10, 16)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Extended Community Condition",
- }).Errorf("failed to parse the global administrator %d.", gAdmin)
- }
- return true, bgp.EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC, uint16(as)
- }
- regAs4, _ := regexp.Compile("^([0-9]+).([0-9]+)$")
- if regAs4.MatchString(gAdmin) {
- as4Elem := regAs4.FindStringSubmatch(gAdmin)
- highAs, errHigh := strconv.ParseUint(as4Elem[1], 10, 16)
- lowAs, errLow := strconv.ParseUint(as4Elem[2], 10, 16)
- if errHigh != nil || errLow != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Extended Community Condition",
- }).Errorf("failed to parse the global administrator %d.", gAdmin)
- }
- return true, bgp.EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC, uint32(highAs<<16 | lowAs)
- }
- return false, bgp.ExtendedCommunityAttrType(0xFF), nil
+type AsPathLengthCondition struct {
+ length uint32
+ operator AttributeComparison
}
-func (c *ExtCommunityCondition) checkMembers(eCommunities []bgp.ExtendedCommunityInterface, checkAll bool) bool {
+// compare AS_PATH length in the message's AS_PATH attribute with
+// the one in condition.
+func (c *AsPathLengthCondition) Evaluate(path *Path) bool {
+ length := uint32(path.GetAsPathLen())
result := false
- if checkAll {
- result = true
- }
-
- makeAs4Str := func(ec *ExtCommunityElement) string {
- t := ec.ecType
- str := fmt.Sprintf("%d", ec.localAdmin)
- switch t {
- case bgp.EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC:
- str = fmt.Sprintf("%d:%s", ec.globalAdmin.(uint16), str)
- case bgp.EC_TYPE_TRANSITIVE_IP4_SPECIFIC:
- str = fmt.Sprintf("%s:%s", ec.globalAdmin.(net.IP).String(), str)
- case bgp.EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC:
- ga := ec.globalAdmin.(uint32)
- upper := strconv.FormatUint(uint64(ga&0xFFFF0000>>16), 10)
- lower := strconv.FormatUint(uint64(ga&0x0000FFFF), 10)
- str = fmt.Sprintf("%s.%s:%s", upper, lower, str)
- }
- return str
+ switch c.operator {
+ case ATTRIBUTE_EQ:
+ result = c.length == length
+ case ATTRIBUTE_GE:
+ result = c.length <= length
+ case ATTRIBUTE_LE:
+ result = c.length >= length
}
- makeTypeSubStr := func(st bgp.ExtendedCommunityAttrSubType) string {
- subStr := ""
- switch st {
- case bgp.EC_SUBTYPE_ROUTE_TARGET:
- subStr = "RT"
- case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
- subStr = "SoO"
- }
- return subStr
- }
-
- matched := false
- matchStr := ""
- for _, member := range c.ExtCommunityList {
- for _, ec := range eCommunities {
- t, st := ec.GetTypes()
- if member.isRegExp {
- ecString := fmt.Sprintf("%s:%s", makeTypeSubStr(st), ec.String())
- if member.regExp.MatchString(ecString) {
- matched = true
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "RegExp": member.regExp.String(),
- }).Debug("extended community regexp used")
- matchStr = ec.String()
- break
- }
- } else if member.ecType == t && member.ecSubType == st {
- if makeAs4Str(member) == ec.String() {
- matched = true
- matchStr = ec.String()
- break
- }
-
- }
- }
- if matched {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Condition": "Extended Community",
- "Extended Community": matchStr,
- }).Debug("condition matched")
-
- if !checkAll {
- result = true
- break
- }
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Condition": "aspath length",
+ "Reason": c.operator,
+ "Matched": result,
+ }).Debug("evaluation result")
- } else {
- if checkAll {
- result = false
- break
- }
- }
- }
return result
}
-// compare extended community in the message's attribute with
-// the one in the condition.
-func (c *ExtCommunityCondition) evaluate(path *Path) bool {
-
- eCommunities := path.GetExtCommunities()
- if len(eCommunities) == 0 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Condition": "extended community",
- "Matched": false,
- "Path": path,
- }).Debug("extended community length is zero")
- return false
+func (c *AsPathLengthCondition) ToApiStruct() *api.AsPathLength {
+ return &api.AsPathLength{
+ Length: c.length,
+ Type: int32(c.operator),
}
+}
- result := false
- if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ALL {
- result = c.checkMembers(eCommunities, true)
- } else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ANY {
- result = c.checkMembers(eCommunities, false)
- } else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_INVERT {
- result = !c.checkMembers(eCommunities, false)
+func NewAsPathLengthCondition(c config.AsPathLength) (*AsPathLengthCondition, error) {
+ if c.Value == 0 && c.Operator == "" {
+ return nil, nil
}
-
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Condition": "extended community",
- "MatchOption": c.MatchOption,
- "Matched": result,
- "Path": path,
- }).Debug("evaluate extended community")
-
- return result
+ var op AttributeComparison
+ switch strings.ToLower(c.Operator) {
+ case "eq":
+ op = ATTRIBUTE_EQ
+ case "ge":
+ op = ATTRIBUTE_GE
+ case "le":
+ op = ATTRIBUTE_LE
+ default:
+ return nil, fmt.Errorf("invalid as path length operator: %s", c.Operator)
+ }
+ return &AsPathLengthCondition{
+ length: c.Value,
+ operator: op,
+ }, nil
}
-type RPKIValidationCondition struct {
+type RpkiValidationCondition struct {
result config.RpkiValidationResultType
}
-func NewRPKIValidationCondition(result config.RpkiValidationResultType) *RPKIValidationCondition {
- return &RPKIValidationCondition{
- result: result,
- }
+func (c *RpkiValidationCondition) Evaluate(path *Path) bool {
+ return c.result == path.Validation
}
-func (c *RPKIValidationCondition) evaluate(path *Path) bool {
- return c.result == path.Validation
+func NewRpkiValidationCondition(c config.RpkiValidationResultType) (*RpkiValidationCondition, error) {
+ if c == config.RPKI_VALIDATION_RESULT_TYPE_NONE {
+ return nil, nil
+ }
+ return &RpkiValidationCondition{
+ result: c,
+ }, nil
}
type Action interface {
- apply(*Path) *Path
+ Apply(*Path) *Path
}
type RoutingAction struct {
AcceptRoute bool
}
-func NewRoutingAction(action config.Actions) *RoutingAction {
- return &RoutingAction{
- AcceptRoute: action.RouteDisposition.AcceptRoute,
- }
-}
-
-func (r *RoutingAction) apply(path *Path) *Path {
- if r.AcceptRoute {
+func (a *RoutingAction) Apply(path *Path) *Path {
+ if a.AcceptRoute {
return path
}
return nil
}
-type CommunityAction struct {
- Values []uint32
- ext []byte
- action config.BgpSetCommunityOptionType
- RegexpValues []*regexp.Regexp
-}
-
-const (
- COMMUNITY_ACTION_ADD string = "ADD"
- COMMUNITY_ACTION_REPLACE = "REPLACE"
- COMMUNITY_ACTION_REMOVE = "REMOVE"
- COMMUNITY_ACTION_NULL = "NULL"
-)
-
-// NewCommunityAction creates CommunityAction object.
-// If it cannot parse community string, then return nil.
-// Similarly, if option string is invalid, return nil.
-func NewCommunityAction(action config.SetCommunity) *CommunityAction {
-
- m := &CommunityAction{}
- communities := action.SetCommunityMethod.Communities
- if len(communities) == 0 && action.Options != COMMUNITY_ACTION_REPLACE {
- return nil
+func (a *RoutingAction) ToApiStruct() api.RouteAction {
+ if a.AcceptRoute {
+ return api.RouteAction_ACCEPT
+ } else {
+ return api.RouteAction_REJECT
}
+}
- values := make([]uint32, 0, len(communities))
- regexpValues := make([]*regexp.Regexp, 0, len(communities))
-
- for _, com := range communities {
- matched, value := getCommunityValue(com)
- if matched {
- values = append(values, value)
- continue
- }
-
- exp, err := regexp.Compile(com)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Community Action",
- }).Errorf("community string invalid")
- return nil
- }
- regexpValues = append(regexpValues, exp)
+func NewRoutingAction(c config.RouteDisposition) (*RoutingAction, error) {
+ if c.AcceptRoute == c.RejectRoute && c.AcceptRoute {
+ return nil, fmt.Errorf("invalid route disposition")
}
- if len(values) > 0 {
- m.Values = values
- }
- if len(regexpValues) > 0 {
- if action.Options != COMMUNITY_ACTION_REMOVE {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Community Action",
- }).Error("regexp values can only be used for remove action")
- return nil
- }
- m.RegexpValues = regexpValues
+ accept := false
+ if c.AcceptRoute && !c.RejectRoute {
+ accept = true
}
+ return &RoutingAction{
+ AcceptRoute: accept,
+ }, nil
+}
- switch action.Options {
- case COMMUNITY_ACTION_ADD:
- m.action = config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD
- case COMMUNITY_ACTION_REMOVE:
- m.action = config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE
- case COMMUNITY_ACTION_REPLACE:
- m.action = config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE
- default:
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Community Action",
- }).Error("action string should be ADD or REMOVE or REPLACE or NULL.")
- return nil
- }
- return m
+type CommunityAction struct {
+ action config.BgpSetCommunityOptionType
+ list []uint32
+ removeList []*regexp.Regexp
}
func RegexpRemoveCommunities(path *Path, exps []*regexp.Regexp) {
@@ -1136,150 +1003,198 @@ func RegexpRemoveCommunities(path *Path, exps []*regexp.Regexp) {
path.SetCommunities(newComms, true)
}
-func (a *CommunityAction) apply(path *Path) *Path {
- if len(a.ext) > 0 {
- return a.extApply(path)
+func RegexpRemoveExtCommunities(path *Path, exps []*regexp.Regexp, subtypes []bgp.ExtendedCommunityAttrSubType) {
+ comms := path.GetExtCommunities()
+ newComms := make([]bgp.ExtendedCommunityInterface, 0, len(comms))
+ for _, comm := range comms {
+ match := false
+ typ, subtype := comm.GetTypes()
+ // match only with transitive community. see RFC7153
+ if typ >= 0x3f {
+ continue
+ }
+ for idx, exp := range exps {
+ if subtype == subtypes[idx] && exp.MatchString(comm.String()) {
+ match = true
+ break
+ }
+ }
+ if match == false {
+ newComms = append(newComms, comm)
+ }
}
- list := a.Values
+ path.SetExtCommunities(newComms, true)
+}
+
+func (a *CommunityAction) Apply(path *Path) *Path {
switch a.action {
case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
- path.SetCommunities(list, false)
+ path.SetCommunities(a.list, false)
case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
- path.RemoveCommunities(list)
- if len(a.RegexpValues) > 0 {
- RegexpRemoveCommunities(path, a.RegexpValues)
- }
+ RegexpRemoveCommunities(path, a.removeList)
case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
- path.SetCommunities(list, true)
+ path.SetCommunities(a.list, true)
}
-
log.WithFields(log.Fields{
"Topic": "Policy",
"Action": "community",
- "Values": list,
+ "Values": a.list,
"Method": a.action,
}).Debug("community action applied")
-
- return path
-}
-
-func (a *CommunityAction) extApply(path *Path) *Path {
- path.SetExtCommunities(a.ext, false)
-
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Action": "extended community",
- "Values": a.ext,
- "Method": a.action,
- }).Debug("extended community action applied")
-
return path
}
-func NewExtCommunityAction(action config.SetExtCommunity) *CommunityAction {
- communities := action.SetExtCommunityMethod.Communities
- if len(communities) == 0 {
- return nil
+func (a *CommunityAction) ToApiStruct() *api.CommunityAction {
+ cs := make([]string, 0, len(a.list)+len(a.removeList))
+ for _, comm := range a.list {
+ c := fmt.Sprintf("%d:%d", comm>>16, comm&0x0000ffff)
+ cs = append(cs, c)
}
+ for _, exp := range a.removeList {
+ cs = append(cs, exp.String())
+ }
+ return &api.CommunityAction{
+ Communities: cs,
+ Option: int32(a.action),
+ }
+}
- b := make([]byte, len(communities)*8)
- for i, c := range communities {
- l := strings.Split(c, ":")
- if len(l) != 8 {
- goto E
+func NewCommunityAction(c config.SetCommunity) (*CommunityAction, error) {
+ a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
+ if !ok {
+ if len(c.SetCommunityMethod.Communities) == 0 {
+ return nil, nil
}
- for j, v := range l {
- v, err := strconv.ParseInt(v, 0, 32)
+ return nil, fmt.Errorf("invalid option name: %s", c.Options)
+ }
+ var list []uint32
+ var removeList []*regexp.Regexp
+ if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
+ removeList = make([]*regexp.Regexp, 0, len(c.SetCommunityMethod.Communities))
+ } else {
+ list = make([]uint32, 0, len(c.SetCommunityMethod.Communities))
+ }
+ for _, x := range c.SetCommunityMethod.Communities {
+ if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
+ exp, err := parseCommunityRegexp(x)
if err != nil {
- goto E
+ return nil, err
}
- b[j+i*8] = uint8(v)
+ removeList = append(removeList, exp)
+ } else {
+ comm, err := ParseCommunity(x)
+ if err != nil {
+ return nil, err
+ }
+ list = append(list, comm)
}
}
return &CommunityAction{
- ext: b,
- }
-E:
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Action": "ExtCommunity",
- "Values": communities,
- }).Error("invalid extended community action")
- return nil
+ action: a,
+ list: list,
+ removeList: removeList,
+ }, nil
}
-type ActionType int
-
-type MedAction struct {
- Value int64
- action ActionType
+type ExtCommunityAction struct {
+ action config.BgpSetCommunityOptionType
+ list []bgp.ExtendedCommunityInterface
+ removeList []*regexp.Regexp
+ subtypeList []bgp.ExtendedCommunityAttrSubType
}
-const (
- MED_ACTION_NONE ActionType = iota
- MED_ACTION_REPLACE
- MED_ACTION_ADD
- MED_ACTION_SUB
-)
-
-// NewMedAction creates MedAction object.
-// If it cannot parse med string, then return nil.
-func NewMedAction(med config.BgpSetMedType) *MedAction {
-
- if med == "" {
- return nil
+func (a *ExtCommunityAction) Apply(path *Path) *Path {
+ switch a.action {
+ case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
+ path.SetExtCommunities(a.list, false)
+ case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
+ RegexpRemoveExtCommunities(path, a.removeList, a.subtypeList)
+ case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
+ path.SetExtCommunities(a.list, true)
}
+ return path
+}
- m := &MedAction{}
+func (a *ExtCommunityAction) ToApiStruct() *api.CommunityAction {
+ cs := make([]string, 0, len(a.list)+len(a.removeList))
+ f := func(idx int, arg string) string {
+ switch a.subtypeList[idx] {
+ case bgp.EC_SUBTYPE_ROUTE_TARGET:
+ return fmt.Sprintf("rt:%s", arg)
+ case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
+ return fmt.Sprintf("soo:%s", arg)
+ default:
+ return fmt.Sprintf("%d:%s", a.subtypeList[idx])
+ }
+ }
+ for idx, c := range a.list {
+ cs = append(cs, f(idx, c.String()))
+ }
+ for idx, exp := range a.removeList {
+ cs = append(cs, f(idx, exp.String()))
+ }
+ return &api.CommunityAction{
+ Communities: cs,
+ Option: int32(a.action),
+ }
+}
- matched, value, action := getMedValue(fmt.Sprintf("%s", med))
- if !matched {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Med Action",
- }).Error("med string invalid.")
- return nil
- }
- m.Value = value
- m.action = action
- return m
-}
-
-// getMedValue returns uint32 med value and action type (+ or -).
-// if the string doesn't match a number or operator,
-// it returns false and 0.
-func getMedValue(medStr string) (bool, int64, ActionType) {
- regMed, _ := regexp.Compile("^(\\+|\\-)?([0-9]+)$")
- if regMed.MatchString(medStr) {
- group := regMed.FindStringSubmatch(medStr)
- action := MED_ACTION_REPLACE
- if group[1] == "+" {
- action = MED_ACTION_ADD
- } else if group[1] == "-" {
- action = MED_ACTION_SUB
+func NewExtCommunityAction(c config.SetExtCommunity) (*ExtCommunityAction, error) {
+ a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
+ if !ok {
+ if len(c.SetExtCommunityMethod.Communities) == 0 {
+ return nil, nil
}
- val, err := strconv.ParseInt(medStr, 10, 64)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Med Action",
- }).Error("failed to parser as number or med value.")
+ return nil, fmt.Errorf("invalid option name: %s", c.Options)
+ }
+ var list []bgp.ExtendedCommunityInterface
+ var removeList []*regexp.Regexp
+ subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.SetExtCommunityMethod.Communities))
+ if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
+ removeList = make([]*regexp.Regexp, 0, len(c.SetExtCommunityMethod.Communities))
+ } else {
+ list = make([]bgp.ExtendedCommunityInterface, 0, len(c.SetExtCommunityMethod.Communities))
+ }
+ for _, x := range c.SetExtCommunityMethod.Communities {
+ if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
+ subtype, exp, err := parseExtCommunityRegexp(x)
+ if err != nil {
+ return nil, err
+ }
+ removeList = append(removeList, exp)
+ subtypeList = append(subtypeList, subtype)
+ } else {
+ comm, err := parseExtCommunity(x)
+ if err != nil {
+ return nil, err
+ }
+ list = append(list, comm)
+ _, subtype := comm.GetTypes()
+ subtypeList = append(subtypeList, subtype)
}
- return true, int64(val), action
}
- return false, int64(0), MED_ACTION_NONE
+ return &ExtCommunityAction{
+ action: a,
+ list: list,
+ removeList: removeList,
+ subtypeList: subtypeList,
+ }, nil
}
-func (a *MedAction) apply(path *Path) *Path {
+type MedAction struct {
+ value int
+ action MedActionType
+}
+
+func (a *MedAction) Apply(path *Path) *Path {
var err error
switch a.action {
+ case MED_ACTION_MOD:
+ err = path.SetMed(int64(a.value), false)
case MED_ACTION_REPLACE:
- err = path.SetMed(a.Value, true)
- case MED_ACTION_ADD:
- err = path.SetMed(a.Value, false)
- case MED_ACTION_SUB:
- err = path.SetMed(a.Value, false)
+ err = path.SetMed(int64(a.value), true)
}
+
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
@@ -1289,7 +1204,7 @@ func (a *MedAction) apply(path *Path) *Path {
log.WithFields(log.Fields{
"Topic": "Policy",
"Action": "med",
- "Value": a.Value,
+ "Value": a.value,
"ActionType": a.action,
}).Debug("med action applied")
}
@@ -1297,43 +1212,41 @@ func (a *MedAction) apply(path *Path) *Path {
return path
}
-type AsPathPrependAction struct {
- asn uint32
- useLeftMost bool
- repeat uint8
+func (a *MedAction) ToApiStruct() *api.MedAction {
+ return &api.MedAction{
+ Type: int32(a.action),
+ Value: int64(a.value),
+ }
}
-// NewAsPathPrependAction creates AsPathPrependAction object.
-// If ASN cannot be parsed, nil will be returned.
-func NewAsPathPrependAction(action config.SetAsPathPrepend) *AsPathPrependAction {
-
- a := &AsPathPrependAction{}
-
- if action.As == "" {
- return nil
+func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
+ if string(c) == "" {
+ return nil, nil
}
-
- if action.As == "last-as" {
- a.useLeftMost = true
- } else {
- asn, err := strconv.ParseUint(action.As, 10, 32)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "AsPathPrepend Action",
- "Value": action.As,
- }).Error("As number string invalid.")
- return nil
- }
- a.asn = uint32(asn)
+ exp := regexp.MustCompile("^(\\+|\\-)?(\\d+)$")
+ elems := exp.FindStringSubmatch(string(c))
+ if len(elems) != 3 {
+ return nil, fmt.Errorf("invalid med action format")
}
- a.repeat = action.RepeatN
-
- return a
+ action := MED_ACTION_REPLACE
+ switch elems[1] {
+ case "+", "-":
+ action = MED_ACTION_MOD
+ }
+ value, _ := strconv.Atoi(string(c))
+ return &MedAction{
+ value: value,
+ action: action,
+ }, nil
}
-func (a *AsPathPrependAction) apply(path *Path) *Path {
+type AsPathPrependAction struct {
+ asn uint32
+ useLeftMost bool
+ repeat uint8
+}
+func (a *AsPathPrependAction) Apply(path *Path) *Path {
var asn uint32
if a.useLeftMost {
asns := path.GetAsSeqList()
@@ -1341,7 +1254,7 @@ func (a *AsPathPrependAction) apply(path *Path) *Path {
log.WithFields(log.Fields{
"Topic": "Policy",
"Type": "AsPathPrepend Action",
- }).Error("aspath length is zero.")
+ }).Errorf("aspath length is zero.")
return path
}
asn = asns[0]
@@ -1367,680 +1280,324 @@ func (a *AsPathPrependAction) apply(path *Path) *Path {
return path
}
-type Prefix struct {
- Prefix *net.IPNet
- AddressFamily bgp.RouteFamily
- MasklengthRangeMax uint8
- MasklengthRangeMin uint8
-}
-
-func NewPrefix(prefixStr string, maskRange string) (Prefix, error) {
- p := Prefix{}
- addr, ipPref, e := net.ParseCIDR(prefixStr)
- if e != nil {
- return p, e
+func (a *AsPathPrependAction) ToApiStruct() *api.AsPrependAction {
+ return &api.AsPrependAction{
+ Asn: a.asn,
+ Repeat: uint32(a.repeat),
+ UseLeftMost: a.useLeftMost,
}
-
- if ipv4Family := addr.To4(); ipv4Family != nil {
- p.AddressFamily, _ = bgp.GetRouteFamily("ipv4-unicast")
- } else if ipv6Family := addr.To16(); ipv6Family != nil {
- p.AddressFamily, _ = bgp.GetRouteFamily("ipv6-unicast")
- } else {
- return p, fmt.Errorf("can not determine the address family.")
- }
-
- p.Prefix = ipPref
-
- if maskRange == "" {
- l, _ := ipPref.Mask.Size()
- maskLength := uint8(l)
- p.MasklengthRangeMax = maskLength
- p.MasklengthRangeMin = maskLength
- } else {
- exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)")
- elems := exp.FindStringSubmatch(maskRange)
- if len(elems) != 3 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Prefix",
- "MaskRangeFormat": maskRange,
- }).Warn("mask length range format is invalid.")
- return p, fmt.Errorf("mask length range format is invalid")
- }
- // we've already checked the range is sane by regexp
- min, _ := strconv.Atoi(elems[1])
- max, _ := strconv.Atoi(elems[2])
- p.MasklengthRangeMin = uint8(min)
- p.MasklengthRangeMax = uint8(max)
- }
- return p, nil
-}
-
-// Compare path with a policy's condition in stored order in the policy.
-// If a condition match, then this function stops evaluation and
-// subsequent conditions are skipped.
-func (p *Policy) Apply(path *Path) (RouteType, *Path) {
- for _, statement := range p.Statements {
-
- result := statement.evaluate(path)
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Path": path,
- "PolicyName": p.Name,
- }).Debug("statement evaluate : ", result)
-
- if result {
- //Routing action
- p := statement.routingAction.apply(path)
- if p == nil {
- return ROUTE_TYPE_REJECT, path
- }
- if len(statement.modificationActions) == 0 {
- return ROUTE_TYPE_ACCEPT, path
- }
- // apply all modification actions
- cloned := path.Clone(p.Owner, p.IsWithdraw)
- for _, action := range statement.modificationActions {
- cloned = action.apply(cloned)
- }
- return ROUTE_TYPE_ACCEPT, cloned
- }
- }
- return ROUTE_TYPE_NONE, path
-}
-
-func ipPrefixCalculate(path *Path, cPrefix Prefix) bool {
- rf := path.GetRouteFamily()
- log.Debug("path routefamily : ", rf.String())
- var pAddr net.IP
- var pMasklen uint8
-
- if rf != cPrefix.AddressFamily {
- return false
- }
-
- switch rf {
- case bgp.RF_IPv4_UC:
- pAddr = path.GetNlri().(*bgp.IPAddrPrefix).Prefix
- pMasklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
- case bgp.RF_IPv6_UC:
- pAddr = path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix
- pMasklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
- default:
- return false
- }
-
- return (cPrefix.MasklengthRangeMin <= pMasklen && pMasklen <= cPrefix.MasklengthRangeMax) && cPrefix.Prefix.Contains(pAddr)
-}
-
-const (
- OPTIONS_ANY string = "ANY"
- OPTIONS_ALL = "ALL"
- OPTIONS_INVERT = "INVERT"
-)
-
-func MatchSetOptionToString(option config.MatchSetOptionsType) string {
- op := OPTIONS_ANY
- switch option {
- case config.MATCH_SET_OPTIONS_TYPE_ALL:
- op = OPTIONS_ALL
- case config.MATCH_SET_OPTIONS_TYPE_INVERT:
- op = OPTIONS_INVERT
- }
- return op
-}
-
-func MatchSetOptionsRestrictedToString(option config.MatchSetOptionsRestrictedType) string {
- op := OPTIONS_ANY
- if option == config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT {
- op = OPTIONS_INVERT
- }
- return op
-}
-
-func MatchSetOptionsToType(option string) config.MatchSetOptionsType {
- op := config.MATCH_SET_OPTIONS_TYPE_ANY
- switch option {
- case OPTIONS_ALL:
- op = config.MATCH_SET_OPTIONS_TYPE_ALL
- case OPTIONS_INVERT:
- op = config.MATCH_SET_OPTIONS_TYPE_INVERT
- }
- return op
-}
-
-func MatchSetOptionsRestrictedToType(option string) config.MatchSetOptionsRestrictedType {
- op := config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY
- if option == OPTIONS_INVERT {
- op = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT
- }
- return op
-}
-
-// find index PrefixSet of request from PrefixSet of configuration file.
-// Return the idxPrefixSet of the location where the name of PrefixSet matches,
-// and idxPrefix of the location where element of PrefixSet matches
-func IndexOfPrefixSet(conPrefixSetList []config.PrefixSet, reqPrefixSet config.PrefixSet) (int, int) {
- idxPrefixSet := -1
- idxPrefix := -1
- for i, conPrefixSet := range conPrefixSetList {
- if conPrefixSet.PrefixSetName == reqPrefixSet.PrefixSetName {
- idxPrefixSet = i
- if reqPrefixSet.PrefixList == nil {
- return idxPrefixSet, idxPrefix
- }
- for j, conPrefix := range conPrefixSet.PrefixList {
- if reflect.DeepEqual(conPrefix.IpPrefix, reqPrefixSet.PrefixList[0].IpPrefix) &&
- conPrefix.MasklengthRange == reqPrefixSet.PrefixList[0].MasklengthRange {
- idxPrefix = j
- return idxPrefixSet, idxPrefix
- }
- }
- }
- }
- return idxPrefixSet, idxPrefix
}
-// find index NeighborSet of request from NeighborSet of configuration file.
-// Return the idxNeighborSet of the location where the name of NeighborSet matches,
-// and idxNeighbor of the location where element of NeighborSet matches
-func IndexOfNeighborSet(conNeighborSetList []config.NeighborSet, reqNeighborSet config.NeighborSet) (int, int) {
- idxNeighborSet := -1
- idxNeighbor := -1
- for i, conNeighborSet := range conNeighborSetList {
- if conNeighborSet.NeighborSetName == reqNeighborSet.NeighborSetName {
- idxNeighborSet = i
- if reqNeighborSet.NeighborInfoList == nil {
- return idxNeighborSet, idxNeighbor
- }
- for j, conNeighbor := range conNeighborSet.NeighborInfoList {
- if reflect.DeepEqual(conNeighbor.Address, reqNeighborSet.NeighborInfoList[0].Address) {
- idxNeighbor = j
- return idxNeighborSet, idxNeighbor
- }
- }
- }
+// NewAsPathPrependAction creates AsPathPrependAction object.
+// If ASN cannot be parsed, nil will be returned.
+func NewAsPathPrependAction(action config.SetAsPathPrepend) (*AsPathPrependAction, error) {
+ a := &AsPathPrependAction{
+ repeat: action.RepeatN,
}
- return idxNeighborSet, idxNeighbor
-}
-
-// find index AsPathSet of request from AsPathSet of configuration file.
-// Return the idxAsPathSet of the location where the name of AsPathSet matches,
-// and idxAsPath of the location where element of AsPathSet matches
-func IndexOfAsPathSet(conAsPathSetList []config.AsPathSet, reqAsPathSet config.AsPathSet) (int, int) {
- idxAsPathSet := -1
- idxAsPath := -1
- for i, conAsPathSet := range conAsPathSetList {
- if conAsPathSet.AsPathSetName == reqAsPathSet.AsPathSetName {
- idxAsPathSet = i
- if len(reqAsPathSet.AsPathList) == 0 {
- return idxAsPathSet, idxAsPath
- }
- for j, conAsPath := range conAsPathSet.AsPathList {
- if conAsPath == reqAsPathSet.AsPathList[0] {
- idxAsPath = j
- return idxAsPathSet, idxAsPath
- }
- }
+ switch action.As {
+ case "":
+ if a.repeat == 0 {
+ return nil, nil
}
- }
- return idxAsPathSet, idxAsPath
-}
-
-// find index CommunitySet of request from CommunitySet of configuration file.
-// Return the idxCommunitySet of the location where the name of CommunitySet matches,
-// and idxCommunity of the location where element of CommunitySet matches
-func IndexOfCommunitySet(conCommunitySetList []config.CommunitySet, reqCommunitySet config.CommunitySet) (int, int) {
- idxCommunitySet := -1
- idxCommunity := -1
- for i, conCommunitySet := range conCommunitySetList {
- if conCommunitySet.CommunitySetName == reqCommunitySet.CommunitySetName {
- idxCommunitySet = i
- if len(reqCommunitySet.CommunityList) == 0 {
- return idxCommunitySet, idxCommunity
- }
- for j, conCommunity := range conCommunitySet.CommunityList {
- if conCommunity == reqCommunitySet.CommunityList[0] {
- idxCommunity = j
- return idxCommunitySet, idxCommunity
- }
- }
+ return nil, fmt.Errorf("specify as to prepend")
+ case "last-as":
+ a.useLeftMost = true
+ default:
+ asn, err := strconv.Atoi(action.As)
+ if err != nil {
+ return nil, fmt.Errorf("As number string invalid")
}
+ a.asn = uint32(asn)
}
- return idxCommunitySet, idxCommunity
+ return a, nil
}
-// find index ExtCommunitySet of request from ExtCommunitySet of configuration file.
-// Return the idxExtCommunitySet of the location where the name of ExtCommunitySet matches,
-// and idxExtCommunity of the location where element of ExtCommunitySet matches
-func IndexOfExtCommunitySet(conExtCommunitySetList []config.ExtCommunitySet, reqExtCommunitySet config.ExtCommunitySet) (int, int) {
- idxExtCommunitySet := -1
- idxExtCommunity := -1
- for i, conExtCommunitySet := range conExtCommunitySetList {
- if conExtCommunitySet.ExtCommunitySetName == reqExtCommunitySet.ExtCommunitySetName {
- idxExtCommunitySet = i
- if len(reqExtCommunitySet.ExtCommunityList) == 0 {
- return idxExtCommunitySet, idxExtCommunity
- }
- for j, conExtCommunity := range conExtCommunitySet.ExtCommunityList {
- if conExtCommunity == reqExtCommunitySet.ExtCommunityList[0] {
- idxExtCommunity = j
- return idxExtCommunitySet, idxExtCommunity
- }
- }
- }
- }
- return idxExtCommunitySet, idxExtCommunity
+type Statement struct {
+ Name string
+ Conditions []Condition
+ RouteAction Action
+ ModActions []Action
}
-// find index PolicyDefinition of request from PolicyDefinition of configuration file.
-// Return the idxPolicyDefinition of the location where the name of PolicyDefinition matches,
-// and idxStatement of the location where Statement of PolicyDefinition matches
-func IndexOfPolicyDefinition(conPolicyList []config.PolicyDefinition, reqPolicy config.PolicyDefinition) (int, int) {
- idxPolicyDefinition := -1
- idxStatement := -1
- for i, conPolicy := range conPolicyList {
- if conPolicy.Name == reqPolicy.Name {
- idxPolicyDefinition = i
- if reqPolicy.Statements.StatementList == nil {
- return idxPolicyDefinition, idxStatement
- }
- for j, conStatement := range conPolicy.Statements.StatementList {
- if conStatement.Name == reqPolicy.Statements.StatementList[0].Name {
- idxStatement = j
- return idxPolicyDefinition, idxStatement
- }
- }
+// evaluate each condition in the statement according to MatchSetOptions
+func (s *Statement) Evaluate(p *Path) bool {
+ for _, c := range s.Conditions {
+ fmt.Printf("%v, %t\n", c, c)
+ if !c.Evaluate(p) {
+ return false
}
}
- return idxPolicyDefinition, idxStatement
+ return true
}
-func PrefixSetToApiStruct(ps config.PrefixSet) *gobgpapi.PrefixSet {
- resPrefixList := make([]*gobgpapi.Prefix, 0)
- for _, p := range ps.PrefixList {
- resPrefix := &gobgpapi.Prefix{
- IpPrefix: p.IpPrefix,
- MaskLengthRange: p.MasklengthRange,
- }
- resPrefixList = append(resPrefixList, resPrefix)
- }
- resPrefixSet := &gobgpapi.PrefixSet{
- PrefixSetName: ps.PrefixSetName,
- PrefixList: resPrefixList,
+func (s *Statement) Apply(path *Path) (RouteType, *Path) {
+ result := s.Evaluate(path)
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Path": path,
+ "PolicyName": s.Name,
+ }).Debug("statement evaluate : ", result)
+ if result {
+ //Routing action
+ p := s.RouteAction.Apply(path)
+ if p == nil {
+ return ROUTE_TYPE_REJECT, path
+ }
+ if len(s.ModActions) == 0 {
+ return ROUTE_TYPE_ACCEPT, path
+ }
+ // apply all modification actions
+ cloned := path.Clone(p.Owner, p.IsWithdraw)
+ for _, action := range s.ModActions {
+ cloned = action.Apply(cloned)
+ }
+ return ROUTE_TYPE_ACCEPT, cloned
}
-
- return resPrefixSet
+ return ROUTE_TYPE_NONE, path
}
-func PrefixSetToConfigStruct(reqPrefixSet *gobgpapi.PrefixSet) (bool, config.PrefixSet) {
- var prefix config.Prefix
- var prefixSet config.PrefixSet
- isReqPrefixSet := true
- if reqPrefixSet.PrefixList != nil {
- prefix = config.Prefix{
- IpPrefix: reqPrefixSet.PrefixList[0].IpPrefix,
- MasklengthRange: reqPrefixSet.PrefixList[0].MaskLengthRange,
- }
- prefixList := []config.Prefix{prefix}
-
- prefixSet = config.PrefixSet{
- PrefixSetName: reqPrefixSet.PrefixSetName,
- PrefixList: prefixList,
- }
- } else {
- isReqPrefixSet = false
- prefixSet = config.PrefixSet{
- PrefixSetName: reqPrefixSet.PrefixSetName,
- PrefixList: nil,
+func (s *Statement) ToApiStruct() *api.Statement {
+ cs := &api.Conditions{}
+ for _, c := range s.Conditions {
+ switch c.(type) {
+ case *PrefixCondition:
+ cs.PrefixSet = c.(*PrefixCondition).ToApiStruct()
+ case *NeighborCondition:
+ cs.NeighborSet = c.(*NeighborCondition).ToApiStruct()
+ case *AsPathLengthCondition:
+ cs.AsPathLength = c.(*AsPathLengthCondition).ToApiStruct()
+ case *AsPathCondition:
+ cs.AsPathSet = c.(*AsPathCondition).ToApiStruct()
+ case *CommunityCondition:
+ cs.CommunitySet = c.(*CommunityCondition).ToApiStruct()
+ case *ExtCommunityCondition:
+ cs.ExtCommunitySet = c.(*ExtCommunityCondition).ToApiStruct()
+ case *RpkiValidationCondition:
+ cs.RpkiResult = int32(c.(*RpkiValidationCondition).result)
+ }
+ }
+ as := &api.Actions{}
+ as.RouteAction = s.RouteAction.(*RoutingAction).ToApiStruct()
+ for _, a := range s.ModActions {
+ switch a.(type) {
+ case *CommunityAction:
+ as.Community = a.(*CommunityAction).ToApiStruct()
+ case *MedAction:
+ as.Med = a.(*MedAction).ToApiStruct()
+ case *AsPathPrependAction:
+ as.AsPrepend = a.(*AsPathPrependAction).ToApiStruct()
+ case *ExtCommunityAction:
+ as.ExtCommunity = a.(*ExtCommunityAction).ToApiStruct()
+ }
+ }
+ return &api.Statement{
+ Name: s.Name,
+ Conditions: cs,
+ Actions: as,
+ }
+}
+
+func NewStatement(c config.Statement, dmap DefinedSetMap) (*Statement, error) {
+ if c.Name == "" {
+ return nil, fmt.Errorf("empty statement name")
+ }
+ var ra Action
+ var as []Action
+ var cs []Condition
+ var err error
+ cfs := []func() (Condition, error){
+ func() (Condition, error) {
+ return NewPrefixCondition(c.Conditions.MatchPrefixSet, dmap[DEFINED_TYPE_PREFIX])
+ },
+ func() (Condition, error) {
+ return NewNeighborCondition(c.Conditions.MatchNeighborSet, dmap[DEFINED_TYPE_NEIGHBOR])
+ },
+ func() (Condition, error) {
+ return NewAsPathLengthCondition(c.Conditions.BgpConditions.AsPathLength)
+ },
+ func() (Condition, error) {
+ return NewRpkiValidationCondition(c.Conditions.BgpConditions.RpkiValidationResult)
+ },
+ func() (Condition, error) {
+ return NewAsPathCondition(c.Conditions.BgpConditions.MatchAsPathSet, dmap[DEFINED_TYPE_AS_PATH])
+ },
+ func() (Condition, error) {
+ return NewCommunityCondition(c.Conditions.BgpConditions.MatchCommunitySet, dmap[DEFINED_TYPE_COMMUNITY])
+ },
+ func() (Condition, error) {
+ return NewExtCommunityCondition(c.Conditions.BgpConditions.MatchExtCommunitySet, dmap[DEFINED_TYPE_EXT_COMMUNITY])
+ },
+ }
+ cs = make([]Condition, 0, len(cfs))
+ for _, f := range cfs {
+ c, err := f()
+ if err != nil {
+ return nil, err
}
- }
- return isReqPrefixSet, prefixSet
-}
-
-func NeighborSetToApiStruct(ns config.NeighborSet) *gobgpapi.NeighborSet {
- resNeighborList := make([]*gobgpapi.Neighbor, 0)
- for _, n := range ns.NeighborInfoList {
- resNeighbor := &gobgpapi.Neighbor{
- Address: n.Address.String(),
+ if !reflect.ValueOf(c).IsNil() {
+ cs = append(cs, c)
}
- resNeighborList = append(resNeighborList, resNeighbor)
- }
- resNeighborSet := &gobgpapi.NeighborSet{
- NeighborSetName: ns.NeighborSetName,
- NeighborList: resNeighborList,
}
- return resNeighborSet
-}
-
-func NeighborSetToConfigStruct(reqNeighborSet *gobgpapi.NeighborSet) (bool, config.NeighborSet) {
- var neighbor config.NeighborInfo
- var neighborSet config.NeighborSet
- isReqNeighborSet := true
- if reqNeighborSet.NeighborList != nil {
- neighbor = config.NeighborInfo{
- Address: net.ParseIP(reqNeighborSet.NeighborList[0].Address),
- }
- neighborList := []config.NeighborInfo{neighbor}
-
- neighborSet = config.NeighborSet{
- NeighborSetName: reqNeighborSet.NeighborSetName,
- NeighborInfoList: neighborList,
+ ra, err = NewRoutingAction(c.Actions.RouteDisposition)
+ if err != nil {
+ return nil, err
+ }
+ afs := []func() (Action, error){
+ func() (Action, error) {
+ return NewCommunityAction(c.Actions.BgpActions.SetCommunity)
+ },
+ func() (Action, error) {
+ return NewExtCommunityAction(c.Actions.BgpActions.SetExtCommunity)
+ },
+ func() (Action, error) {
+ return NewMedAction(c.Actions.BgpActions.SetMed)
+ },
+ func() (Action, error) {
+ return NewAsPathPrependAction(c.Actions.BgpActions.SetAsPathPrepend)
+ },
+ }
+ as = make([]Action, 0, len(afs))
+ for _, f := range afs {
+ a, err := f()
+ if err != nil {
+ return nil, err
}
- } else {
- isReqNeighborSet = false
- neighborSet = config.NeighborSet{
- NeighborSetName: reqNeighborSet.NeighborSetName,
- NeighborInfoList: nil,
+ if !reflect.ValueOf(a).IsNil() {
+ as = append(as, a)
}
}
- return isReqNeighborSet, neighborSet
-}
-
-func AsPathSetToApiStruct(as config.AsPathSet) *gobgpapi.AsPathSet {
- resAsPathMembers := make([]string, 0)
- for _, a := range as.AsPathList {
- resAsPathMembers = append(resAsPathMembers, a.AsPath)
- }
- resAsPathSet := &gobgpapi.AsPathSet{
- AsPathSetName: as.AsPathSetName,
- AsPathMembers: resAsPathMembers,
- }
- return resAsPathSet
-}
-
-func AsPathSetToConfigStruct(reqAsPathSet *gobgpapi.AsPathSet) (bool, config.AsPathSet) {
- isAsPathSetSet := true
- if len(reqAsPathSet.AsPathMembers) == 0 {
- isAsPathSetSet = false
- }
- asPathList := make([]config.AsPath, 0)
- for _, a := range reqAsPathSet.AsPathMembers {
- asPathList = append(asPathList, config.AsPath{AsPath: a})
- }
- asPathSet := config.AsPathSet{
- AsPathSetName: reqAsPathSet.AsPathSetName,
- AsPathList: asPathList,
- }
- return isAsPathSetSet, asPathSet
-}
-
-func CommunitySetToApiStruct(cs config.CommunitySet) *gobgpapi.CommunitySet {
- resCommunityMembers := make([]string, 0)
- for _, c := range cs.CommunityList {
- resCommunityMembers = append(resCommunityMembers, c.Community)
- }
- resCommunitySet := &gobgpapi.CommunitySet{
- CommunitySetName: cs.CommunitySetName,
- CommunityMembers: resCommunityMembers,
- }
- return resCommunitySet
-}
-
-func CommunitySetToConfigStruct(reqCommunitySet *gobgpapi.CommunitySet) (bool, config.CommunitySet) {
- isCommunitySet := true
- if len(reqCommunitySet.CommunityMembers) == 0 {
- isCommunitySet = false
- }
- communityList := make([]config.Community, 0)
- for _, c := range reqCommunitySet.CommunityMembers {
- communityList = append(communityList, config.Community{Community: c})
- }
- communitySet := config.CommunitySet{
- CommunitySetName: reqCommunitySet.CommunitySetName,
- CommunityList: communityList,
- }
- return isCommunitySet, communitySet
-}
-
-func ExtCommunitySetToApiStruct(es config.ExtCommunitySet) *gobgpapi.ExtCommunitySet {
- resExtCommunityMembers := make([]string, 0)
- for _, ec := range es.ExtCommunityList {
- resExtCommunityMembers = append(resExtCommunityMembers, ec.ExtCommunity)
- }
- resExtCommunitySet := &gobgpapi.ExtCommunitySet{
- ExtCommunitySetName: es.ExtCommunitySetName,
- ExtCommunityMembers: resExtCommunityMembers,
- }
- return resExtCommunitySet
-}
-
-func ExtCommunitySetToConfigStruct(reqExtCommunitySet *gobgpapi.ExtCommunitySet) (bool, config.ExtCommunitySet) {
- isExtCommunitySet := true
- if len(reqExtCommunitySet.ExtCommunityMembers) == 0 {
- isExtCommunitySet = false
- }
- extCommunityList := make([]config.ExtCommunity, 0)
- for _, ec := range reqExtCommunitySet.ExtCommunityMembers {
- extCommunityList = append(extCommunityList, config.ExtCommunity{ExtCommunity: ec})
- }
- ExtCommunitySet := config.ExtCommunitySet{
- ExtCommunitySetName: reqExtCommunitySet.ExtCommunitySetName,
- ExtCommunityList: extCommunityList,
- }
- return isExtCommunitySet, ExtCommunitySet
+ return &Statement{
+ Name: c.Name,
+ Conditions: cs,
+ RouteAction: ra,
+ ModActions: as,
+ }, nil
}
-func AsPathLengthToApiStruct(asPathLength config.AsPathLength) *gobgpapi.AsPathLength {
- value := ""
- if asPathLength.Operator != "" {
- value = fmt.Sprintf("%d", asPathLength.Value)
- }
- resAsPathLength := &gobgpapi.AsPathLength{
- Value: value,
- Operator: asPathLength.Operator,
- }
- return resAsPathLength
+type Policy struct {
+ name string
+ Statements []*Statement
}
-func AsPathLengthToConfigStruct(reqAsPathLength *gobgpapi.AsPathLength) config.AsPathLength {
- operator := reqAsPathLength.Operator
- value := reqAsPathLength.Value
- valueUint, _ := strconv.ParseUint(value, 10, 32)
- asPathLength := config.AsPathLength{
- Operator: operator,
- Value: uint32(valueUint),
- }
- return asPathLength
+func (p *Policy) Name() string {
+ return p.name
}
-func ConditionsToConfigStruct(reqConditions *gobgpapi.Conditions) config.Conditions {
- conditions := config.Conditions{}
- if reqConditions == nil {
- return conditions
- }
- if reqConditions.MatchPrefixSet != nil {
- conditions.MatchPrefixSet.PrefixSet = reqConditions.MatchPrefixSet.PrefixSetName
- conditions.MatchPrefixSet.MatchSetOptions =
- MatchSetOptionsRestrictedToType(reqConditions.MatchPrefixSet.MatchSetOptions)
- }
- if reqConditions.MatchNeighborSet != nil {
- conditions.MatchNeighborSet.NeighborSet = reqConditions.MatchNeighborSet.NeighborSetName
- conditions.MatchNeighborSet.MatchSetOptions =
- MatchSetOptionsRestrictedToType(reqConditions.MatchNeighborSet.MatchSetOptions)
- }
- if reqConditions.MatchAsPathSet != nil {
- conditions.BgpConditions.MatchAsPathSet.AsPathSet = reqConditions.MatchAsPathSet.AsPathSetName
- conditions.BgpConditions.MatchAsPathSet.MatchSetOptions =
- MatchSetOptionsToType(reqConditions.MatchAsPathSet.MatchSetOptions)
- }
- if reqConditions.MatchCommunitySet != nil {
- conditions.BgpConditions.MatchCommunitySet.CommunitySet = reqConditions.MatchCommunitySet.CommunitySetName
- conditions.BgpConditions.MatchCommunitySet.MatchSetOptions =
- MatchSetOptionsToType(reqConditions.MatchCommunitySet.MatchSetOptions)
- }
- if reqConditions.MatchExtCommunitySet != nil {
- conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet = reqConditions.MatchExtCommunitySet.ExtCommunitySetName
- conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions =
- MatchSetOptionsToType(reqConditions.MatchExtCommunitySet.MatchSetOptions)
- }
- if reqConditions.MatchAsPathLength != nil {
- conditions.BgpConditions.AsPathLength =
- AsPathLengthToConfigStruct(reqConditions.MatchAsPathLength)
+// Compare path with a policy's condition in stored order in the policy.
+// If a condition match, then this function stops evaluation and
+// subsequent conditions are skipped.
+func (p *Policy) Apply(path *Path) (RouteType, *Path) {
+ for _, stmt := range p.Statements {
+ result, path := stmt.Apply(path)
+ if result != ROUTE_TYPE_NONE {
+ return result, path
+ }
}
- return conditions
+ return ROUTE_TYPE_NONE, path
}
-func ActionsToApiStruct(conActions config.Actions) *gobgpapi.Actions {
- action := gobgpapi.RouteAction_REJECT
- if conActions.RouteDisposition.AcceptRoute {
- action = gobgpapi.RouteAction_ACCEPT
- }
-
- //TODO: support CommunitySetRef
- communityAction := &gobgpapi.CommunityAction{
- Communities: conActions.BgpActions.SetCommunity.SetCommunityMethod.Communities,
- Options: conActions.BgpActions.SetCommunity.Options,
- }
- medAction := fmt.Sprintf("%s", conActions.BgpActions.SetMed)
- asprependAction := &gobgpapi.AsPrependAction{
- conActions.BgpActions.SetAsPathPrepend.As,
- uint32(conActions.BgpActions.SetAsPathPrepend.RepeatN),
- }
- extCommunityAction := &gobgpapi.CommunityAction{
- Communities: conActions.BgpActions.SetExtCommunity.SetExtCommunityMethod.Communities,
- Options: conActions.BgpActions.SetExtCommunity.Options,
+func (p *Policy) ToApiStruct() *api.PolicyDefinition {
+ ss := make([]*api.Statement, 0, len(p.Statements))
+ for _, s := range p.Statements {
+ ss = append(ss, s.ToApiStruct())
}
-
- resActions := &gobgpapi.Actions{
- RouteAction: action,
- Community: communityAction,
- Med: medAction,
- AsPrepend: asprependAction,
- ExtCommunity: extCommunityAction,
+ return &api.PolicyDefinition{
+ Name: p.name,
+ Statements: ss,
}
- return resActions
}
-func ActionsToConfigStruct(reqActions *gobgpapi.Actions) config.Actions {
- actions := config.Actions{}
- if reqActions == nil {
- return actions
- }
- if reqActions.Community != nil {
- actions.BgpActions.SetCommunity.SetCommunityMethod.Communities = reqActions.Community.Communities
- actions.BgpActions.SetCommunity.Options = reqActions.Community.Options
- }
- if reqActions.Med != "" {
- actions.BgpActions.SetMed = config.BgpSetMedType(reqActions.Med)
+func NewPolicy(c config.PolicyDefinition, dmap DefinedSetMap) (*Policy, error) {
+ if c.Name == "" {
+ return nil, fmt.Errorf("empty policy name")
}
- if reqActions.AsPrepend != nil {
- actions.BgpActions.SetAsPathPrepend.As = reqActions.AsPrepend.As
- actions.BgpActions.SetAsPathPrepend.RepeatN = uint8(reqActions.AsPrepend.Repeatn)
- }
-
- switch reqActions.RouteAction {
- case gobgpapi.RouteAction_ACCEPT:
- actions.RouteDisposition.AcceptRoute = true
- case gobgpapi.RouteAction_REJECT:
- actions.RouteDisposition.RejectRoute = true
+ var st []*Statement
+ stmts := c.Statements.StatementList
+ if len(stmts) != 0 {
+ st = make([]*Statement, 0, len(stmts))
+ for _, stmt := range stmts {
+ s, err := NewStatement(stmt, dmap)
+ if err != nil {
+ return nil, err
+ }
+ st = append(st, s)
+ }
}
- return actions
+ return &Policy{
+ name: c.Name,
+ Statements: st,
+ }, nil
}
-func StatementToConfigStruct(reqStatement *gobgpapi.Statement) config.Statement {
- statement := config.Statement{
- Name: reqStatement.StatementNeme,
- Conditions: ConditionsToConfigStruct(reqStatement.Conditions),
- Actions: ActionsToConfigStruct(reqStatement.Actions),
- }
- return statement
+type RoutingPolicy struct {
+ DefinedSetMap DefinedSetMap
+ PolicyMap map[string]*Policy
}
-func PolicyDefinitionToConfigStruct(reqPolicy *gobgpapi.PolicyDefinition) (bool, config.PolicyDefinition) {
- isReqStatement := true
- policy := config.PolicyDefinition{
- Name: reqPolicy.PolicyDefinitionName,
- }
- if reqPolicy.StatementList != nil {
- statement := StatementToConfigStruct(reqPolicy.StatementList[0])
- policy.Statements.StatementList = []config.Statement{statement}
- } else {
- isReqStatement = false
- }
- return isReqStatement, policy
-}
-
-func PolicyDefinitionToApiStruct(pd config.PolicyDefinition, df config.DefinedSets) *gobgpapi.PolicyDefinition {
- conPrefixSetList := df.PrefixSets.PrefixSetList
- conNeighborSetList := df.NeighborSets.NeighborSetList
- conAsPathSetList := df.BgpDefinedSets.AsPathSets.AsPathSetList
- conCommunitySetList := df.BgpDefinedSets.CommunitySets.CommunitySetList
- conExtCommunitySetList := df.BgpDefinedSets.ExtCommunitySets.ExtCommunitySetList
- resStatementList := make([]*gobgpapi.Statement, 0)
- for _, st := range pd.Statements.StatementList {
- co := st.Conditions
- bco := co.BgpConditions
- ac := st.Actions
-
- prefixSet := &gobgpapi.PrefixSet{PrefixSetName: co.MatchPrefixSet.PrefixSet}
- conPrefixSet := config.PrefixSet{PrefixSetName: co.MatchPrefixSet.PrefixSet}
- idxPrefixSet, _ := IndexOfPrefixSet(conPrefixSetList, conPrefixSet)
- if idxPrefixSet != -1 {
- prefixSet = PrefixSetToApiStruct(conPrefixSetList[idxPrefixSet])
- prefixSet.MatchSetOptions = MatchSetOptionsRestrictedToString(st.Conditions.MatchPrefixSet.MatchSetOptions)
- }
- neighborSet := &gobgpapi.NeighborSet{NeighborSetName: co.MatchNeighborSet.NeighborSet}
- conNeighborSet := config.NeighborSet{NeighborSetName: co.MatchNeighborSet.NeighborSet}
- idxNeighborSet, _ := IndexOfNeighborSet(conNeighborSetList, conNeighborSet)
- if idxNeighborSet != -1 {
- neighborSet = NeighborSetToApiStruct(conNeighborSetList[idxNeighborSet])
- neighborSet.MatchSetOptions = MatchSetOptionsRestrictedToString(st.Conditions.MatchNeighborSet.MatchSetOptions)
- }
-
- asPathSet := &gobgpapi.AsPathSet{AsPathSetName: bco.MatchAsPathSet.AsPathSet}
- conAsPathSet := config.AsPathSet{AsPathSetName: bco.MatchAsPathSet.AsPathSet}
- idxAsPathSet, _ := IndexOfAsPathSet(conAsPathSetList, conAsPathSet)
- if idxAsPathSet != -1 {
- asPathSet = AsPathSetToApiStruct(conAsPathSetList[idxAsPathSet])
- asPathSet.MatchSetOptions = MatchSetOptionToString(bco.MatchAsPathSet.MatchSetOptions)
- }
-
- communitySet := &gobgpapi.CommunitySet{CommunitySetName: bco.MatchCommunitySet.CommunitySet}
- conCommunitySet := config.CommunitySet{CommunitySetName: bco.MatchCommunitySet.CommunitySet}
- idxCommunitySet, _ := IndexOfCommunitySet(conCommunitySetList, conCommunitySet)
- if idxCommunitySet != -1 {
- communitySet = CommunitySetToApiStruct(conCommunitySetList[idxCommunitySet])
- communitySet.MatchSetOptions = MatchSetOptionToString(bco.MatchCommunitySet.MatchSetOptions)
- }
-
- extCommunitySet := &gobgpapi.ExtCommunitySet{ExtCommunitySetName: bco.MatchExtCommunitySet.ExtCommunitySet}
- conExtCommunitySet := config.ExtCommunitySet{ExtCommunitySetName: bco.MatchExtCommunitySet.ExtCommunitySet}
- idxExtCommunitySet, _ := IndexOfExtCommunitySet(conExtCommunitySetList, conExtCommunitySet)
- if idxExtCommunitySet != -1 {
- extCommunitySet = ExtCommunitySetToApiStruct(conExtCommunitySetList[idxExtCommunitySet])
- extCommunitySet.MatchSetOptions = MatchSetOptionToString(bco.MatchExtCommunitySet.MatchSetOptions)
+func NewRoutingPolicy(c config.RoutingPolicy) (*RoutingPolicy, error) {
+ dmap := make(map[DefinedType]map[string]DefinedSet)
+ dmap[DEFINED_TYPE_PREFIX] = make(map[string]DefinedSet)
+ d := c.DefinedSets
+ for _, x := range d.PrefixSets.PrefixSetList {
+ y, err := NewPrefixSet(x)
+ if err != nil {
+ return nil, err
}
-
- resConditions := &gobgpapi.Conditions{
- MatchPrefixSet: prefixSet,
- MatchNeighborSet: neighborSet,
- MatchAsPathSet: asPathSet,
- MatchCommunitySet: communitySet,
- MatchExtCommunitySet: extCommunitySet,
- MatchAsPathLength: AsPathLengthToApiStruct(st.Conditions.BgpConditions.AsPathLength),
+ dmap[DEFINED_TYPE_PREFIX][y.Name()] = y
+ }
+ dmap[DEFINED_TYPE_NEIGHBOR] = make(map[string]DefinedSet)
+ for _, x := range d.NeighborSets.NeighborSetList {
+ y, err := NewNeighborSet(x)
+ if err != nil {
+ return nil, err
+ }
+ dmap[DEFINED_TYPE_NEIGHBOR][y.Name()] = y
+ }
+ // dmap[DEFINED_TYPE_TAG] = make(map[string]DefinedSet)
+ // for _, x := range c.DefinedSets.TagSets.TagSetList {
+ // y, err := NewTagSet(x)
+ // if err != nil {
+ // return nil, err
+ // }
+ // dmap[DEFINED_TYPE_TAG][y.Name()] = y
+ // }
+ bd := c.DefinedSets.BgpDefinedSets
+ dmap[DEFINED_TYPE_AS_PATH] = make(map[string]DefinedSet)
+ for _, x := range bd.AsPathSets.AsPathSetList {
+ y, err := NewAsPathSet(x)
+ if err != nil {
+ return nil, err
}
- resActions := ActionsToApiStruct(ac)
- resStatement := &gobgpapi.Statement{
- StatementNeme: st.Name,
- Conditions: resConditions,
- Actions: resActions,
+ dmap[DEFINED_TYPE_AS_PATH][y.Name()] = y
+ }
+ dmap[DEFINED_TYPE_COMMUNITY] = make(map[string]DefinedSet)
+ for _, x := range bd.CommunitySets.CommunitySetList {
+ y, err := NewCommunitySet(x)
+ if err != nil {
+ return nil, err
}
- resStatementList = append(resStatementList, resStatement)
+ dmap[DEFINED_TYPE_COMMUNITY][y.Name()] = y
}
- resPolicyDefinition := &gobgpapi.PolicyDefinition{
- PolicyDefinitionName: pd.Name,
- StatementList: resStatementList,
+ dmap[DEFINED_TYPE_EXT_COMMUNITY] = make(map[string]DefinedSet)
+ for _, x := range bd.ExtCommunitySets.ExtCommunitySetList {
+ y, err := NewExtCommunitySet(x)
+ if err != nil {
+ return nil, err
+ }
+ dmap[DEFINED_TYPE_EXT_COMMUNITY][y.Name()] = y
}
- return resPolicyDefinition
-}
-
-func PoliciesToString(reqPolicies []*gobgpapi.PolicyDefinition) []string {
- policies := make([]string, 0)
- for _, reqPolicy := range reqPolicies {
- policies = append(policies, reqPolicy.PolicyDefinitionName)
+ pmap := make(map[string]*Policy)
+ for _, x := range c.PolicyDefinitions.PolicyDefinitionList {
+ y, err := NewPolicy(x, dmap)
+ if err != nil {
+ return nil, err
+ }
+ pmap[y.Name()] = y
}
- return policies
+ return &RoutingPolicy{
+ DefinedSetMap: dmap,
+ PolicyMap: pmap,
+ }, nil
}
func CanImportToVrf(v *Vrf, path *Path) bool {
@@ -2053,13 +1610,22 @@ func CanImportToVrf(v *Vrf, path *Path) bool {
}
return ret
}
- set := config.ExtCommunitySet{
+ set, _ := NewExtCommunitySet(config.ExtCommunitySet{
ExtCommunitySetName: v.Name,
ExtCommunityList: f(v.ImportRt),
- }
+ })
matchSet := config.MatchExtCommunitySet{
ExtCommunitySet: v.Name,
MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
}
- return NewExtCommunityCondition(matchSet, []config.ExtCommunitySet{set}).evaluate(path)
+ c, _ := NewExtCommunityCondition(matchSet, map[string]DefinedSet{v.Name: set})
+ return c.Evaluate(path)
+}
+
+func PoliciesToString(ps []*api.PolicyDefinition) []string {
+ names := make([]string, 0, len(ps))
+ for _, p := range ps {
+ names = append(names, p.Name)
+ }
+ return names
}
diff --git a/table/policy_test.go b/table/policy_test.go
index a60c9cc7..9f9e1d17 100644
--- a/table/policy_test.go
+++ b/table/policy_test.go
@@ -23,7 +23,6 @@ import (
"github.com/stretchr/testify/assert"
"math"
"net"
- "regexp"
"strconv"
"strings"
"testing"
@@ -48,14 +47,14 @@ func TestPrefixCalcurateNoRange(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("10.10.0.0/24", "")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"10.10.0.0/24", ""})
+ match1 := pl1.Match(path)
assert.Equal(t, true, match1)
- pl2, _ := NewPrefix("10.10.0.0/23", "")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"10.10.0.0/23", ""})
+ match2 := pl2.Match(path)
assert.Equal(t, false, match2)
- pl3, _ := NewPrefix("10.10.0.0/16", "21..24")
- match3 := ipPrefixCalculate(path, pl3)
+ pl3, _ := NewPrefix(config.Prefix{"10.10.0.0/16", "21..24"})
+ match3 := pl3.Match(path)
assert.Equal(t, true, match3)
}
@@ -72,11 +71,11 @@ func TestPrefixCalcurateAddress(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("10.11.0.0/16", "21..24")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"10.11.0.0/16", "21..24"})
+ match1 := pl1.Match(path)
assert.Equal(t, false, match1)
- pl2, _ := NewPrefix("10.10.0.0/16", "21..24")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"10.10.0.0/16", "21..24"})
+ match2 := pl2.Match(path)
assert.Equal(t, true, match2)
}
@@ -93,11 +92,11 @@ func TestPrefixCalcurateLength(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("10.10.64.0/24", "21..24")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"10.10.64.0/24", "21..24"})
+ match1 := pl1.Match(path)
assert.Equal(t, false, match1)
- pl2, _ := NewPrefix("10.10.64.0/16", "21..24")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"10.10.64.0/16", "21..24"})
+ match2 := pl2.Match(path)
assert.Equal(t, true, match2)
}
@@ -114,14 +113,14 @@ func TestPrefixCalcurateLengthRange(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("10.10.0.0/16", "21..23")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"10.10.0.0/16", "21..23"})
+ match1 := pl1.Match(path)
assert.Equal(t, false, match1)
- pl2, _ := NewPrefix("10.10.0.0/16", "25..26")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"10.10.0.0/16", "25..26"})
+ match2 := pl2.Match(path)
assert.Equal(t, false, match2)
- pl3, _ := NewPrefix("10.10.0.0/16", "21..24")
- match3 := ipPrefixCalculate(path, pl3)
+ pl3, _ := NewPrefix(config.Prefix{"10.10.0.0/16", "21..24"})
+ match3 := pl3.Match(path)
assert.Equal(t, true, match3)
}
@@ -139,14 +138,14 @@ func TestPrefixCalcurateNoRangeIPv6(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("2001:123:123::/48", "")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"2001:123:123::/48", ""})
+ match1 := pl1.Match(path)
assert.Equal(t, false, match1)
- pl2, _ := NewPrefix("2001:123:123:1::/64", "")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"2001:123:123:1::/64", ""})
+ match2 := pl2.Match(path)
assert.Equal(t, true, match2)
- pl3, _ := NewPrefix("2001:123:123::/48", "64..80")
- match3 := ipPrefixCalculate(path, pl3)
+ pl3, _ := NewPrefix(config.Prefix{"2001:123:123::/48", "64..80"})
+ match3 := pl3.Match(path)
assert.Equal(t, true, match3)
}
@@ -163,11 +162,11 @@ func TestPrefixCalcurateAddressIPv6(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("2001:123:128::/48", "64..80")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"2001:123:128::/48", "64..80"})
+ match1 := pl1.Match(path)
assert.Equal(t, false, match1)
- pl2, _ := NewPrefix("2001:123:123::/48", "64..80")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"2001:123:123::/48", "64..80"})
+ match2 := pl2.Match(path)
assert.Equal(t, true, match2)
}
@@ -184,11 +183,11 @@ func TestPrefixCalcurateLengthIPv6(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("2001:123:123:64::/64", "64..80")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"2001:123:123:64::/64", "64..80"})
+ match1 := pl1.Match(path)
assert.Equal(t, false, match1)
- pl2, _ := NewPrefix("2001:123:123:64::/48", "64..80")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"2001:123:123:64::/48", "64..80"})
+ match2 := pl2.Match(path)
assert.Equal(t, true, match2)
}
@@ -205,14 +204,14 @@ func TestPrefixCalcurateLengthRangeIPv6(t *testing.T) {
updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
path := ProcessMessage(updateMsg, peer)[0]
// test
- pl1, _ := NewPrefix("2001:123:123::/48", "62..63")
- match1 := ipPrefixCalculate(path, pl1)
+ pl1, _ := NewPrefix(config.Prefix{"2001:123:123::/48", "62..63"})
+ match1 := pl1.Match(path)
assert.Equal(t, false, match1)
- pl2, _ := NewPrefix("2001:123:123::/48", "65..66")
- match2 := ipPrefixCalculate(path, pl2)
+ pl2, _ := NewPrefix(config.Prefix{"2001:123:123::/48", "65..66"})
+ match2 := pl2.Match(path)
assert.Equal(t, false, match2)
- pl3, _ := NewPrefix("2001:123:123::/48", "63..65")
- match3 := ipPrefixCalculate(path, pl3)
+ pl3, _ := NewPrefix(config.Prefix{"2001:123:123::/48", "63..65"})
+ match3 := pl3.Match(path)
assert.Equal(t, true, match3)
}
@@ -239,10 +238,9 @@ func TestPolicyNotMatch(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
- //test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
- pType, newPath := p.Apply(path)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ pType, newPath := r.PolicyMap["pd1"].Apply(path)
assert.Equal(t, ROUTE_TYPE_NONE, pType)
assert.Equal(t, newPath, path)
}
@@ -270,10 +268,9 @@ func TestPolicyMatchAndReject(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
- //test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
- pType, newPath := p.Apply(path)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ pType, newPath := r.PolicyMap["pd1"].Apply(path)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
}
@@ -302,9 +299,9 @@ func TestPolicyMatchAndAccept(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
- pType, newPath := p.Apply(path)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ pType, newPath := r.PolicyMap["pd1"].Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
assert.Equal(t, path, newPath)
}
@@ -338,13 +335,14 @@ func TestPolicyRejectOnlyPrefixSet(t *testing.T) {
ds := config.DefinedSets{}
ds.PrefixSets.PrefixSetList = []config.PrefixSet{ps}
- s := createStatement("statement1", "ps1", "ns1", false)
+ s := createStatement("statement1", "ps1", "", false)
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path1)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path1)
@@ -383,18 +381,18 @@ func TestPolicyRejectOnlyNeighborSet(t *testing.T) {
ds := config.DefinedSets{}
ds.NeighborSets.NeighborSetList = []config.NeighborSet{ns}
- s := createStatement("statement1", "ps1", "ns1", false)
+ s := createStatement("statement1", "", "ns1", false)
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
- pType, newPath := p.Apply(path1)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ pType, newPath := r.PolicyMap["pd1"].Apply(path1)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path1)
- pType2, newPath2 := p.Apply(path2)
+ pType2, newPath2 := r.PolicyMap["pd1"].Apply(path2)
assert.Equal(t, ROUTE_TYPE_NONE, pType2)
assert.Equal(t, newPath2, path2)
}
@@ -440,8 +438,9 @@ func TestPolicyDifferentRoutefamilyOfPathAndPolicy(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType1, newPath1 := p.Apply(pathIPv4)
assert.Equal(t, ROUTE_TYPE_REJECT, pType1)
assert.Equal(t, newPath1, pathIPv4)
@@ -474,30 +473,30 @@ func TestAsPathLengthConditionEvaluate(t *testing.T) {
Operator: "eq",
Value: 5,
}
- c := NewAsPathLengthCondition(asPathLength)
+ c, _ := NewAsPathLengthCondition(asPathLength)
// test
- assert.Equal(t, true, c.evaluate(path))
+ assert.Equal(t, true, c.Evaluate(path))
// create match condition
asPathLength = config.AsPathLength{
Operator: "ge",
Value: 3,
}
- c = NewAsPathLengthCondition(asPathLength)
+ c, _ = NewAsPathLengthCondition(asPathLength)
// test
- assert.Equal(t, true, c.evaluate(path))
+ assert.Equal(t, true, c.Evaluate(path))
// create match condition
asPathLength = config.AsPathLength{
Operator: "le",
Value: 3,
}
- c = NewAsPathLengthCondition(asPathLength)
+ c, _ = NewAsPathLengthCondition(asPathLength)
// test
- assert.Equal(t, false, c.evaluate(path))
+ assert.Equal(t, false, c.Evaluate(path))
}
func TestAsPathLengthConditionWithOtherCondition(t *testing.T) {
@@ -538,8 +537,9 @@ func TestAsPathLengthConditionWithOtherCondition(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
@@ -579,30 +579,30 @@ func TestAs4PathLengthConditionEvaluate(t *testing.T) {
Operator: "eq",
Value: 5,
}
- c := NewAsPathLengthCondition(asPathLength)
+ c, _ := NewAsPathLengthCondition(asPathLength)
// test
- assert.Equal(t, true, c.evaluate(path))
+ assert.Equal(t, true, c.Evaluate(path))
// create match condition
asPathLength = config.AsPathLength{
Operator: "ge",
Value: 3,
}
- c = NewAsPathLengthCondition(asPathLength)
+ c, _ = NewAsPathLengthCondition(asPathLength)
// test
- assert.Equal(t, true, c.evaluate(path))
+ assert.Equal(t, true, c.Evaluate(path))
// create match condition
asPathLength = config.AsPathLength{
Operator: "le",
Value: 3,
}
- c = NewAsPathLengthCondition(asPathLength)
+ c, _ = NewAsPathLengthCondition(asPathLength)
// test
- assert.Equal(t, false, c.evaluate(path))
+ assert.Equal(t, false, c.Evaluate(path))
}
func TestAs4PathLengthConditionWithOtherCondition(t *testing.T) {
@@ -654,8 +654,8 @@ func TestAs4PathLengthConditionWithOtherCondition(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, _ := NewRoutingPolicy(pl)
+ p, _ := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], r.DefinedSetMap)
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
@@ -733,14 +733,18 @@ func TestAsPathConditionEvaluate(t *testing.T) {
},
}
- asPathSetList := []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6}
+ m := make(map[string]DefinedSet)
+ for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
+ asPathSet4, asPathSet5, asPathSet6} {
+ a, _ := NewAsPathSet(s)
+ m[s.AsPathSetName] = a
+ }
createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p := NewAsPathCondition(matchSet, asPathSetList)
+ p, _ := NewAsPathCondition(matchSet, m)
return p
}
@@ -750,22 +754,19 @@ func TestAsPathConditionEvaluate(t *testing.T) {
p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY)
p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY)
p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY)
-
- //TODO: add ALL and INVERT cases.
p7 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ALL)
p8 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_INVERT)
// test
- assert.Equal(t, true, p1.evaluate(path1))
- assert.Equal(t, true, p2.evaluate(path1))
- assert.Equal(t, true, p3.evaluate(path1))
- assert.Equal(t, false, p4.evaluate(path1))
- assert.Equal(t, true, p5.evaluate(path1))
- assert.Equal(t, false, p6.evaluate(path1))
- assert.Equal(t, true, p6.evaluate(path2))
-
- assert.Equal(t, true, p7.evaluate(path1))
- assert.Equal(t, true, p8.evaluate(path2))
+ assert.Equal(t, true, p1.Evaluate(path1))
+ assert.Equal(t, true, p2.Evaluate(path1))
+ assert.Equal(t, true, p3.Evaluate(path1))
+ assert.Equal(t, false, p4.Evaluate(path1))
+ assert.Equal(t, true, p5.Evaluate(path1))
+ assert.Equal(t, false, p6.Evaluate(path1))
+ assert.Equal(t, true, p6.Evaluate(path2))
+ assert.Equal(t, true, p7.Evaluate(path1))
+ assert.Equal(t, true, p8.Evaluate(path2))
}
func TestMultipleAsPathConditionEvaluate(t *testing.T) {
@@ -850,14 +851,18 @@ func TestMultipleAsPathConditionEvaluate(t *testing.T) {
},
}
- asPathSetList := []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9}
+ m := make(map[string]DefinedSet)
+ for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
+ asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9} {
+ a, _ := NewAsPathSet(s)
+ m[s.AsPathSetName] = a
+ }
createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p := NewAsPathCondition(matchSet, asPathSetList)
+ p, _ := NewAsPathCondition(matchSet, m)
return p
}
@@ -872,15 +877,15 @@ func TestMultipleAsPathConditionEvaluate(t *testing.T) {
p9 := createAspathC("asset9", config.MATCH_SET_OPTIONS_TYPE_ANY)
// test
- assert.Equal(t, true, p1.evaluate(path1))
- assert.Equal(t, true, p2.evaluate(path1))
- assert.Equal(t, true, p3.evaluate(path1))
- assert.Equal(t, true, p4.evaluate(path1))
- assert.Equal(t, true, p5.evaluate(path1))
- assert.Equal(t, true, p6.evaluate(path1))
- assert.Equal(t, true, p7.evaluate(path1))
- assert.Equal(t, true, p8.evaluate(path1))
- assert.Equal(t, false, p9.evaluate(path1))
+ assert.Equal(t, true, p1.Evaluate(path1))
+ assert.Equal(t, true, p2.Evaluate(path1))
+ assert.Equal(t, true, p3.Evaluate(path1))
+ assert.Equal(t, true, p4.Evaluate(path1))
+ assert.Equal(t, true, p5.Evaluate(path1))
+ assert.Equal(t, true, p6.Evaluate(path1))
+ assert.Equal(t, true, p7.Evaluate(path1))
+ assert.Equal(t, true, p8.Evaluate(path1))
+ assert.Equal(t, false, p9.Evaluate(path1))
}
func TestAsPathCondition(t *testing.T) {
@@ -930,17 +935,19 @@ func TestAsPathCondition(t *testing.T) {
}
for k, v := range tests {
- r, _ := regexp.Compile(strings.Replace(k, "_", ASPATH_REGEXP_MAGIC, -1))
- c := &AsPathCondition{
- AsRegExpList: []*regexp.Regexp{r},
- MatchOption: config.MATCH_SET_OPTIONS_TYPE_ANY,
- }
+ s, _ := NewAsPathSet(config.AsPathSet{
+ AsPathSetName: k,
+ AsPathList: []config.AsPath{config.AsPath{k}},
+ })
+ c, _ := NewAsPathCondition(config.MatchAsPathSet{
+ AsPathSet: k,
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
+ }, map[string]DefinedSet{k: s})
for _, a := range v {
- result := c.evaluate(a.path)
+ result := c.Evaluate(a.path)
if a.result != result {
log.WithFields(log.Fields{
"EXP": k,
- "ASN": r,
"ASSTR": a.path.GetAsString(),
"Expected": a.result,
"Result": result,
@@ -990,8 +997,9 @@ func TestAsPathConditionWithOtherCondition(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
@@ -1077,14 +1085,18 @@ func TestAs4PathConditionEvaluate(t *testing.T) {
},
}
- asPathSetList := []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6}
+ m := make(map[string]DefinedSet)
+ for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
+ asPathSet4, asPathSet5, asPathSet6} {
+ a, _ := NewAsPathSet(s)
+ m[s.AsPathSetName] = a
+ }
createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p := NewAsPathCondition(matchSet, asPathSetList)
+ p, _ := NewAsPathCondition(matchSet, m)
return p
}
@@ -1099,16 +1111,16 @@ func TestAs4PathConditionEvaluate(t *testing.T) {
p8 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_INVERT)
// test
- assert.Equal(t, true, p1.evaluate(path1))
- assert.Equal(t, true, p2.evaluate(path1))
- assert.Equal(t, true, p3.evaluate(path1))
- assert.Equal(t, false, p4.evaluate(path1))
- assert.Equal(t, true, p5.evaluate(path1))
- assert.Equal(t, false, p6.evaluate(path1))
- assert.Equal(t, true, p6.evaluate(path2))
-
- assert.Equal(t, true, p7.evaluate(path1))
- assert.Equal(t, true, p8.evaluate(path2))
+ assert.Equal(t, true, p1.Evaluate(path1))
+ assert.Equal(t, true, p2.Evaluate(path1))
+ assert.Equal(t, true, p3.Evaluate(path1))
+ assert.Equal(t, false, p4.Evaluate(path1))
+ assert.Equal(t, true, p5.Evaluate(path1))
+ assert.Equal(t, false, p6.Evaluate(path1))
+ assert.Equal(t, true, p6.Evaluate(path2))
+
+ assert.Equal(t, true, p7.Evaluate(path1))
+ assert.Equal(t, true, p8.Evaluate(path2))
}
func TestMultipleAs4PathConditionEvaluate(t *testing.T) {
@@ -1200,14 +1212,18 @@ func TestMultipleAs4PathConditionEvaluate(t *testing.T) {
},
}
- asPathSetList := []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9}
+ m := make(map[string]DefinedSet)
+ for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
+ asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9} {
+ a, _ := NewAsPathSet(s)
+ m[s.AsPathSetName] = a
+ }
createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p := NewAsPathCondition(matchSet, asPathSetList)
+ p, _ := NewAsPathCondition(matchSet, m)
return p
}
@@ -1222,15 +1238,15 @@ func TestMultipleAs4PathConditionEvaluate(t *testing.T) {
p9 := createAspathC("asset9", config.MATCH_SET_OPTIONS_TYPE_ANY)
// test
- assert.Equal(t, true, p1.evaluate(path1))
- assert.Equal(t, true, p2.evaluate(path1))
- assert.Equal(t, true, p3.evaluate(path1))
- assert.Equal(t, true, p4.evaluate(path1))
- assert.Equal(t, true, p5.evaluate(path1))
- assert.Equal(t, true, p6.evaluate(path1))
- assert.Equal(t, true, p7.evaluate(path1))
- assert.Equal(t, true, p8.evaluate(path1))
- assert.Equal(t, false, p9.evaluate(path1))
+ assert.Equal(t, true, p1.Evaluate(path1))
+ assert.Equal(t, true, p2.Evaluate(path1))
+ assert.Equal(t, true, p3.Evaluate(path1))
+ assert.Equal(t, true, p4.Evaluate(path1))
+ assert.Equal(t, true, p5.Evaluate(path1))
+ assert.Equal(t, true, p6.Evaluate(path1))
+ assert.Equal(t, true, p7.Evaluate(path1))
+ assert.Equal(t, true, p8.Evaluate(path1))
+ assert.Equal(t, false, p9.Evaluate(path1))
}
func TestAs4PathConditionWithOtherCondition(t *testing.T) {
@@ -1286,8 +1302,8 @@ func TestAs4PathConditionWithOtherCondition(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, _ := NewRoutingPolicy(pl)
+ p, _ := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], r.DefinedSetMap)
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
@@ -1373,14 +1389,18 @@ func TestAs4PathConditionEvaluateMixedWith2byteAS(t *testing.T) {
},
}
- asPathSetList := []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6, asPathSet7}
+ m := make(map[string]DefinedSet)
+ for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
+ asPathSet4, asPathSet5, asPathSet6, asPathSet7} {
+ a, _ := NewAsPathSet(s)
+ m[s.AsPathSetName] = a
+ }
createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p := NewAsPathCondition(matchSet, asPathSetList)
+ p, _ := NewAsPathCondition(matchSet, m)
return p
}
@@ -1393,13 +1413,13 @@ func TestAs4PathConditionEvaluateMixedWith2byteAS(t *testing.T) {
p7 := createAspathC("asset7", config.MATCH_SET_OPTIONS_TYPE_ANY)
// test
- assert.Equal(t, true, p1.evaluate(path1))
- assert.Equal(t, true, p2.evaluate(path1))
- assert.Equal(t, true, p3.evaluate(path1))
- assert.Equal(t, true, p4.evaluate(path1))
- assert.Equal(t, true, p5.evaluate(path1))
- assert.Equal(t, false, p6.evaluate(path1))
- assert.Equal(t, true, p7.evaluate(path1))
+ assert.Equal(t, true, p1.Evaluate(path1))
+ assert.Equal(t, true, p2.Evaluate(path1))
+ assert.Equal(t, true, p3.Evaluate(path1))
+ assert.Equal(t, true, p4.Evaluate(path1))
+ assert.Equal(t, true, p5.Evaluate(path1))
+ assert.Equal(t, false, p6.Evaluate(path1))
+ assert.Equal(t, true, p7.Evaluate(path1))
}
@@ -1434,6 +1454,17 @@ func TestCommunityConditionEvaluate(t *testing.T) {
UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
path1 := ProcessMessage(updateMsg1, peer)[0]
+ communities2 := bgp.NewPathAttributeCommunities([]uint32{
+ stringToCommunityValue("65001:100"),
+ stringToCommunityValue("65001:200"),
+ stringToCommunityValue("65001:300"),
+ stringToCommunityValue("65001:400")})
+
+ pathAttributes2 := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities2}
+ updateMsg2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri)
+ UpdatePathAttrs4ByteAs(updateMsg2.Body.(*bgp.BGPUpdate))
+ path2 := ProcessMessage(updateMsg2, peer)[0]
+
// create match condition
comSet1 := config.CommunitySet{
CommunitySetName: "comset1",
@@ -1496,9 +1527,8 @@ func TestCommunityConditionEvaluate(t *testing.T) {
comSet9 := config.CommunitySet{
CommunitySetName: "comset9",
CommunityList: []config.Community{
- config.Community{"65001:100"},
- config.Community{"65001:200"},
- config.Community{"65001:300"},
+ config.Community{"65001:\\d+"},
+ config.Community{"\\d+:\\d00"},
},
}
@@ -1511,14 +1541,19 @@ func TestCommunityConditionEvaluate(t *testing.T) {
},
}
- comSetList := []config.CommunitySet{comSet1, comSet2, comSet3,
- comSet4, comSet5, comSet6, comSet7, comSet8, comSet9, comSet10}
+ m := make(map[string]DefinedSet)
+
+ for _, c := range []config.CommunitySet{comSet1, comSet2, comSet3,
+ comSet4, comSet5, comSet6, comSet7, comSet8, comSet9, comSet10} {
+ s, _ := NewCommunitySet(c)
+ m[c.CommunitySetName] = s
+ }
createCommunityC := func(name string, option config.MatchSetOptionsType) *CommunityCondition {
matchSet := config.MatchCommunitySet{}
matchSet.CommunitySet = name
matchSet.MatchSetOptions = option
- c := NewCommunityCondition(matchSet, comSetList)
+ c, _ := NewCommunityCondition(matchSet, m)
return c
}
@@ -1539,16 +1574,16 @@ func TestCommunityConditionEvaluate(t *testing.T) {
p10 := createCommunityC("comset10", config.MATCH_SET_OPTIONS_TYPE_INVERT)
// test
- assert.Equal(t, true, p1.evaluate(path1))
- assert.Equal(t, true, p2.evaluate(path1))
- assert.Equal(t, true, p3.evaluate(path1))
- assert.Equal(t, true, p4.evaluate(path1))
- assert.Equal(t, true, p5.evaluate(path1))
- assert.Equal(t, true, p6.evaluate(path1))
- assert.Equal(t, true, p7.evaluate(path1))
- assert.Equal(t, true, p8.evaluate(path1))
- assert.Equal(t, true, p9.evaluate(path1))
- assert.Equal(t, true, p10.evaluate(path1))
+ assert.Equal(t, true, p1.Evaluate(path1))
+ assert.Equal(t, true, p2.Evaluate(path1))
+ assert.Equal(t, true, p3.Evaluate(path1))
+ assert.Equal(t, true, p4.Evaluate(path1))
+ assert.Equal(t, true, p5.Evaluate(path1))
+ assert.Equal(t, true, p6.Evaluate(path1))
+ assert.Equal(t, true, p7.Evaluate(path1))
+ assert.Equal(t, true, p8.Evaluate(path1))
+ assert.Equal(t, true, p9.Evaluate(path2))
+ assert.Equal(t, true, p10.Evaluate(path1))
}
@@ -1626,14 +1661,14 @@ func TestCommunityConditionEvaluateWithOtherCondition(t *testing.T) {
pl := createRoutingPolicy(ds, pd1, pd2)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
- df = pl.DefinedSets
- p = NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[1], df)
+ p = r.PolicyMap["pd2"]
pType, newPath = p.Apply(path)
assert.Equal(t, ROUTE_TYPE_NONE, pType)
assert.Equal(t, newPath, path)
@@ -1670,8 +1705,9 @@ func TestPolicyMatchAndAddCommunities(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
@@ -1713,8 +1749,9 @@ func TestPolicyMatchAndReplaceCommunities(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
@@ -1756,8 +1793,9 @@ func TestPolicyMatchAndRemoveCommunities(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
assert.NotEqual(t, nil, newPath)
@@ -1800,8 +1838,9 @@ func TestPolicyMatchAndRemoveCommunitiesRegexp(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
assert.NotEqual(t, nil, newPath)
@@ -1844,8 +1883,9 @@ func TestPolicyMatchAndRemoveCommunitiesRegexp2(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
assert.NotEqual(t, nil, newPath)
@@ -1888,8 +1928,9 @@ func TestPolicyMatchAndClearCommunities(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
@@ -2041,9 +2082,8 @@ func TestExtCommunityConditionEvaluate(t *testing.T) {
ecomSet10 := config.ExtCommunitySet{
ExtCommunitySetName: "ecomSet10",
ExtCommunityList: []config.ExtCommunity{
- config.ExtCommunity{"RT:65001:200"},
- config.ExtCommunity{"RT:10.0.0.1:300"},
- config.ExtCommunity{"SoO:10.0.10.10:[0-9]+"},
+ config.ExtCommunity{"RT:.+:\\d00"},
+ config.ExtCommunity{"SoO:.+:\\d00"},
},
}
@@ -2051,19 +2091,22 @@ func TestExtCommunityConditionEvaluate(t *testing.T) {
ExtCommunitySetName: "ecomSet11",
ExtCommunityList: []config.ExtCommunity{
config.ExtCommunity{"RT:65001:2"},
- config.ExtCommunity{"RT:10.0.0.1:3"},
config.ExtCommunity{"SoO:11.0.10.10:[0-9]+"},
},
}
- comSetList := []config.ExtCommunitySet{ecomSet1, ecomSet2, ecomSet3, ecomSet4, ecomSet5, ecomSet6, ecomSet7,
- ecomSet8, ecomSet9, ecomSet10, ecomSet11}
+ m := make(map[string]DefinedSet)
+ for _, c := range []config.ExtCommunitySet{ecomSet1, ecomSet2, ecomSet3, ecomSet4, ecomSet5, ecomSet6, ecomSet7,
+ ecomSet8, ecomSet9, ecomSet10, ecomSet11} {
+ s, _ := NewExtCommunitySet(c)
+ m[s.Name()] = s
+ }
createExtCommunityC := func(name string, option config.MatchSetOptionsType) *ExtCommunityCondition {
matchSet := config.MatchExtCommunitySet{}
matchSet.ExtCommunitySet = name
matchSet.MatchSetOptions = option
- c := NewExtCommunityCondition(matchSet, comSetList)
+ c, _ := NewExtCommunityCondition(matchSet, m)
return c
}
@@ -2084,17 +2127,17 @@ func TestExtCommunityConditionEvaluate(t *testing.T) {
p11 := createExtCommunityC("ecomSet11", config.MATCH_SET_OPTIONS_TYPE_INVERT)
// test
- assert.Equal(t, true, p1.evaluate(path1))
- assert.Equal(t, true, p2.evaluate(path1))
- assert.Equal(t, true, p3.evaluate(path1))
- assert.Equal(t, false, p4.evaluate(path1))
- assert.Equal(t, false, p5.evaluate(path1))
- assert.Equal(t, false, p6.evaluate(path1))
- assert.Equal(t, true, p7.evaluate(path1))
- assert.Equal(t, true, p8.evaluate(path1))
- assert.Equal(t, true, p9.evaluate(path1))
- assert.Equal(t, true, p10.evaluate(path1))
- assert.Equal(t, true, p11.evaluate(path1))
+ assert.Equal(t, true, p1.Evaluate(path1))
+ assert.Equal(t, true, p2.Evaluate(path1))
+ assert.Equal(t, true, p3.Evaluate(path1))
+ assert.Equal(t, false, p4.Evaluate(path1))
+ assert.Equal(t, false, p5.Evaluate(path1))
+ assert.Equal(t, false, p6.Evaluate(path1))
+ assert.Equal(t, true, p7.Evaluate(path1))
+ assert.Equal(t, true, p8.Evaluate(path1))
+ assert.Equal(t, true, p9.Evaluate(path1))
+ assert.Equal(t, true, p10.Evaluate(path1))
+ assert.Equal(t, true, p11.Evaluate(path1))
}
@@ -2219,13 +2262,14 @@ func TestExtCommunityConditionEvaluateWithOtherCondition(t *testing.T) {
pd2 := createPolicyDefinition("pd2", s2)
pl := createRoutingPolicy(ds, pd1, pd2)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_NONE, pType)
assert.Equal(t, newPath, path)
- p = NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[1], df)
+ p = r.PolicyMap["pd2"]
pType, newPath = p.Apply(path)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
@@ -2262,8 +2306,9 @@ func TestPolicyMatchAndReplaceMed(t *testing.T) {
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
@@ -2304,8 +2349,9 @@ func TestPolicyMatchAndAddingMed(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
assert.NotEqual(t, nil, newPath)
@@ -2347,8 +2393,9 @@ func TestPolicyMatchAndAddingMedOverFlow(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
@@ -2391,8 +2438,9 @@ func TestPolicyMatchAndSubtractMed(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
@@ -2435,8 +2483,9 @@ func TestPolicyMatchAndSubtractMedUnderFlow(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
@@ -2476,14 +2525,15 @@ func TestPolicyMatchWhenPathHaveNotMed(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, err := NewRoutingPolicy(pl)
+ assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
assert.NotEqual(t, nil, newPath)
- _, err := newPath.GetMed()
+ _, err = newPath.GetMed()
assert.NotNil(t, err)
}
@@ -2522,8 +2572,9 @@ func TestPolicyAsPathPrepend(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, _ := NewRoutingPolicy(pl)
+ // assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(ROUTE_TYPE_ACCEPT, pType)
@@ -2565,8 +2616,9 @@ func TestPolicyAsPathPrependLastAs(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, _ := NewRoutingPolicy(pl)
+ // assert.Nil(t, err)
+ p := r.PolicyMap["pd1"]
pType, newPath := p.Apply(path)
assert.Equal(ROUTE_TYPE_ACCEPT, pType)
@@ -2614,8 +2666,8 @@ func TestPolicyAs4PathPrepend(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, _ := NewRoutingPolicy(pl)
+ p, _ := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], r.DefinedSetMap)
pType, newPath := p.Apply(path)
assert.Equal(ROUTE_TYPE_ACCEPT, pType)
@@ -2668,8 +2720,8 @@ func TestPolicyAs4PathPrependLastAs(t *testing.T) {
pd := createPolicyDefinition("pd1", s)
pl := createRoutingPolicy(ds, pd)
//test
- df := pl.DefinedSets
- p := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], df)
+ r, _ := NewRoutingPolicy(pl)
+ p, _ := NewPolicy(pl.PolicyDefinitions.PolicyDefinitionList[0], r.DefinedSetMap)
pType, newPath := p.Apply(path)
assert.Equal(ROUTE_TYPE_ACCEPT, pType)
@@ -2684,7 +2736,6 @@ func TestPolicyAs4PathPrependLastAs(t *testing.T) {
}
func createStatement(name, psname, nsname string, accept bool) config.Statement {
-
c := config.Conditions{
MatchPrefixSet: config.MatchPrefixSet{
PrefixSet: psname,