summaryrefslogtreecommitdiffhomepage
path: root/table/policy.go
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-10-18 15:06:33 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-10-20 10:33:10 +0900
commita88e0b5592b5f344981983d91f4f55a6d3f002bf (patch)
tree2fb183724091e4c1b2e2e6b70179821ea9c4b0fe /table/policy.go
parent7cb50ce1cfdf959a74dad516ef65a6c6c34aaec8 (diff)
api: support statement modification via grpc
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'table/policy.go')
-rw-r--r--table/policy.go206
1 files changed, 205 insertions, 1 deletions
diff --git a/table/policy.go b/table/policy.go
index 8375faab..1d8cb161 100644
--- a/table/policy.go
+++ b/table/policy.go
@@ -96,6 +96,28 @@ var CommunityOptionValueMap = map[string]config.BgpSetCommunityOptionType{
CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE,
}
+type ConditionType int
+
+const (
+ CONDITION_PREFIX ConditionType = iota
+ CONDITION_NEIGHBOR
+ CONDITION_AS_PATH
+ CONDITION_COMMUNITY
+ CONDITION_EXT_COMMUNITY
+ CONDITION_AS_PATH_LENGTH
+ CONDITION_RPKI
+)
+
+type ActionType int
+
+const (
+ ACTION_ROUTING ActionType = iota
+ ACTION_COMMUNITY
+ ACTION_EXT_COMMUNITY
+ ACTION_MED
+ ACTION_AS_PATH_PREPEND
+)
+
func NewMatchOption(c interface{}) (MatchOption, error) {
switch c.(type) {
case config.MatchSetOptionsType:
@@ -779,6 +801,7 @@ func NewDefinedSetFromApiStruct(a *api.DefinedSet) (DefinedSet, error) {
}
type Condition interface {
+ Type() ConditionType
Evaluate(*Path) bool
Set() DefinedSet
}
@@ -788,6 +811,10 @@ type PrefixCondition struct {
option MatchOption
}
+func (c *PrefixCondition) Type() ConditionType {
+ return CONDITION_PREFIX
+}
+
func (c *PrefixCondition) Set() DefinedSet {
return c.set
}
@@ -869,6 +896,10 @@ type NeighborCondition struct {
option MatchOption
}
+func (c *NeighborCondition) Type() ConditionType {
+ return CONDITION_NEIGHBOR
+}
+
func (c *NeighborCondition) Set() DefinedSet {
return c.set
}
@@ -954,6 +985,10 @@ type AsPathCondition struct {
option MatchOption
}
+func (c *AsPathCondition) Type() ConditionType {
+ return CONDITION_AS_PATH
+}
+
func (c *AsPathCondition) Set() DefinedSet {
return c.set
}
@@ -1031,6 +1066,10 @@ type CommunityCondition struct {
option MatchOption
}
+func (c *CommunityCondition) Type() ConditionType {
+ return CONDITION_COMMUNITY
+}
+
func (c *CommunityCondition) Set() DefinedSet {
return c.set
}
@@ -1111,6 +1150,10 @@ type ExtCommunityCondition struct {
option MatchOption
}
+func (c *ExtCommunityCondition) Type() ConditionType {
+ return CONDITION_EXT_COMMUNITY
+}
+
func (c *ExtCommunityCondition) Set() DefinedSet {
return c.set
}
@@ -1197,6 +1240,10 @@ type AsPathLengthCondition struct {
operator AttributeComparison
}
+func (c *AsPathLengthCondition) Type() ConditionType {
+ return CONDITION_AS_PATH_LENGTH
+}
+
// compare AS_PATH length in the message's AS_PATH attribute with
// the one in condition.
func (c *AsPathLengthCondition) Evaluate(path *Path) bool {
@@ -1265,6 +1312,10 @@ type RpkiValidationCondition struct {
result config.RpkiValidationResultType
}
+func (c *RpkiValidationCondition) Type() ConditionType {
+ return CONDITION_RPKI
+}
+
func (c *RpkiValidationCondition) Evaluate(path *Path) bool {
return c.result == path.Validation
}
@@ -1288,6 +1339,7 @@ func NewRpkiValidationCondition(c config.RpkiValidationResultType) (*RpkiValidat
}
type Action interface {
+ Type() ActionType
Apply(*Path) *Path
}
@@ -1295,6 +1347,10 @@ type RoutingAction struct {
AcceptRoute bool
}
+func (a *RoutingAction) Type() ActionType {
+ return ACTION_ROUTING
+}
+
func (a *RoutingAction) Apply(path *Path) *Path {
if a.AcceptRoute {
return path
@@ -1384,6 +1440,10 @@ func RegexpRemoveExtCommunities(path *Path, exps []*regexp.Regexp, subtypes []bg
path.SetExtCommunities(newComms, true)
}
+func (a *CommunityAction) Type() ActionType {
+ return ACTION_COMMUNITY
+}
+
func (a *CommunityAction) Apply(path *Path) *Path {
switch a.action {
case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
@@ -1492,6 +1552,10 @@ type ExtCommunityAction struct {
subtypeList []bgp.ExtendedCommunityAttrSubType
}
+func (a *ExtCommunityAction) Type() ActionType {
+ return ACTION_EXT_COMMUNITY
+}
+
func (a *ExtCommunityAction) Apply(path *Path) *Path {
switch a.action {
case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
@@ -1611,6 +1675,10 @@ type MedAction struct {
action MedActionType
}
+func (a *MedAction) Type() ActionType {
+ return ACTION_MED
+}
+
func (a *MedAction) Apply(path *Path) *Path {
var err error
switch a.action {
@@ -1678,6 +1746,10 @@ type AsPathPrependAction struct {
repeat uint8
}
+func (a *AsPathPrependAction) Type() ActionType {
+ return ACTION_AS_PATH_PREPEND
+}
+
func (a *AsPathPrependAction) Apply(path *Path) *Path {
var asn uint32
if a.useLeftMost {
@@ -1779,6 +1851,14 @@ func (s *Statement) Apply(path *Path) (RouteType, *Path) {
}).Debug("statement evaluate : ", result)
if result {
//Routing action
+ if s.RouteAction == nil {
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Path": path,
+ "PolicyName": s.Name,
+ }).Warn("route action is nil")
+ return ROUTE_TYPE_REJECT, path
+ }
p := s.RouteAction.Apply(path)
if p == nil {
return ROUTE_TYPE_REJECT, path
@@ -1837,7 +1917,120 @@ func (s *Statement) ToApiStruct() *api.Statement {
}
}
-func NewStatementFromApiStruct(a api.Statement, dmap DefinedSetMap) (*Statement, error) {
+type opType int
+
+const (
+ ADD opType = iota
+ REMOVE
+ REPLACE
+)
+
+func (lhs *Statement) mod(op opType, rhs *Statement) error {
+ cs := make([]Condition, len(lhs.Conditions))
+ copy(cs, lhs.Conditions)
+ ra := lhs.RouteAction
+ as := make([]Action, len(lhs.ModActions))
+ copy(as, lhs.ModActions)
+ for _, x := range rhs.Conditions {
+ var c Condition
+ i := 0
+ for idx, y := range lhs.Conditions {
+ if x.Type() == y.Type() {
+ c = y
+ i = idx
+ break
+ }
+ }
+ switch op {
+ case ADD:
+ if c != nil {
+ return fmt.Errorf("condition %d is already set", c.Type())
+ }
+ if cs == nil {
+ cs = make([]Condition, len(rhs.Conditions))
+ }
+ cs = append(cs, x)
+ case REMOVE:
+ if c == nil {
+ return fmt.Errorf("condition %d is not set", c.Type())
+ }
+ cs = append(cs[:i], cs[i+1:]...)
+ case REPLACE:
+ if c == nil {
+ return fmt.Errorf("condition %d is not set", c.Type())
+ }
+ cs[i] = x
+ }
+ }
+ if rhs.RouteAction != nil {
+ switch op {
+ case ADD:
+ if lhs.RouteAction != nil {
+ return fmt.Errorf("route action is already set")
+ }
+ ra = rhs.RouteAction
+ case REMOVE:
+ if lhs.RouteAction == nil {
+ return fmt.Errorf("route action is not set")
+ }
+ ra = nil
+ case REPLACE:
+ if lhs.RouteAction == nil {
+ return fmt.Errorf("route action is not set")
+ }
+ ra = rhs.RouteAction
+ }
+ }
+ for _, x := range rhs.ModActions {
+ var a Action
+ i := 0
+ for idx, y := range lhs.ModActions {
+ if x.Type() == y.Type() {
+ a = y
+ i = idx
+ break
+ }
+ }
+ switch op {
+ case ADD:
+ if a != nil {
+ return fmt.Errorf("action %d is already set", a.Type())
+ }
+ if as == nil {
+ as = make([]Action, len(rhs.ModActions))
+ }
+ as = append(as, a)
+ case REMOVE:
+ if a == nil {
+ return fmt.Errorf("action %d is not set", a.Type())
+ }
+ as = append(as[:i], as[i+1:]...)
+ case REPLACE:
+ if a == nil {
+ return fmt.Errorf("action %d is not set", a.Type())
+ }
+ as[i] = x
+ }
+ }
+ lhs.Conditions = cs
+ lhs.RouteAction = ra
+ lhs.ModActions = as
+ return nil
+}
+
+func (lhs *Statement) Add(rhs *Statement) error {
+ return lhs.mod(ADD, rhs)
+}
+
+func (lhs *Statement) Remove(rhs *Statement) error {
+ return lhs.mod(REMOVE, rhs)
+}
+
+func (lhs *Statement) Replace(rhs *Statement) error {
+ return lhs.mod(REPLACE, rhs)
+}
+
+func NewStatementFromApiStruct(a *api.Statement, dmap DefinedSetMap) (*Statement, error) {
if a.Name == "" {
return nil, fmt.Errorf("empty statement name")
}
@@ -2070,6 +2263,17 @@ func (r *RoutingPolicy) InUse(d DefinedSet) bool {
return false
}
+func (r *RoutingPolicy) StatementInUse(x *Statement) bool {
+ for _, p := range r.PolicyMap {
+ for _, y := range p.Statements {
+ if x.Name == y.Name {
+ return true
+ }
+ }
+ }
+ return false
+}
+
func NewRoutingPolicy(c config.RoutingPolicy) (*RoutingPolicy, error) {
dmap := make(map[DefinedType]map[string]DefinedSet)
dmap[DEFINED_TYPE_PREFIX] = make(map[string]DefinedSet)