diff options
author | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-07-08 14:07:46 +0900 |
---|---|---|
committer | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-07-13 15:41:08 +0900 |
commit | c0d597433f6a3bcd7009fd60806d6b5906faa65d (patch) | |
tree | 192067ae010517cf218d074668d647fa02db211e | |
parent | 1bf1652c08dde3368e098c2f28260cb24f4aa0f8 (diff) |
cli: add aspath prepend support
-rw-r--r-- | api/gobgp.pb.go | 18 | ||||
-rw-r--r-- | api/gobgp.proto | 6 | ||||
-rw-r--r-- | gobgp/common.go | 7 | ||||
-rw-r--r-- | gobgp/policy.go | 58 | ||||
-rw-r--r-- | policy/policy.go | 10 | ||||
-rw-r--r-- | server/server.go | 3 |
6 files changed, 99 insertions, 3 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index b0897927..cd935f84 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -45,6 +45,7 @@ It has these top-level messages: CommunitySet Conditions CommunityAction + AsPrependAction Actions Statement PolicyDefinition @@ -1220,10 +1221,20 @@ func (m *CommunityAction) Reset() { *m = CommunityAction{} } func (m *CommunityAction) String() string { return proto.CompactTextString(m) } func (*CommunityAction) ProtoMessage() {} +type AsPrependAction struct { + As string `protobuf:"bytes,1,opt,name=as" json:"as,omitempty"` + Repeatn uint32 `protobuf:"varint,2,opt,name=repeatn" json:"repeatn,omitempty"` +} + +func (m *AsPrependAction) Reset() { *m = AsPrependAction{} } +func (m *AsPrependAction) String() string { return proto.CompactTextString(m) } +func (*AsPrependAction) ProtoMessage() {} + type Actions struct { RouteAction string `protobuf:"bytes,1,opt,name=route_action" json:"route_action,omitempty"` Community *CommunityAction `protobuf:"bytes,2,opt,name=community" json:"community,omitempty"` Med string `protobuf:"bytes,3,opt,name=med" json:"med,omitempty"` + AsPrepend *AsPrependAction `protobuf:"bytes,4,opt,name=as_prepend" json:"as_prepend,omitempty"` } func (m *Actions) Reset() { *m = Actions{} } @@ -1237,6 +1248,13 @@ func (m *Actions) GetCommunity() *CommunityAction { return nil } +func (m *Actions) GetAsPrepend() *AsPrependAction { + if m != nil { + return m.AsPrepend + } + return nil +} + type Statement struct { StatementNeme string `protobuf:"bytes,1,opt,name=statement_neme" json:"statement_neme,omitempty"` Conditions *Conditions `protobuf:"bytes,2,opt,name=conditions" json:"conditions,omitempty"` diff --git a/api/gobgp.proto b/api/gobgp.proto index 677ee963..b0fa4714 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -448,10 +448,16 @@ message CommunityAction { string options = 2; } +message AsPrependAction { + string as = 1; + uint32 repeatn = 2; +} + message Actions { string route_action = 1; CommunityAction community = 2; string med = 3; + AsPrependAction as_prepend = 4; } message Statement { diff --git a/gobgp/common.go b/gobgp/common.go index f2533c37..2f17faa3 100644 --- a/gobgp/common.go +++ b/gobgp/common.go @@ -74,9 +74,10 @@ var conditionOpts struct { } var actionOpts struct { - RouteAction string `long:"route-action" description:"specifying a route action of policy (accept | reject)"` - CommunityAction string `long:"community" description:"specifying a community action of policy"` - MedAction string `long:"med" description:"specifying a med action of policy"` + RouteAction string `long:"route-action" description:"specifying a route action of policy (accept | reject)"` + CommunityAction string `long:"community" description:"specifying a community action of policy"` + MedAction string `long:"med" description:"specifying a med action of policy"` + AsPathPrependAction string `long:"as-prepend" description:"specifying a as-prepend action of policy"` } func formatTimedelta(d int64) string { diff --git a/gobgp/policy.go b/gobgp/policy.go index b8ea2e01..61298748 100644 --- a/gobgp/policy.go +++ b/gobgp/policy.go @@ -816,6 +816,14 @@ func showPolicyStatement(head string, pd *api.PolicyDefinition) { } fmt.Printf("%s Community: %s\n", head, communityAction) fmt.Printf("%s Med: %s\n", head, st.Actions.Med) + + asn := "" + repeat := "" + if st.Actions.AsPrepend.As != "" { + asn = st.Actions.AsPrepend.As + repeat = fmt.Sprintf("%d", st.Actions.AsPrepend.Repeatn) + } + fmt.Printf("%s AsPrepend: %s %s\n", head, asn, repeat) fmt.Printf("%s %s\n", head, st.Actions.RouteAction) } @@ -999,6 +1007,31 @@ func parseCommunityAction(communityStr string) (*api.CommunityAction, error) { return communityAction, nil } +func parseAsPrependAction(communityStr string) (*api.AsPrependAction, error) { + regStr, _ := regexp.Compile("^([0-9]+|last-as),([0-9]+)$") + group := regStr.FindStringSubmatch(communityStr) + + as := group[1] + if as != "last-as" { + _, e := strconv.ParseUint(as, 10, 32) + if e != nil { + return nil, fmt.Errorf("%s", "invalid as number") + } + } + + repeatn, e := strconv.ParseUint(group[2], 10, 8) + if e != nil { + return nil, fmt.Errorf("%s", "invalid repeat count") + } + + asprependAction := &api.AsPrependAction{ + As: as, + Repeatn: uint32(repeatn), + } + + return asprependAction, nil +} + func checkMedAction(medStr string) error { regMed, _ := regexp.Compile("^(\\+|\\-)?([0-9]+)$") if !regMed.MatchString(medStr) { @@ -1009,6 +1042,16 @@ func checkMedAction(medStr string) error { return nil } +func checkAsPrependAction(asStr string) error { + regPrepend, _ := regexp.Compile("^([0-9]+|last-as),([0-9]+)$") + if !regPrepend.MatchString(asStr) { + e := fmt.Sprintf("invalid format: %s\n", asStr) + e += "please enter as <AS>,<repeat count>" + return fmt.Errorf("%s", e) + } + return nil +} + func parseActions() (*api.Actions, error) { actions := &api.Actions{} if actionOpts.RouteAction != "" { @@ -1033,6 +1076,20 @@ func parseActions() (*api.Actions, error) { } actions.Med = actionOpts.MedAction } + if actionOpts.AsPathPrependAction != "" { + + s := actionOpts.AsPathPrependAction + e := checkAsPrependAction(s) + if e != nil { + return nil, e + } + + p, e := parseAsPrependAction(s) + if e != nil { + return nil, e + } + actions.AsPrepend = p + } return actions, nil } @@ -1111,6 +1168,7 @@ func NewPolicyAddCmd(v string, mod func(string, []string) error) *cobra.Command policyAddCmd.Flags().StringVarP(&actionOpts.RouteAction, "a-route", "", "", "a route action of policy action (accept | reject)") policyAddCmd.Flags().StringVarP(&actionOpts.CommunityAction, "a-community", "", "", "a community of policy action") policyAddCmd.Flags().StringVarP(&actionOpts.MedAction, "a-med", "", "", "a med of policy action") + policyAddCmd.Flags().StringVarP(&actionOpts.AsPathPrependAction, "a-asprepend", "", "", "aspath prepend for policy action") } return policyAddCmd diff --git a/policy/policy.go b/policy/policy.go index b641b7a4..788f4a7a 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -1621,10 +1621,16 @@ func ActionsToApiStruct(conActions config.Actions) *api.Actions { Options: conActions.BgpActions.SetCommunity.Options, } medAction := fmt.Sprintf("%s", conActions.BgpActions.SetMed) + asprependAction := &api.AsPrependAction{ + conActions.BgpActions.SetAsPathPrepend.As, + uint32(conActions.BgpActions.SetAsPathPrepend.RepeatN), + } + resActions := &api.Actions{ RouteAction: action, Community: communityAction, Med: medAction, + AsPrepend: asprependAction, } return resActions } @@ -1641,6 +1647,10 @@ func ActionsToConfigStruct(reqActions *api.Actions) config.Actions { if reqActions.Med != "" { actions.BgpActions.SetMed = config.BgpSetMedType(reqActions.Med) } + if reqActions.AsPrepend != nil { + actions.BgpActions.SetAsPathPrepend.As = reqActions.AsPrepend.As + actions.BgpActions.SetAsPathPrepend.RepeatN = uint8(reqActions.AsPrepend.Repeatn) + } switch reqActions.RouteAction { case ROUTE_ACCEPT: diff --git a/server/server.go b/server/server.go index 52c0d3ac..e0b0dcef 100644 --- a/server/server.go +++ b/server/server.go @@ -1563,6 +1563,9 @@ func (server *BgpServer) handleGrpcAddPolicy(grpcReq *GrpcRequest) { if reqActions.Med != "" { conStatement.Actions.BgpActions.SetMed = statement.Actions.BgpActions.SetMed } + if reqActions.AsPrepend.As != "" { + conStatement.Actions.BgpActions.SetAsPathPrepend = statement.Actions.BgpActions.SetAsPathPrepend + } } } server.routingPolicy.PolicyDefinitionList = conPolicyList |