summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/grpc_server.go5
-rw-r--r--config/bgp_configs.go61
-rw-r--r--config/default.go33
-rw-r--r--docs/sources/policy.md86
-rw-r--r--gobgp/cmd/policy.go4
-rw-r--r--table/policy.go27
-rw-r--r--table/policy_test.go54
-rw-r--r--test/scenario_test/route_server_policy_test.py100
-rw-r--r--test/scenario_test/route_server_softreset_test.py2
-rw-r--r--tools/config/example_toml.go5
-rw-r--r--tools/pyang_plugins/bgpyang2golang.py32
11 files changed, 281 insertions, 128 deletions
diff --git a/api/grpc_server.go b/api/grpc_server.go
index 78a53d0b..6445c003 100644
--- a/api/grpc_server.go
+++ b/api/grpc_server.go
@@ -1230,9 +1230,10 @@ func toStatementApi(s *config.Statement) *Statement {
cs.RpkiResult = int32(s.Conditions.BgpConditions.RpkiValidationResult.ToInt())
as := &Actions{
RouteAction: func() RouteAction {
- if s.Actions.RouteDisposition.AcceptRoute {
+ switch s.Actions.RouteDisposition {
+ case config.ROUTE_DISPOSITION_ACCEPT_ROUTE:
return RouteAction_ACCEPT
- } else if s.Actions.RouteDisposition.RejectRoute {
+ case config.ROUTE_DISPOSITION_REJECT_ROUTE:
return RouteAction_REJECT
}
return RouteAction_NONE
diff --git a/config/bgp_configs.go b/config/bgp_configs.go
index 300d9058..742f80dd 100644
--- a/config/bgp_configs.go
+++ b/config/bgp_configs.go
@@ -581,6 +581,42 @@ func (v AttributeComparison) Validate() error {
return nil
}
+// typedef for identity rpol:route-disposition
+type RouteDisposition string
+
+const (
+ ROUTE_DISPOSITION_NONE RouteDisposition = "none"
+ ROUTE_DISPOSITION_ACCEPT_ROUTE RouteDisposition = "accept-route"
+ ROUTE_DISPOSITION_REJECT_ROUTE RouteDisposition = "reject-route"
+)
+
+var RouteDispositionToIntMap = map[RouteDisposition]int{
+ ROUTE_DISPOSITION_NONE: 0,
+ ROUTE_DISPOSITION_ACCEPT_ROUTE: 1,
+ ROUTE_DISPOSITION_REJECT_ROUTE: 2,
+}
+
+func (v RouteDisposition) ToInt() int {
+ i, ok := RouteDispositionToIntMap[v]
+ if !ok {
+ return -1
+ }
+ return i
+}
+
+var IntToRouteDispositionMap = map[int]RouteDisposition{
+ 0: ROUTE_DISPOSITION_NONE,
+ 1: ROUTE_DISPOSITION_ACCEPT_ROUTE,
+ 2: ROUTE_DISPOSITION_REJECT_ROUTE,
+}
+
+func (v RouteDisposition) Validate() error {
+ if _, ok := RouteDispositionToIntMap[v]; !ok {
+ return fmt.Errorf("invalid RouteDisposition: %s", v)
+ }
+ return nil
+}
+
// typedef for identity rpol:route-type
type RouteType string
@@ -4011,29 +4047,6 @@ func (lhs *IgpActions) Equal(rhs *IgpActions) bool {
return true
}
-//struct for container rpol:route-disposition
-type RouteDisposition struct {
- // original -> rpol:accept-route
- //rpol:accept-route's original type is empty
- AcceptRoute bool `mapstructure:"accept-route" json:"accept-route,omitempty"`
- // original -> rpol:reject-route
- //rpol:reject-route's original type is empty
- RejectRoute bool `mapstructure:"reject-route" json:"reject-route,omitempty"`
-}
-
-func (lhs *RouteDisposition) Equal(rhs *RouteDisposition) bool {
- if lhs == nil || rhs == nil {
- return false
- }
- if lhs.AcceptRoute != rhs.AcceptRoute {
- return false
- }
- if lhs.RejectRoute != rhs.RejectRoute {
- return false
- }
- return true
-}
-
//struct for container rpol:actions
type Actions struct {
// original -> rpol:route-disposition
@@ -4048,7 +4061,7 @@ func (lhs *Actions) Equal(rhs *Actions) bool {
if lhs == nil || rhs == nil {
return false
}
- if !lhs.RouteDisposition.Equal(&(rhs.RouteDisposition)) {
+ if lhs.RouteDisposition != rhs.RouteDisposition {
return false
}
if !lhs.IgpActions.Equal(&(rhs.IgpActions)) {
diff --git a/config/default.go b/config/default.go
index 05fe2db8..fc15f046 100644
--- a/config/default.go
+++ b/config/default.go
@@ -216,6 +216,23 @@ func SetDefaultConfigValues(b *BgpConfigSet) error {
return setDefaultConfigValuesWithViper(nil, b)
}
+func setDefaultPolicyConfigValuesWithViper(v *viper.Viper, p *PolicyDefinition) error {
+ stmts, err := extractArray(v.Get("policy.statements"))
+ if err != nil {
+ return err
+ }
+ for i, _ := range p.Statements {
+ vv := viper.New()
+ if len(stmts) > i {
+ vv.Set("statement", stmts[i])
+ }
+ if !vv.IsSet("statement.actions.route-disposition") {
+ p.Statements[i].Actions.RouteDisposition = ROUTE_DISPOSITION_NONE
+ }
+ }
+ return nil
+}
+
func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
if v == nil {
v = viper.New()
@@ -258,5 +275,21 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
}
}
+ list, err = extractArray(v.Get("policy-definitions"))
+ if err != nil {
+ return err
+ }
+
+ for idx, p := range b.PolicyDefinitions {
+ vv := viper.New()
+ if len(list) > idx {
+ vv.Set("policy", list[idx])
+ }
+ if err := setDefaultPolicyConfigValuesWithViper(vv, &p); err != nil {
+ return err
+ }
+ b.PolicyDefinitions[idx] = p
+ }
+
return nil
}
diff --git a/docs/sources/policy.md b/docs/sources/policy.md
index e9d4b8be..0d7f5a05 100644
--- a/docs/sources/policy.md
+++ b/docs/sources/policy.md
@@ -493,8 +493,8 @@ policy-definitions consists of condition and action. Condition part is used to e
[policy-definitions.statements.conditions.bgp-conditions.as-path-length]
operator = "eq"
value = 2
- [policy-definitions.statements.actions.route-disposition]
- accept-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "accept-route"
[policy-definitions.statements.actions.bgp-actions]
set-med = "-200"
[policy-definitions.statements.actions.bgp-actions.set-as-path-prepend]
@@ -562,11 +562,11 @@ policy-definitions consists of condition and action. Condition part is used to e
| operator | operator to compare the length of AS number in AS_PATH attribute. <br> "eq","ge","le" can be used. <br> "eq" means that length of AS number is equal to Value element <br> "ge" means that length of AS number is equal or greater than the Value element <br> "le" means that length of AS number is equal or smaller than the Value element| "eq" |
| value | value used to compare with the length of AS number in AS_PATH attribute | 2 |
- - policy-definitions.statements.actions.route-disposition
+ - policy-definitions.statements.actions
- | Element | Description | Example |
- |--------------|-----------------------------------------------------------------------------------|---------|
- | accept-route | action to accept the route if matches conditions. If true, this route is accepted | true |
+ | Element | Description | Example |
+ |-------------------|---------------------------------------------------------------------------------------------------------------|----------------|
+ | route-disposition | stop following policy/statement evaluation and accept/reject the route:<br> "accept-route" or "reject-route" | "accept-route" |
- policy-definitions.statements.actions.bgp-actions
@@ -618,8 +618,8 @@ policy-definitions consists of condition and action. Condition part is used to e
prefix-set = "ps1"
[policy-definitions.statements.conditions.match-neighbor-set]
neighbor-set = "ns1"
- [policy-definitions.statements.actions.route-disposition]
- reject-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "reject-route"
```
- example 2
@@ -636,8 +636,8 @@ policy-definitions consists of condition and action. Condition part is used to e
prefix-set = "ps1"
[policy-definitions.statements.conditions.match-neighbor-set]
neighbor-set = "ns1"
- [policy-definitions.statements.actions.route-disposition]
- reject-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "reject-route"
# second statement - (2)
[[policy-definitions.statements]]
name = "statement2"
@@ -645,8 +645,8 @@ policy-definitions consists of condition and action. Condition part is used to e
prefix-set = "ps2"
[policy-definitions.statements.conditions.match-neighbor-set]
neighbor-set = "ns2"
- [policy-definitions.statements.actions.route-disposition]
- reject-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "reject-route"
```
- if a route matches the condition inside the first statement(1), GoBGP applies its action and quits the policy evaluation.
@@ -665,8 +665,8 @@ policy-definitions consists of condition and action. Condition part is used to e
prefix-set = "ps1"
[policy-definitions.statements.conditions.match-neighbor-set]
neighbor-set = "ns1"
- [policy-definitions.statements.actions.route-disposition]
- reject-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "reject-route"
# second policy
[[policy-definitions]]
name = "policy2"
@@ -676,8 +676,8 @@ policy-definitions consists of condition and action. Condition part is used to e
prefix-set = "ps2"
[policy-definitions.statements.conditions.match-neighbor-set]
neighbor-set = "ns2"
- [policy-definitions.statements.actions.route-disposition]
- reject-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "reject-route"
```
- example 4
@@ -710,8 +710,8 @@ policy-definitions consists of condition and action. Condition part is used to e
[policy-definitions.statements.conditions.bgp-conditions.as-path-length]
operator = "eq"
value = 2
- [policy-definitions.statements.actions.route-disposition]
- accept-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "accept-route"
[policy-definitions.statements.actions.bgp-actions]
set-med = "-200"
set-next-hop = "10.0.0.1"
@@ -725,6 +725,42 @@ policy-definitions consists of condition and action. Condition part is used to e
communities-list = ["65100:20"]
```
+ - example 5
+ - example of multiple statement
+
+ ```toml
+ # example 5
+ [[policy-definitions]]
+ name = "policy1"
+ [[policy-definitions.statements]]
+ # statement without route-disposition continues to the next statement
+ [policy-definitions.statements.actions.bgp-actions]
+ set-med = "+100"
+ [[policy-definitions.statements]]
+ # if matched with "ps1", reject the route and stop evaluating
+ # following statements
+ [policy-definitions.statements.conditions.match-prefix-set]
+ prefix-set = "ps1"
+ [policy-definitions.statements.actions]
+ route-disposition = "reject-route"
+ [[policy-definitions.statements]]
+ # if matched with "ps2", accept the route and stop evaluating
+ # following statements
+ [policy-definitions.statements.conditions.match-prefix-set]
+ prefix-set = "ps2"
+ [policy-definitions.statements.actions]
+ route-disposition = "accept-route"
+ [[policy-definitions.statements]]
+ # since this is the last statement, if the route matched with "ps3",
+ # add 10 to MED value and continue to the next policy if exists.
+ # If not, default-policy is applied.
+ [policy-definitions.statements.conditions.match-prefix-set]
+ prefix-set = "ps3"
+ [policy-definitions.statements.actions.bgp-actions]
+ set-med = "+10"
+ ```
+
+
---
@@ -749,8 +785,8 @@ default-export-policy = "accept-route"
|-------------------------|---------------------------------------------------------------------------------------------|----------------|
| import-policy | policy-definitions.name for Import policy | "policy1" |
| export-policy | policy-definitions.name for Export policy | "policy2" |
-| default-import-policy | action when the route doesn't match any policy:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
-| default-export-policy | action when the route doesn't match any policy:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
+| default-import-policy | action when the route doesn't match any policy or none of the matched policy specifies `route-disposition`:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
+| default-export-policy | action when the route doesn't match any policy or none of the matched policy specifies `route-disposition`:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
#### <a name="rs-attachment"> 4.2. Attach policy to route-server-client
@@ -785,9 +821,9 @@ The apply-policy has 6 elements.
| import-policy | policy-definitions.name for Import policy | "policy1" |
| export-policy | policy-definitions.name for Export policy | "policy2" |
| in-policy | policy-definitions.name for In policy | "policy3" |
-| default-import-policy | action when the route doesn't match any policy:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
-| default-export-policy | action when the route doesn't match any policy:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
-| default-in-policy | action when the route doesn't match any policy:<br> "accept-route" or "reject-route". default is "accept-route" | "reject-route" |
+| default-import-policy | action when the route doesn't match any policy or none of the matched policy specifies `route-disposition`:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
+| default-export-policy | action when the route doesn't match any policy or none of the matched policy specifies `route-disposition`:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
+| default-in-policy | action when the route doesn't match any policy or none of the matched policy specifies `route-disposition`:<br> "accept-route" or "reject-route". default is "accept-route" | "accept-route" |
@@ -847,8 +883,8 @@ define an import policy for neighbor 10.0.255.2 that drops
[policy-definitions.statements.conditions.match-neighbor-set]
neighbor-set = "ns1"
match-set-options = "any"
- [policy-definitions.statements.actions.route-disposition]
- reject-route = true
+ [policy-definitions.statements.actions]
+ route-disposition = "reject-route"
```
Neighbor 10.0.255.2 has pd2 policy. The pd2 policy consists of ps2 prefix match and ns1 neighbor match. The ps2 specifies 10.33.0.0 and 10.50.0.0 address. The ps2 specifies the mask with **MASK** keyword. **masklength-range** keyword can specify the range of mask length like ```masklength-range 24..26```. The *ns1* specifies neighbor 10.0.255.1.
diff --git a/gobgp/cmd/policy.go b/gobgp/cmd/policy.go
index aa614d50..8ef136d8 100644
--- a/gobgp/cmd/policy.go
+++ b/gobgp/cmd/policy.go
@@ -669,9 +669,9 @@ func modAction(name, op string, args []string) error {
args = args[1:]
switch typ {
case "reject":
- stmt.Actions.RouteDisposition = config.RouteDisposition{RejectRoute: true}
+ stmt.Actions.RouteDisposition = config.ROUTE_DISPOSITION_REJECT_ROUTE
case "accept":
- stmt.Actions.RouteDisposition = config.RouteDisposition{AcceptRoute: true}
+ stmt.Actions.RouteDisposition = config.ROUTE_DISPOSITION_ACCEPT_ROUTE
case "community":
if len(args) < 1 {
return fmt.Errorf("%s community { add | remove | replace } <value>...", usage)
diff --git a/table/policy.go b/table/policy.go
index 1d055b57..994ff4d8 100644
--- a/table/policy.go
+++ b/table/policy.go
@@ -1725,14 +1725,16 @@ func (a *RoutingAction) String() string {
}
func NewRoutingAction(c config.RouteDisposition) (*RoutingAction, error) {
- if c.AcceptRoute == c.RejectRoute && c.AcceptRoute {
- return nil, fmt.Errorf("invalid route disposition")
- } else if !c.AcceptRoute && !c.RejectRoute {
+ var accept bool
+ switch c {
+ case config.RouteDisposition(""), config.ROUTE_DISPOSITION_NONE:
return nil, nil
- }
- accept := false
- if c.AcceptRoute && !c.RejectRoute {
+ case config.ROUTE_DISPOSITION_ACCEPT_ROUTE:
accept = true
+ case config.ROUTE_DISPOSITION_REJECT_ROUTE:
+ accept = false
+ default:
+ return nil, fmt.Errorf("invalid route disposition")
}
return &RoutingAction{
AcceptRoute: accept,
@@ -2341,11 +2343,6 @@ func (s *Statement) Apply(path *Path, options *PolicyOptions) (RouteType, *Path)
}
//Routing action
if s.RouteAction == nil || reflect.ValueOf(s.RouteAction).IsNil() {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Path": path,
- "PolicyName": s.Name,
- }).Warn("route action is nil")
return ROUTE_TYPE_NONE, path
}
p := s.RouteAction.Apply(path, options)
@@ -2399,7 +2396,13 @@ func (s *Statement) ToConfig() *config.Statement {
act := config.Actions{}
if s.RouteAction != nil && !reflect.ValueOf(s.RouteAction).IsNil() {
a := s.RouteAction.(*RoutingAction)
- act.RouteDisposition = config.RouteDisposition{AcceptRoute: a.AcceptRoute, RejectRoute: !a.AcceptRoute}
+ if a.AcceptRoute {
+ act.RouteDisposition = config.ROUTE_DISPOSITION_ACCEPT_ROUTE
+ } else {
+ act.RouteDisposition = config.ROUTE_DISPOSITION_REJECT_ROUTE
+ }
+ } else {
+ act.RouteDisposition = config.ROUTE_DISPOSITION_NONE
}
for _, a := range s.ModActions {
switch a.(type) {
diff --git a/table/policy_test.go b/table/policy_test.go
index c3a04433..6897a227 100644
--- a/table/policy_test.go
+++ b/table/policy_test.go
@@ -2728,11 +2728,12 @@ func createStatement(name, psname, nsname string, accept bool) config.Statement
NeighborSet: nsname,
},
}
+ rd := config.ROUTE_DISPOSITION_REJECT_ROUTE
+ if accept {
+ rd = config.ROUTE_DISPOSITION_ACCEPT_ROUTE
+ }
a := config.Actions{
- RouteDisposition: config.RouteDisposition{
- AcceptRoute: accept,
- RejectRoute: !accept,
- },
+ RouteDisposition: rd,
}
s := config.Statement{
Name: name,
@@ -2940,3 +2941,48 @@ func TestLargeCommunityMatchAction(t *testing.T) {
assert.Equal(t, m.Evaluate(p, nil), true)
}
+
+func TestMultipleStatementPolicy(t *testing.T) {
+ r := NewRoutingPolicy()
+ rp := config.RoutingPolicy{
+ PolicyDefinitions: []config.PolicyDefinition{config.PolicyDefinition{
+ Name: "p1",
+ Statements: []config.Statement{
+ config.Statement{
+ Actions: config.Actions{
+ BgpActions: config.BgpActions{
+ SetMed: "+100",
+ },
+ },
+ },
+ config.Statement{
+ Actions: config.Actions{
+ BgpActions: config.BgpActions{
+ SetLocalPref: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ err := r.reload(rp)
+ assert.Nil(t, err)
+
+ nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0")
+
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ pattrs := []bgp.PathAttributeInterface{origin, aspath, nexthop}
+
+ path := NewPath(nil, nlri, false, pattrs, time.Now(), false)
+
+ pType, newPath := r.policyMap["p1"].Apply(path, nil)
+ assert.Equal(t, ROUTE_TYPE_NONE, pType)
+ med, _ := newPath.GetMed()
+ assert.Equal(t, med, uint32(100))
+ localPref, _ := newPath.GetLocalPref()
+ assert.Equal(t, localPref, uint32(100))
+}
diff --git a/test/scenario_test/route_server_policy_test.py b/test/scenario_test/route_server_policy_test.py
index 6bf02eb0..7188f43c 100644
--- a/test/scenario_test/route_server_policy_test.py
+++ b/test/scenario_test/route_server_policy_test.py
@@ -114,7 +114,7 @@ class ImportPolicy(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -180,7 +180,7 @@ class ExportPolicy(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -266,7 +266,7 @@ class ImportPolicyUpdate(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -313,7 +313,7 @@ class ImportPolicyUpdate(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -393,7 +393,7 @@ class ExportPolicyUpdate(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -440,7 +440,7 @@ class ExportPolicyUpdate(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -536,7 +536,7 @@ class ImportPolicyIPV6(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -605,7 +605,7 @@ class ExportPolicyIPV6(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -687,7 +687,7 @@ class ImportPolicyIPV6Update(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -731,7 +731,7 @@ class ImportPolicyIPV6Update(object):
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
'actions': {
- 'route-disposition': {'reject-route': True}}}
+ 'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -808,7 +808,7 @@ class ExportPolicyIPv6Update(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -851,7 +851,7 @@ class ExportPolicyIPv6Update(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -902,7 +902,7 @@ class ImportPolicyAsPathLengthCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'as-path-length': {'operator': 'ge',
'value': 10}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -962,7 +962,7 @@ class ImportPolicyAsPathCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-as-path-set': {'as-path-set': 'as0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -1014,7 +1014,7 @@ class ImportPolicyAsPathAnyCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-as-path-set': {'as-path-set': 'as0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -1066,7 +1066,7 @@ class ImportPolicyAsPathOriginCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-as-path-set': {'as-path-set': 'as0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -1118,7 +1118,7 @@ class ImportPolicyAsPathOnlyCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-as-path-set': {'as-path-set': 'as0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -1172,7 +1172,7 @@ class ImportPolicyAsPathMismatchCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-community-set': {'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -1232,7 +1232,7 @@ class ImportPolicyCommunityCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-community-set': {'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -1285,7 +1285,7 @@ class ImportPolicyCommunityRegexp(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-community-set': {'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -1346,7 +1346,7 @@ class ImportPolicyCommunityAction(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions': {'match-community-set': {'community-set': 'cs0', 'match-set-options': 'any'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'add',
'set-community-method': {'communities-list': ['65100:20']}}}}}
@@ -1420,7 +1420,7 @@ class ImportPolicyCommunityReplace(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'REPLACE',
'set-community-method': {'communities-list': ['65100:20']}}}}}
@@ -1486,7 +1486,7 @@ class ImportPolicyCommunityRemove(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'REMOVE',
'set-community-method': {'communities-list': ['65100:10', '65100:20']}}}}}
@@ -1570,7 +1570,7 @@ class ImportPolicyCommunityNull(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'REPLACE',
'set-community-method': {'communities-list': []}}}}}
@@ -1644,7 +1644,7 @@ class ExportPolicyCommunityAdd(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'add',
'set-community-method': {'communities-list': ['65100:20']}}}}}
@@ -1717,7 +1717,7 @@ class ExportPolicyCommunityReplace(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'REPLACE',
'set-community-method': {'communities-list': ['65100:20']}}}}}
@@ -1790,7 +1790,7 @@ class ExportPolicyCommunityRemove(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'REMOVE',
'set-community-method': {'communities-list': ['65100:20', '65100:30']}}}}}
@@ -1866,7 +1866,7 @@ class ExportPolicyCommunityNull(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-community': {'options': 'REPLACE',
'set-community-method': {'communities-list': []}}}}}
@@ -1944,7 +1944,7 @@ class ImportPolicyMedReplace(object):
q1 = env.q1
q2 = env.q2
st0 = {'name': 'st0',
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-med': '100'}}}
policy = {'name': 'policy0',
@@ -2005,7 +2005,7 @@ class ImportPolicyMedAdd(object):
q1 = env.q1
q2 = env.q2
st0 = {'name': 'st0',
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-med': '+100'}}}
policy = {'name': 'policy0',
@@ -2066,7 +2066,7 @@ class ImportPolicyMedSub(object):
q1 = env.q1
q2 = env.q2
st0 = {'name': 'st0',
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-med': '-100'}}}
policy = {'name': 'policy0',
@@ -2127,7 +2127,7 @@ class ExportPolicyMedReplace(object):
q1 = env.q1
q2 = env.q2
st0 = {'name': 'st0',
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-med': '100'}}}
policy = {'name': 'policy0',
@@ -2188,7 +2188,7 @@ class ExportPolicyMedAdd(object):
q1 = env.q1
q2 = env.q2
st0 = {'name': 'st0',
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-med': '+100'}}}
policy = {'name': 'policy0',
@@ -2249,7 +2249,7 @@ class ExportPolicyMedSub(object):
q1 = env.q1
q2 = env.q2
st0 = {'name': 'st0',
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-med': '-100'}}}
policy = {'name': 'policy0',
@@ -2314,7 +2314,7 @@ class InPolicyReject(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -2373,7 +2373,7 @@ class InPolicyAccept(object):
st0 = {'name': 'st0',
'conditions':{'bgp-conditions':{'match-community-set':{'community-set': 'cs0'}}},
- 'actions':{'route-disposition': {'accept-route': True}}}
+ 'actions':{'route-disposition': 'accept-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -2448,7 +2448,7 @@ class InPolicyUpdate(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -2496,7 +2496,7 @@ class InPolicyUpdate(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -2556,7 +2556,7 @@ class ExportPolicyAsPathPrepend(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-as-path-prepend': {'repeat-n': 5, 'as': "65005"}}}}
policy = {'name': 'policy0',
@@ -2643,7 +2643,7 @@ class ImportPolicyAsPathPrependLastAS(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-as-path-prepend': {'repeat-n': 5, 'as': "last-as"}}}}
policy = {'name': 'policy0',
@@ -2720,7 +2720,7 @@ class ExportPolicyAsPathPrependLastAS(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']}},
- 'actions': {'route-disposition': {'accept-route': True},
+ 'actions': {'route-disposition': 'accept-route',
'bgp-actions': {'set-as-path-prepend': {'repeat-n': 5, 'as': "last-as"}}}}
policy = {'name': 'policy0',
@@ -2795,7 +2795,7 @@ class ImportPolicyExCommunityOriginCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions':{'match-ext-community-set':{'ext-community-set': 'es0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -2846,7 +2846,7 @@ class ImportPolicyExCommunityTargetCondition(object):
st0 = {'name': 'st0',
'conditions': {'bgp-conditions':{'match-ext-community-set':{'ext-community-set': 'es0'}}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -2899,7 +2899,7 @@ class InPolicyPrefixCondition(object):
st0 = {'name': 'st0',
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -2971,7 +2971,7 @@ class ImportPolicyExCommunityAdd(object):
}
},
'actions': {
- 'route-disposition': {'accept-route': True},
+ 'route-disposition': 'accept-route',
'bgp-actions': {
'set-ext-community': {
'options': 'add',
@@ -3051,7 +3051,7 @@ class ImportPolicyExCommunityAdd2(object):
}
},
'actions': {
- 'route-disposition': {'accept-route': True},
+ 'route-disposition': 'accept-route',
'bgp-actions': {
'set-ext-community': {
'options': 'add',
@@ -3136,7 +3136,7 @@ class ImportPolicyExCommunityMultipleAdd(object):
}
},
'actions': {
- 'route-disposition': {'accept-route': True},
+ 'route-disposition': 'accept-route',
'bgp-actions': {
'set-ext-community': {
'options': 'add',
@@ -3221,7 +3221,7 @@ class ExportPolicyExCommunityAdd(object):
}
},
'actions': {
- 'route-disposition': {'accept-route': True},
+ 'route-disposition': 'accept-route',
'bgp-actions': {
'set-ext-community': {
'options': 'add',
@@ -3318,7 +3318,7 @@ class InPolicyUpdate2(object):
'conditions': {
'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
@@ -3367,7 +3367,7 @@ class InPolicyUpdate2(object):
st0 = {'name': 'st0',
'conditions': {'match-prefix-set': {'prefix-set': ps0['prefix-set-name']},
'match-neighbor-set': {'neighbor-set': ns0['neighbor-set-name']}},
- 'actions': {'route-disposition': {'reject-route': True}}}
+ 'actions': {'route-disposition': 'reject-route'}}
policy = {'name': 'policy0',
'statements': [st0]}
diff --git a/test/scenario_test/route_server_softreset_test.py b/test/scenario_test/route_server_softreset_test.py
index 05e39ba2..63388fd5 100644
--- a/test/scenario_test/route_server_softreset_test.py
+++ b/test/scenario_test/route_server_softreset_test.py
@@ -80,7 +80,7 @@ class GoBGPTestBase(unittest.TestCase):
g1.set_prefix_set(ps0)
st0 = {'conditions': {'match-prefix-set': {'prefix-set': 'ps0'}},
- 'actions': {'route-disposition': {'accept-route': True}}}
+ 'actions': {'route-disposition': 'accept-route'}}
pol0 = {'name': 'pol0', 'statements': [st0]}
diff --git a/tools/config/example_toml.go b/tools/config/example_toml.go
index 11ab2939..62e6b8f6 100644
--- a/tools/config/example_toml.go
+++ b/tools/config/example_toml.go
@@ -156,10 +156,7 @@ func policy() config.RoutingPolicy {
},
},
Actions: config.Actions{
- RouteDisposition: config.RouteDisposition{
- AcceptRoute: false,
- RejectRoute: true,
- },
+ RouteDisposition: "reject-route",
BgpActions: config.BgpActions{
SetCommunity: config.SetCommunity{
SetCommunityMethod: config.SetCommunityMethod{
diff --git a/tools/pyang_plugins/bgpyang2golang.py b/tools/pyang_plugins/bgpyang2golang.py
index f6ea1a86..a7a59866 100644
--- a/tools/pyang_plugins/bgpyang2golang.py
+++ b/tools/pyang_plugins/bgpyang2golang.py
@@ -18,6 +18,7 @@ import optparse
import StringIO
import sys
from pyang import plugin
+from collections import namedtuple
_COPYRIGHT_NOTICE = """
// DO NOT EDIT
@@ -207,6 +208,9 @@ def emit_class_def(ctx, yang_statement, struct_name, prefix):
if is_case(child):
continue
+ if is_choice(child) and is_enum_choice(child):
+ emit_type_name = val_name_go
+
# case leaflist
if is_leaflist(child):
type_obj = child.search_one('type')
@@ -239,7 +243,7 @@ def emit_class_def(ctx, yang_statement, struct_name, prefix):
emit_type_name = '[]'+t.golang_name
# case container
- elif is_container(child) or is_choice(child):
+ elif is_container(child) or (is_choice(child) and not is_enum_choice(child)):
key = child_prefix+':'+container_or_list_name
t = ctx.golang_struct_names[key]
val_name_go = t.golang_name
@@ -380,7 +384,7 @@ def visit_children(ctx, module, children):
t = c.search_one('type')
# define container embeded enums
- if is_leaf(c) and c.search_one('type').arg == 'enumeration':
+ def define_enum(c):
prefix = module.i_prefix
c.path = get_path(c)
c.golang_name = convert_to_golang(c.arg)
@@ -389,12 +393,17 @@ def visit_children(ctx, module, children):
else:
ctx.golang_typedef_map[prefix] = {c.arg: c}
- if is_list(c) or is_container(c) or is_choice(c):
+ if is_leaf(c) and c.search_one('type').arg == 'enumeration':
+ define_enum(c)
+ elif is_list(c) or is_container(c) or is_choice(c):
c.golang_name = convert_to_golang(c.uniq_name)
if is_choice(c):
picks = pickup_choice(c)
c.i_children = picks
+ if is_enum_choice(c):
+ define_enum(c)
+ continue
if ctx.golang_struct_names.get(prefix+':'+c.uniq_name):
ext_c = ctx.golang_struct_names.get(prefix+':'+c.uniq_name)
@@ -504,6 +513,12 @@ def emit_enum(prefix, name, stmt, substmts):
const_prefix = convert_const_prefix(type_name_org)
print >> o, 'const ('
m = {}
+
+ if is_choice(stmt) and is_enum_choice(stmt):
+ n = namedtuple('Statement', ['arg'])
+ n.arg = 'none'
+ substmts = [n] + substmts
+
for sub in substmts:
enum_name = '%s_%s' % (const_prefix, convert_const_prefix(sub.arg))
m[sub.arg.lower()] = enum_name
@@ -580,7 +595,9 @@ def emit_typedef(ctx, module):
t = stmt.search_one('type')
o = StringIO.StringIO()
- if t.arg == 'enumeration':
+ if not t and is_choice(stmt):
+ emit_enum(prefix, type_name_org, stmt, stmt.i_children)
+ elif t.arg == 'enumeration':
emit_enum(prefix, type_name_org, stmt, t.substmts)
elif t.arg == 'union':
print >> o, '// typedef for typedef %s:%s'\
@@ -642,6 +659,13 @@ def is_case(s):
def is_choice(s):
return s.keyword in ['choice']
+def is_enum_choice(s):
+ return all(e.search_one('type').arg in _type_enum_case for e in s.i_children)
+
+_type_enum_case = [
+ 'empty',
+]
+
def is_builtin_type(t):
return t.arg in _type_builtin