diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-10-18 15:06:33 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-10-20 10:33:10 +0900 |
commit | a88e0b5592b5f344981983d91f4f55a6d3f002bf (patch) | |
tree | 2fb183724091e4c1b2e2e6b70179821ea9c4b0fe /table/policy.go | |
parent | 7cb50ce1cfdf959a74dad516ef65a6c6c34aaec8 (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.go | 206 |
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) |