summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/gobgp.pb.go87
-rw-r--r--api/gobgp.proto2
-rw-r--r--gobgp/cmd/common.go1
-rw-r--r--gobgp/cmd/policy.go155
-rw-r--r--server/grpc_server.go52
-rw-r--r--server/server.go29
-rw-r--r--table/policy.go10
7 files changed, 266 insertions, 70 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index 3b583fe7..d3bdc1e4 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -749,6 +749,8 @@ type GobgpApiClient interface {
GetDefinedSet(ctx context.Context, in *DefinedSet, opts ...grpc.CallOption) (*DefinedSet, error)
GetDefinedSets(ctx context.Context, in *DefinedSet, opts ...grpc.CallOption) (GobgpApi_GetDefinedSetsClient, error)
ModDefinedSet(ctx context.Context, in *ModDefinedSetArguments, opts ...grpc.CallOption) (*Error, error)
+ GetStatement(ctx context.Context, in *Statement, opts ...grpc.CallOption) (*Statement, error)
+ GetStatements(ctx context.Context, in *Statement, opts ...grpc.CallOption) (GobgpApi_GetStatementsClient, error)
}
type gobgpApiClient struct {
@@ -1292,6 +1294,47 @@ func (c *gobgpApiClient) ModDefinedSet(ctx context.Context, in *ModDefinedSetArg
return out, nil
}
+func (c *gobgpApiClient) GetStatement(ctx context.Context, in *Statement, opts ...grpc.CallOption) (*Statement, error) {
+ out := new(Statement)
+ err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/GetStatement", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *gobgpApiClient) GetStatements(ctx context.Context, in *Statement, opts ...grpc.CallOption) (GobgpApi_GetStatementsClient, error) {
+ stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[13], c.cc, "/gobgpapi.GobgpApi/GetStatements", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &gobgpApiGetStatementsClient{stream}
+ if err := x.ClientStream.SendMsg(in); err != nil {
+ return nil, err
+ }
+ if err := x.ClientStream.CloseSend(); err != nil {
+ return nil, err
+ }
+ return x, nil
+}
+
+type GobgpApi_GetStatementsClient interface {
+ Recv() (*Statement, error)
+ grpc.ClientStream
+}
+
+type gobgpApiGetStatementsClient struct {
+ grpc.ClientStream
+}
+
+func (x *gobgpApiGetStatementsClient) Recv() (*Statement, error) {
+ m := new(Statement)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
// Server API for GobgpApi service
type GobgpApiServer interface {
@@ -1321,6 +1364,8 @@ type GobgpApiServer interface {
GetDefinedSet(context.Context, *DefinedSet) (*DefinedSet, error)
GetDefinedSets(*DefinedSet, GobgpApi_GetDefinedSetsServer) error
ModDefinedSet(context.Context, *ModDefinedSetArguments) (*Error, error)
+ GetStatement(context.Context, *Statement) (*Statement, error)
+ GetStatements(*Statement, GobgpApi_GetStatementsServer) error
}
func RegisterGobgpApiServer(s *grpc.Server, srv GobgpApiServer) {
@@ -1771,6 +1816,39 @@ func _GobgpApi_ModDefinedSet_Handler(srv interface{}, ctx context.Context, dec f
return out, nil
}
+func _GobgpApi_GetStatement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
+ in := new(Statement)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ out, err := srv.(GobgpApiServer).GetStatement(ctx, in)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func _GobgpApi_GetStatements_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(Statement)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(GobgpApiServer).GetStatements(m, &gobgpApiGetStatementsServer{stream})
+}
+
+type GobgpApi_GetStatementsServer interface {
+ Send(*Statement) error
+ grpc.ServerStream
+}
+
+type gobgpApiGetStatementsServer struct {
+ grpc.ServerStream
+}
+
+func (x *gobgpApiGetStatementsServer) Send(m *Statement) error {
+ return x.ServerStream.SendMsg(m)
+}
+
var _GobgpApi_serviceDesc = grpc.ServiceDesc{
ServiceName: "gobgpapi.GobgpApi",
HandlerType: (*GobgpApiServer)(nil),
@@ -1827,6 +1905,10 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{
MethodName: "ModDefinedSet",
Handler: _GobgpApi_ModDefinedSet_Handler,
},
+ {
+ MethodName: "GetStatement",
+ Handler: _GobgpApi_GetStatement_Handler,
+ },
},
Streams: []grpc.StreamDesc{
{
@@ -1896,5 +1978,10 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{
Handler: _GobgpApi_GetDefinedSets_Handler,
ServerStreams: true,
},
+ {
+ StreamName: "GetStatements",
+ Handler: _GobgpApi_GetStatements_Handler,
+ ServerStreams: true,
+ },
},
}
diff --git a/api/gobgp.proto b/api/gobgp.proto
index f6b59356..ad070e60 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -46,6 +46,8 @@ service GobgpApi {
rpc GetDefinedSet(DefinedSet) returns (DefinedSet) {}
rpc GetDefinedSets(DefinedSet) returns (stream DefinedSet) {}
rpc ModDefinedSet(ModDefinedSetArguments) returns (Error) {}
+ rpc GetStatement(Statement) returns (Statement) {}
+ rpc GetStatements(Statement) returns (stream Statement) {}
}
message Error {
diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go
index 0b6ca6ff..54bf07ea 100644
--- a/gobgp/cmd/common.go
+++ b/gobgp/cmd/common.go
@@ -66,6 +66,7 @@ const (
CMD_VRF = "vrf"
CMD_ACCEPTED = "accepted"
CMD_REJECTED = "rejected"
+ CMD_STATEMENT = "statement"
)
var subOpts struct {
diff --git a/gobgp/cmd/policy.go b/gobgp/cmd/policy.go
index 2b4ecbc6..441c1ff9 100644
--- a/gobgp/cmd/policy.go
+++ b/gobgp/cmd/policy.go
@@ -399,75 +399,78 @@ func mod(settype string, modtype string, args []string) error {
return err
}
-func showPolicyStatement(indent int, pd *api.PolicyDefinition) {
+func printStatement(indent int, s *api.Statement) {
sIndent := func(indent int) string {
return strings.Repeat(" ", indent)
}
- for _, st := range pd.Statements {
- fmt.Printf("%sStatementName %s:\n", sIndent(indent), st.Name)
- fmt.Printf("%sConditions:\n", sIndent(indent+2))
+ fmt.Printf("%sStatementName %s:\n", sIndent(indent), s.Name)
+ fmt.Printf("%sConditions:\n", sIndent(indent+2))
- ps := st.Conditions.PrefixSet
- if ps != nil {
- fmt.Printf("%sPrefixSet: %s %s\n", sIndent(indent+4), table.MatchOption(ps.Option), ps.Name)
- }
+ ps := s.Conditions.PrefixSet
+ if ps != nil {
+ fmt.Printf("%sPrefixSet: %s %s\n", sIndent(indent+4), table.MatchOption(ps.Option), ps.Name)
+ }
- ns := st.Conditions.NeighborSet
- if ns != nil {
- fmt.Printf("%sNeighborSet: %s %s\n", sIndent(indent+4), table.MatchOption(ns.Option), ns.Name)
- }
+ ns := s.Conditions.NeighborSet
+ if ns != nil {
+ fmt.Printf("%sNeighborSet: %s %s\n", sIndent(indent+4), table.MatchOption(ns.Option), ns.Name)
+ }
- aps := st.Conditions.AsPathSet
- if aps != nil {
- fmt.Printf("%sAsPathSet: %s %s\n", sIndent(indent+4), table.MatchOption(aps.Option), aps.Name)
- }
+ aps := s.Conditions.AsPathSet
+ if aps != nil {
+ fmt.Printf("%sAsPathSet: %s %s\n", sIndent(indent+4), table.MatchOption(aps.Option), aps.Name)
+ }
- cs := st.Conditions.CommunitySet
- if cs != nil {
- fmt.Printf("%sCommunitySet: %s %s\n", sIndent(indent+4), table.MatchOption(cs.Option), cs.Name)
- }
+ cs := s.Conditions.CommunitySet
+ if cs != nil {
+ fmt.Printf("%sCommunitySet: %s %s\n", sIndent(indent+4), table.MatchOption(cs.Option), cs.Name)
+ }
- ecs := st.Conditions.ExtCommunitySet
- if ecs != nil {
- fmt.Printf("%sExtCommunitySet: %s %s\n", sIndent(indent+4), table.MatchOption(ecs.Option), ecs.Name)
- }
+ ecs := s.Conditions.ExtCommunitySet
+ if ecs != nil {
+ fmt.Printf("%sExtCommunitySet: %s %s\n", sIndent(indent+4), table.MatchOption(ecs.Option), ecs.Name)
+ }
- asPathLentgh := st.Conditions.AsPathLength
- if asPathLentgh != nil {
- fmt.Printf("%sAsPathLength: %s %s\n", sIndent(indent+4), asPathLentgh.Type, asPathLentgh.Length)
- }
- fmt.Printf("%sActions:\n", sIndent(indent+2))
+ asPathLentgh := s.Conditions.AsPathLength
+ if asPathLentgh != nil {
+ fmt.Printf("%sAsPathLength: %s %s\n", sIndent(indent+4), asPathLentgh.Type, asPathLentgh.Length)
+ }
+ fmt.Printf("%sActions:\n", sIndent(indent+2))
- formatComAction := func(c *api.CommunityAction) string {
- option := table.CommunityOptionNameMap[config.BgpSetCommunityOptionType(c.Option)]
- if len(c.Communities) != 0 {
- communities := strings.Join(c.Communities, ",")
- option = fmt.Sprintf("%s[%s]", option, communities)
- }
- return option
- }
- if st.Actions.Community != nil {
- fmt.Printf("%sCommunity: %s\n", sIndent(indent+4), formatComAction(st.Actions.Community))
+ formatComAction := func(c *api.CommunityAction) string {
+ option := table.CommunityOptionNameMap[config.BgpSetCommunityOptionType(c.Option)]
+ if len(c.Communities) != 0 {
+ communities := strings.Join(c.Communities, ",")
+ option = fmt.Sprintf("%s[%s]", option, communities)
}
- if st.Actions.ExtCommunity != nil {
- fmt.Printf("%sExtCommunity: %s\n", sIndent(indent+4), formatComAction(st.Actions.ExtCommunity))
- }
- if st.Actions.Med != nil {
- fmt.Printf("%sMed: %s\n", sIndent(indent+4), st.Actions.Med.Value)
+ return option
+ }
+ if s.Actions.Community != nil {
+ fmt.Printf("%sCommunity: %s\n", sIndent(indent+4), formatComAction(s.Actions.Community))
+ }
+ if s.Actions.ExtCommunity != nil {
+ fmt.Printf("%sExtCommunity: %s\n", sIndent(indent+4), formatComAction(s.Actions.ExtCommunity))
+ }
+ if s.Actions.Med != nil {
+ fmt.Printf("%sMed: %s\n", sIndent(indent+4), s.Actions.Med.Value)
+ }
+ if s.Actions.AsPrepend != nil {
+ var asn string
+ if s.Actions.AsPrepend.UseLeftMost {
+ asn = "left-most"
+ } else {
+ asn = fmt.Sprintf("%d", s.Actions.AsPrepend.Asn)
}
- if st.Actions.AsPrepend != nil {
- var asn string
- if st.Actions.AsPrepend.UseLeftMost {
- asn = "left-most"
- } else {
- asn = fmt.Sprintf("%d", st.Actions.AsPrepend.Asn)
- }
- fmt.Printf("%sAsPrepend: %s %d\n", sIndent(indent+4), asn, st.Actions.AsPrepend.Repeat)
- }
- fmt.Printf("%s%s\n", sIndent(indent+4), st.Actions.RouteAction)
+ fmt.Printf("%sAsPrepend: %s %d\n", sIndent(indent+4), asn, s.Actions.AsPrepend.Repeat)
}
+ fmt.Printf("%s%s\n", sIndent(indent+4), s.Actions.RouteAction)
+}
+func showPolicyStatement(indent int, pd *api.PolicyDefinition) {
+ for _, s := range pd.Statements {
+ printStatement(indent, s)
+ }
}
func showPolicyRoutePolicies() error {
@@ -872,6 +875,39 @@ func modPolicyRoutePolicy(modtype string, eArgs []string) error {
return nil
}
+func showStatement(args []string) error {
+ m := []*api.Statement{}
+ if len(args) > 0 {
+ arg := &api.Statement{
+ Name: args[0],
+ }
+ p, e := client.GetStatement(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+ m = append(m, p)
+ } else {
+ arg := &api.Statement{}
+ stream, e := client.GetStatements(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+ for {
+ p, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ m = append(m, p)
+ }
+ }
+ for _, s := range m {
+ printStatement(0, s)
+ }
+ return nil
+}
+
func NewPolicyCmd() *cobra.Command {
policyCmd := &cobra.Command{
Use: CMD_POLICY,
@@ -910,5 +946,16 @@ func NewPolicyCmd() *cobra.Command {
}
policyCmd.AddCommand(cmd)
}
+
+ cmd := &cobra.Command{
+ Use: CMD_STATEMENT,
+ Run: func(cmd *cobra.Command, args []string) {
+ if err := showStatement(args); err != nil {
+ fmt.Println(err)
+ }
+ },
+ }
+ policyCmd.AddCommand(cmd)
+
return policyCmd
}
diff --git a/server/grpc_server.go b/server/grpc_server.go
index 1ed56144..6753417b 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -61,6 +61,7 @@ const (
REQ_GLOBAL_POLICY
REQ_DEFINED_SET
REQ_MOD_DEFINED_SET
+ REQ_STATEMENT
)
const GRPC_PORT = 8080
@@ -419,11 +420,20 @@ func (s *Server) GetVrfs(arg *api.Arguments, stream api.GobgpApi_GetVrfsServer)
})
}
-func (s *Server) ModVrf(ctx context.Context, arg *api.ModVrfArguments) (*api.Error, error) {
- none := &api.Error{}
- req := NewGrpcRequest(REQ_VRF_MOD, "", bgp.RouteFamily(0), arg)
+func (s *Server) get(typ int, d interface{}) (interface{}, error) {
+ req := NewGrpcRequest(typ, "", bgp.RouteFamily(0), d)
s.bgpServerCh <- req
+ res := <-req.ResponseCh
+ if err := res.Err(); err != nil {
+ return nil, err
+ }
+ return res.Data, nil
+}
+func (s *Server) mod(typ int, d interface{}) (*api.Error, error) {
+ none := &api.Error{}
+ req := NewGrpcRequest(typ, "", bgp.RouteFamily(0), d)
+ s.bgpServerCh <- req
res := <-req.ResponseCh
if err := res.Err(); err != nil {
return none, err
@@ -431,34 +441,44 @@ func (s *Server) ModVrf(ctx context.Context, arg *api.ModVrfArguments) (*api.Err
return none, nil
}
+func (s *Server) ModVrf(ctx context.Context, arg *api.ModVrfArguments) (*api.Error, error) {
+ return s.mod(REQ_VRF_MOD, arg)
+}
+
func (s *Server) GetDefinedSet(ctx context.Context, arg *api.DefinedSet) (*api.DefinedSet, error) {
- req := NewGrpcRequest(REQ_DEFINED_SET, "", bgp.RouteFamily(0), arg)
- s.bgpServerCh <- req
- res := <-req.ResponseCh
- if err := res.Err(); err != nil {
+ d, err := s.get(REQ_DEFINED_SET, arg)
+ if err != nil {
return nil, err
}
- return res.Data.(*api.DefinedSet), nil
+ return d.(*api.DefinedSet), nil
}
func (s *Server) GetDefinedSets(arg *api.DefinedSet, stream api.GobgpApi_GetDefinedSetsServer) error {
req := NewGrpcRequest(REQ_DEFINED_SET, "", bgp.RouteFamily(0), arg)
s.bgpServerCh <- req
-
return handleMultipleResponses(req, func(res *GrpcResponse) error {
return stream.Send(res.Data.(*api.DefinedSet))
})
}
func (s *Server) ModDefinedSet(ctx context.Context, arg *api.ModDefinedSetArguments) (*api.Error, error) {
- none := &api.Error{}
- req := NewGrpcRequest(REQ_MOD_DEFINED_SET, "", bgp.RouteFamily(0), arg)
- s.bgpServerCh <- req
- res := <-req.ResponseCh
- if err := res.Err(); err != nil {
- return none, err
+ return s.mod(REQ_MOD_DEFINED_SET, arg)
+}
+
+func (s *Server) GetStatement(ctx context.Context, arg *api.Statement) (*api.Statement, error) {
+ d, err := s.get(REQ_STATEMENT, arg)
+ if err != nil {
+ return nil, err
}
- return none, nil
+ return d.(*api.Statement), nil
+}
+
+func (s *Server) GetStatements(arg *api.Statement, stream api.GobgpApi_GetStatementsServer) error {
+ req := NewGrpcRequest(REQ_STATEMENT, "", bgp.RouteFamily(0), arg)
+ s.bgpServerCh <- req
+ return handleMultipleResponses(req, func(res *GrpcResponse) error {
+ return stream.Send(res.Data.(*api.Statement))
+ })
}
type GrpcRequest struct {
diff --git a/server/server.go b/server/server.go
index 18c2693e..e25d314f 100644
--- a/server/server.go
+++ b/server/server.go
@@ -1643,6 +1643,13 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
ResponseErr: err,
}
close(grpcReq.ResponseCh)
+ case REQ_STATEMENT:
+ if err := server.handleGrpcGetStatement(grpcReq); err != nil {
+ grpcReq.ResponseCh <- &GrpcResponse{
+ ResponseErr: err,
+ }
+ }
+ close(grpcReq.ResponseCh)
case REQ_POLICY_ROUTEPOLICY, REQ_POLICY_ROUTEPOLICIES:
info := server.policy.PolicyMap
typ := grpcReq.RequestType
@@ -1754,6 +1761,28 @@ func (server *BgpServer) handleGrpcModDefinedSet(grpcReq *GrpcRequest) error {
return err
}
+func (server *BgpServer) handleGrpcGetStatement(grpcReq *GrpcRequest) error {
+ arg := grpcReq.Data.(*api.Statement)
+ name := arg.Name
+ found := false
+ for _, s := range server.policy.StatementMap {
+ if name != "" && name != s.Name {
+ continue
+ }
+ grpcReq.ResponseCh <- &GrpcResponse{
+ Data: s.ToApiStruct(),
+ }
+ found = true
+ if name != "" {
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("not found %s", name)
+ }
+ return nil
+}
+
func (server *BgpServer) handleMrt(grpcReq *GrpcRequest) {
now := uint32(time.Now().Unix())
view := ""
diff --git a/table/policy.go b/table/policy.go
index 97277f6f..8375faab 100644
--- a/table/policy.go
+++ b/table/policy.go
@@ -2053,6 +2053,7 @@ func NewPolicy(c config.PolicyDefinition, dmap DefinedSetMap) (*Policy, error) {
type RoutingPolicy struct {
DefinedSetMap DefinedSetMap
PolicyMap map[string]*Policy
+ StatementMap map[string]*Statement
}
func (r *RoutingPolicy) InUse(d DefinedSet) bool {
@@ -2122,16 +2123,25 @@ func NewRoutingPolicy(c config.RoutingPolicy) (*RoutingPolicy, error) {
dmap[DEFINED_TYPE_EXT_COMMUNITY][y.Name()] = y
}
pmap := make(map[string]*Policy)
+ smap := make(map[string]*Statement)
for _, x := range c.PolicyDefinitions.PolicyDefinitionList {
y, err := NewPolicy(x, dmap)
if err != nil {
return nil, err
}
pmap[y.Name()] = y
+ for _, s := range y.Statements {
+ _, ok := smap[s.Name]
+ if ok {
+ return nil, fmt.Errorf("duplicated statement name. statement name must be unique.")
+ }
+ smap[s.Name] = s
+ }
}
return &RoutingPolicy{
DefinedSetMap: dmap,
PolicyMap: pmap,
+ StatementMap: smap,
}, nil
}