summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp>2015-07-08 14:07:46 +0900
committerHiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp>2015-07-13 15:41:08 +0900
commitc0d597433f6a3bcd7009fd60806d6b5906faa65d (patch)
tree192067ae010517cf218d074668d647fa02db211e
parent1bf1652c08dde3368e098c2f28260cb24f4aa0f8 (diff)
cli: add aspath prepend support
-rw-r--r--api/gobgp.pb.go18
-rw-r--r--api/gobgp.proto6
-rw-r--r--gobgp/common.go7
-rw-r--r--gobgp/policy.go58
-rw-r--r--policy/policy.go10
-rw-r--r--server/server.go3
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