summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/gobgp.pb.go81
-rw-r--r--api/gobgp.proto12
-rw-r--r--gobgp/cmd/global.go49
-rw-r--r--gobgpd/main.go10
-rw-r--r--server/grpc_server.go14
-rw-r--r--server/server.go70
6 files changed, 226 insertions, 10 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index d856e19d..e369357c 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -19,6 +19,7 @@ It has these top-level messages:
ModStatementArguments
ModPolicyArguments
ModPolicyAssignmentArguments
+ ModGlobalConfigArguments
Path
Destination
Peer
@@ -68,6 +69,7 @@ It has these top-level messages:
RPKI
ROA
Vrf
+ Global
*/
package gobgpapi
@@ -478,6 +480,22 @@ func (m *ModPolicyAssignmentArguments) GetAssignment() *PolicyAssignment {
return nil
}
+type ModGlobalConfigArguments struct {
+ Operation Operation `protobuf:"varint,1,opt,name=operation,enum=gobgpapi.Operation" json:"operation,omitempty"`
+ Global *Global `protobuf:"bytes,2,opt,name=global" json:"global,omitempty"`
+}
+
+func (m *ModGlobalConfigArguments) Reset() { *m = ModGlobalConfigArguments{} }
+func (m *ModGlobalConfigArguments) String() string { return proto.CompactTextString(m) }
+func (*ModGlobalConfigArguments) ProtoMessage() {}
+
+func (m *ModGlobalConfigArguments) GetGlobal() *Global {
+ if m != nil {
+ return m.Global
+ }
+ return nil
+}
+
type Path struct {
Nlri []byte `protobuf:"bytes,1,opt,name=nlri,proto3" json:"nlri,omitempty"`
Pattrs [][]byte `protobuf:"bytes,2,rep,name=pattrs,proto3" json:"pattrs,omitempty"`
@@ -1454,6 +1472,15 @@ func (m *Vrf) Reset() { *m = Vrf{} }
func (m *Vrf) String() string { return proto.CompactTextString(m) }
func (*Vrf) ProtoMessage() {}
+type Global struct {
+ As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"`
+ RouterId string `protobuf:"bytes,2,opt,name=router_id" json:"router_id,omitempty"`
+}
+
+func (m *Global) Reset() { *m = Global{} }
+func (m *Global) String() string { return proto.CompactTextString(m) }
+func (*Global) ProtoMessage() {}
+
func init() {
proto.RegisterEnum("gobgpapi.Resource", Resource_name, Resource_value)
proto.RegisterEnum("gobgpapi.Operation", Operation_name, Operation_value)
@@ -1474,6 +1501,8 @@ var _ grpc.ClientConn
// Client API for GobgpApi service
type GobgpApiClient interface {
+ GetGlobalConfig(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Global, error)
+ ModGlobalConfig(ctx context.Context, in *ModGlobalConfigArguments, opts ...grpc.CallOption) (*Error, error)
GetNeighbors(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetNeighborsClient, error)
GetNeighbor(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Peer, error)
ModNeighbor(ctx context.Context, in *ModNeighborArguments, opts ...grpc.CallOption) (*Error, error)
@@ -1514,6 +1543,24 @@ func NewGobgpApiClient(cc *grpc.ClientConn) GobgpApiClient {
return &gobgpApiClient{cc}
}
+func (c *gobgpApiClient) GetGlobalConfig(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Global, error) {
+ out := new(Global)
+ err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/GetGlobalConfig", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *gobgpApiClient) ModGlobalConfig(ctx context.Context, in *ModGlobalConfigArguments, opts ...grpc.CallOption) (*Error, error) {
+ out := new(Error)
+ err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/ModGlobalConfig", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func (c *gobgpApiClient) GetNeighbors(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetNeighborsClient, error) {
stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[0], c.cc, "/gobgpapi.GobgpApi/GetNeighbors", opts...)
if err != nil {
@@ -2065,6 +2112,8 @@ func (c *gobgpApiClient) ModPolicyAssignment(ctx context.Context, in *ModPolicyA
// Server API for GobgpApi service
type GobgpApiServer interface {
+ GetGlobalConfig(context.Context, *Arguments) (*Global, error)
+ ModGlobalConfig(context.Context, *ModGlobalConfigArguments) (*Error, error)
GetNeighbors(*Arguments, GobgpApi_GetNeighborsServer) error
GetNeighbor(context.Context, *Arguments) (*Peer, error)
ModNeighbor(context.Context, *ModNeighborArguments) (*Error, error)
@@ -2101,6 +2150,30 @@ func RegisterGobgpApiServer(s *grpc.Server, srv GobgpApiServer) {
s.RegisterService(&_GobgpApi_serviceDesc, srv)
}
+func _GobgpApi_GetGlobalConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
+ in := new(Arguments)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ out, err := srv.(GobgpApiServer).GetGlobalConfig(ctx, in)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func _GobgpApi_ModGlobalConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
+ in := new(ModGlobalConfigArguments)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ out, err := srv.(GobgpApiServer).ModGlobalConfig(ctx, in)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func _GobgpApi_GetNeighbors_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(Arguments)
if err := stream.RecvMsg(m); err != nil {
@@ -2579,6 +2652,14 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{
HandlerType: (*GobgpApiServer)(nil),
Methods: []grpc.MethodDesc{
{
+ MethodName: "GetGlobalConfig",
+ Handler: _GobgpApi_GetGlobalConfig_Handler,
+ },
+ {
+ MethodName: "ModGlobalConfig",
+ Handler: _GobgpApi_ModGlobalConfig_Handler,
+ },
+ {
MethodName: "GetNeighbor",
Handler: _GobgpApi_GetNeighbor_Handler,
},
diff --git a/api/gobgp.proto b/api/gobgp.proto
index 98085a10..95ebeb8b 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -20,6 +20,8 @@ package gobgpapi;
// Interface exported by the server.
service GobgpApi {
+ rpc GetGlobalConfig(Arguments) returns (Global) {}
+ rpc ModGlobalConfig(ModGlobalConfigArguments) returns (Error) {}
rpc GetNeighbors(Arguments) returns (stream Peer) {}
rpc GetNeighbor(Arguments) returns (Peer) {}
rpc ModNeighbor(ModNeighborArguments) returns(Error) {}
@@ -117,6 +119,11 @@ message ModPolicyAssignmentArguments {
PolicyAssignment assignment = 2;
}
+message ModGlobalConfigArguments {
+ Operation operation = 1;
+ Global global = 2;
+}
+
enum Resource {
GLOBAL = 0;
LOCAL = 1;
@@ -528,3 +535,8 @@ message Vrf {
repeated bytes import_rt = 3;
repeated bytes export_rt = 4;
}
+
+message Global {
+ uint32 as = 1;
+ string router_id = 2;
+}
diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go
index e9333d81..3152d01d 100644
--- a/gobgp/cmd/global.go
+++ b/gobgp/cmd/global.go
@@ -627,15 +627,62 @@ usage: %s rib %s match <MATCH_EXPR> then <THEN_EXPR> -a %%s
return nil
}
+func showGlobalConfig(args []string) error {
+ g, err := client.GetGlobalConfig(context.Background(), &api.Arguments{})
+ if err != nil {
+ return err
+ }
+ fmt.Println("AS: ", g.As)
+ fmt.Println("Router-ID:", g.RouterId)
+ return nil
+}
+
+func modGlobalConfig(args []string) error {
+ if len(args) != 4 || args[0] != "as" || args[2] != "router-id" {
+ return fmt.Errorf("usage: gobgp global as <asn> router-id <route-id>")
+ }
+ asn, err := strconv.Atoi(args[1])
+ if err != nil {
+ return err
+ }
+ id := net.ParseIP(args[3])
+ if id.To4() == nil {
+ return fmt.Errorf("invalid router-id format")
+ }
+ _, err = client.ModGlobalConfig(context.Background(), &api.ModGlobalConfigArguments{
+ Operation: api.Operation_ADD,
+ Global: &api.Global{
+ As: uint32(asn),
+ RouterId: args[3],
+ },
+ })
+ return err
+}
+
func NewGlobalCmd() *cobra.Command {
globalCmd := &cobra.Command{
Use: CMD_GLOBAL,
+ Run: func(cmd *cobra.Command, args []string) {
+ var err error
+ if len(args) != 0 {
+ err = modGlobalConfig(args)
+ } else {
+ err = showGlobalConfig(args)
+ }
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ },
}
ribCmd := &cobra.Command{
Use: CMD_RIB,
Run: func(cmd *cobra.Command, args []string) {
- showGlobalRib(args)
+ if err := showGlobalRib(args); err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
},
}
diff --git a/gobgpd/main.go b/gobgpd/main.go
index 4f44e328..6024b102 100644
--- a/gobgpd/main.go
+++ b/gobgpd/main.go
@@ -148,14 +148,12 @@ func main() {
log.Info("gobgpd started")
- if opts.ConfigFile == "" {
- opts.ConfigFile = "gobgpd.conf"
- }
-
configCh := make(chan config.BgpConfigSet)
reloadCh := make(chan bool)
- go config.ReadConfigfileServe(opts.ConfigFile, configCh, reloadCh)
- reloadCh <- true
+ if opts.ConfigFile != "" {
+ go config.ReadConfigfileServe(opts.ConfigFile, configCh, reloadCh)
+ reloadCh <- true
+ }
bgpServer := server.NewBgpServer(bgp.BGP_PORT)
go bgpServer.Serve()
diff --git a/server/grpc_server.go b/server/grpc_server.go
index 348d11c7..c475f232 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -28,6 +28,8 @@ import (
const (
_ = iota
+ REQ_GLOBAL_CONFIG
+ REQ_MOD_GLOBAL_CONFIG
REQ_NEIGHBOR
REQ_NEIGHBORS
REQ_ADJ_RIB_IN
@@ -385,6 +387,18 @@ func (s *Server) ModPolicyAssignment(ctx context.Context, arg *api.ModPolicyAssi
return s.mod(REQ_MOD_POLICY_ASSIGNMENT, arg)
}
+func (s *Server) GetGlobalConfig(ctx context.Context, arg *api.Arguments) (*api.Global, error) {
+ d, err := s.get(REQ_GLOBAL_CONFIG, arg)
+ if err != nil {
+ return nil, err
+ }
+ return d.(*api.Global), nil
+}
+
+func (s *Server) ModGlobalConfig(ctx context.Context, arg *api.ModGlobalConfigArguments) (*api.Error, error) {
+ return s.mod(REQ_MOD_GLOBAL_CONFIG, arg)
+}
+
type GrpcRequest struct {
RequestType int
Name string
diff --git a/server/server.go b/server/server.go
index 49b584ca..67499076 100644
--- a/server/server.go
+++ b/server/server.go
@@ -18,6 +18,7 @@ package server
import (
"bytes"
"fmt"
+ "github.com/BurntSushi/toml"
log "github.com/Sirupsen/logrus"
"github.com/armon/go-radix"
api "github.com/osrg/gobgp/api"
@@ -142,8 +143,19 @@ func listenAndAccept(proto string, port int, ch chan *net.TCPConn) (*net.TCPList
}
func (server *BgpServer) Serve() {
- g := <-server.globalTypeCh
- server.bgpConfig.Global = g
+ var g config.Global
+ for {
+ select {
+ case grpcReq := <-server.GrpcReqCh:
+ server.handleGrpc(grpcReq)
+ case g = <-server.globalTypeCh:
+ server.bgpConfig.Global = g
+ server.globalTypeCh = nil
+ }
+ if server.globalTypeCh == nil {
+ break
+ }
+ }
server.roaClient, _ = newROAClient(g.GlobalConfig.As, config.RpkiServers{})
@@ -830,7 +842,9 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *fsmMsg, incoming chan *
}
func (server *BgpServer) SetGlobalType(g config.Global) {
- server.globalTypeCh <- g
+ if server.globalTypeCh != nil {
+ server.globalTypeCh <- g
+ }
}
func (server *BgpServer) SetRpkiConfig(c config.RpkiServers) {
@@ -1254,6 +1268,33 @@ END:
return msgs
}
+func (server *BgpServer) handleModGlobalConfig(grpcReq *GrpcRequest) error {
+ arg := grpcReq.Data.(*api.ModGlobalConfigArguments)
+ if arg.Operation != api.Operation_ADD {
+ return fmt.Errorf("invalid operation %s", arg.Operation)
+ }
+ if server.globalTypeCh == nil {
+ return fmt.Errorf("gobgp is already started")
+ }
+ g := arg.Global
+ c := config.Bgp{
+ Global: config.Global{
+ GlobalConfig: config.GlobalConfig{
+ As: g.As,
+ RouterId: net.ParseIP(g.RouterId),
+ },
+ },
+ }
+ err := config.SetDefaultConfigValues(toml.MetaData{}, &c)
+ if err != nil {
+ return err
+ }
+ go func() {
+ server.globalTypeCh <- c.Global
+ }()
+ return nil
+}
+
func sendMultipleResponses(grpcReq *GrpcRequest, results []*GrpcResponse) {
defer close(grpcReq.ResponseCh)
for _, r := range results {
@@ -1307,7 +1348,30 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
return results
}
+ if server.globalTypeCh != nil && grpcReq.RequestType != REQ_MOD_GLOBAL_CONFIG {
+ grpcReq.ResponseCh <- &GrpcResponse{
+ ResponseErr: fmt.Errorf("bgpd main loop is not started yet"),
+ }
+ close(grpcReq.ResponseCh)
+ return nil
+ }
+
switch grpcReq.RequestType {
+ case REQ_GLOBAL_CONFIG:
+ result := &GrpcResponse{
+ Data: &api.Global{
+ As: server.bgpConfig.Global.GlobalConfig.As,
+ RouterId: server.bgpConfig.Global.GlobalConfig.RouterId.String(),
+ },
+ }
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ case REQ_MOD_GLOBAL_CONFIG:
+ err := server.handleModGlobalConfig(grpcReq)
+ grpcReq.ResponseCh <- &GrpcResponse{
+ ResponseErr: err,
+ }
+ close(grpcReq.ResponseCh)
case REQ_GLOBAL_RIB:
var results []*GrpcResponse
if t, ok := server.globalRib.Tables[grpcReq.RouteFamily]; ok {