diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/gobgp/cmd/bmp.go | 20 | ||||
-rw-r--r-- | cmd/gobgp/cmd/common.go | 83 | ||||
-rw-r--r-- | cmd/gobgp/cmd/global.go | 63 | ||||
-rw-r--r-- | cmd/gobgp/cmd/monitor.go | 35 | ||||
-rw-r--r-- | cmd/gobgp/cmd/mrt.go | 11 | ||||
-rw-r--r-- | cmd/gobgp/cmd/neighbor.go | 422 | ||||
-rw-r--r-- | cmd/gobgp/cmd/policy.go | 118 | ||||
-rw-r--r-- | cmd/gobgp/cmd/root.go | 16 | ||||
-rw-r--r-- | cmd/gobgp/cmd/rpki.go | 98 | ||||
-rw-r--r-- | cmd/gobgp/cmd/rpki_test.go | 6 | ||||
-rw-r--r-- | cmd/gobgp/cmd/vrf.go | 45 | ||||
-rw-r--r-- | cmd/gobgpd/main.go | 27 |
12 files changed, 572 insertions, 372 deletions
diff --git a/cmd/gobgp/cmd/bmp.go b/cmd/gobgp/cmd/bmp.go index 6de8eac4..c176d770 100644 --- a/cmd/gobgp/cmd/bmp.go +++ b/cmd/gobgp/cmd/bmp.go @@ -20,7 +20,7 @@ import ( "net" "strconv" - "github.com/osrg/gobgp/internal/pkg/config" + api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/pkg/packet/bmp" "github.com/spf13/cobra" ) @@ -49,29 +49,28 @@ func modBmpServer(cmdType string, args []string) error { var err error switch cmdType { case CMD_ADD: - policyType := config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY + policyType := api.AddBmpRequest_PRE if len(args) > 1 { switch args[1] { - case "pre": case "post": - policyType = config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY + policyType = api.AddBmpRequest_POST case "both": - policyType = config.BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH + policyType = api.AddBmpRequest_BOTH case "local-rib": - policyType = config.BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB + policyType = api.AddBmpRequest_LOCAL case "all": - policyType = config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL + policyType = api.AddBmpRequest_ALL default: return fmt.Errorf("invalid bmp policy type. valid type is {pre|post|both|local-rib|all}") } } - err = client.AddBMP(&config.BmpServerConfig{ + _, err = client.AddBmp(ctx, &api.AddBmpRequest{ Address: address, Port: port, - RouteMonitoringPolicy: policyType, + Type: policyType, }) case CMD_DEL: - err = client.DeleteBMP(&config.BmpServerConfig{ + _, err = client.DeleteBmp(ctx, &api.DeleteBmpRequest{ Address: address, Port: port, }) @@ -80,7 +79,6 @@ func modBmpServer(cmdType string, args []string) error { } func NewBmpCmd() *cobra.Command { - bmpCmd := &cobra.Command{ Use: CMD_BMP, } diff --git a/cmd/gobgp/cmd/common.go b/cmd/gobgp/cmd/common.go index fbd75767..a1104836 100644 --- a/cmd/gobgp/cmd/common.go +++ b/cmd/gobgp/cmd/common.go @@ -17,21 +17,18 @@ package cmd import ( "bytes" + "context" "encoding/json" "fmt" "net" "os" - "sort" "strconv" - "strings" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials" api "github.com/osrg/gobgp/api" - cli "github.com/osrg/gobgp/internal/pkg/client" - "github.com/osrg/gobgp/internal/pkg/config" "github.com/osrg/gobgp/pkg/packet/bgp" ) @@ -183,63 +180,8 @@ func extractReserved(args []string, keys map[string]int) (map[string][]string, e return m, nil } -type neighbors []*config.Neighbor - -func (n neighbors) Len() int { - return len(n) -} - -func (n neighbors) Swap(i, j int) { - n[i], n[j] = n[j], n[i] -} - -func (n neighbors) Less(i, j int) bool { - p1 := n[i].State.NeighborAddress - p2 := n[j].State.NeighborAddress - p1Isv4 := !strings.Contains(p1, ":") - p2Isv4 := !strings.Contains(p2, ":") - if p1Isv4 != p2Isv4 { - return p1Isv4 - } - addrlen := 128 - if p1Isv4 { - addrlen = 32 - } - strings := sort.StringSlice{cidr2prefix(fmt.Sprintf("%s/%d", p1, addrlen)), - cidr2prefix(fmt.Sprintf("%s/%d", p2, addrlen))} - return strings.Less(0, 1) -} - -type capabilities []bgp.ParameterCapabilityInterface - -func (c capabilities) Len() int { - return len(c) -} - -func (c capabilities) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -func (c capabilities) Less(i, j int) bool { - return c[i].Code() < c[j].Code() -} - -type vrfs []*api.Vrf - -func (v vrfs) Len() int { - return len(v) -} - -func (v vrfs) Swap(i, j int) { - v[i], v[j] = v[j], v[i] -} - -func (v vrfs) Less(i, j int) bool { - return v[i].Name < v[j].Name -} - -func newClient() *cli.Client { - var grpcOpts []grpc.DialOption +func newClient(ctx context.Context) (api.GobgpApiClient, error) { + grpcOpts := []grpc.DialOption{grpc.WithTimeout(time.Second), grpc.WithBlock()} if globalOpts.TLS { var creds credentials.TransportCredentials if globalOpts.CaFile == "" { @@ -251,18 +193,21 @@ func newClient() *cli.Client { exitWithError(err) } } - grpcOpts = []grpc.DialOption{ - grpc.WithTimeout(time.Second), - grpc.WithBlock(), - grpc.WithTransportCredentials(creds), - } + grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(creds)) + } else { + grpcOpts = append(grpcOpts, grpc.WithInsecure()) } + target := net.JoinHostPort(globalOpts.Host, strconv.Itoa(globalOpts.Port)) - client, err := cli.New(target, grpcOpts...) + if target == "" { + target = ":50051" + } + + conn, err := grpc.DialContext(ctx, target, grpcOpts...) if err != nil { - exitWithError(fmt.Errorf("failed to connect to %s over gRPC: %s", target, err)) + return nil, err } - return client + return api.NewGobgpApiClient(conn), nil } func addr2AddressFamily(a net.IP) bgp.RouteFamily { diff --git a/cmd/gobgp/cmd/global.go b/cmd/gobgp/cmd/global.go index b71deba9..92f5dfc0 100644 --- a/cmd/gobgp/cmd/global.go +++ b/cmd/gobgp/cmd/global.go @@ -29,7 +29,6 @@ import ( api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/internal/pkg/apiutil" - "github.com/osrg/gobgp/internal/pkg/config" "github.com/osrg/gobgp/internal/pkg/table" "github.com/osrg/gobgp/pkg/packet/bgp" @@ -1447,38 +1446,44 @@ usage: %s rib %s key <KEY> [value <VALUE>]`, return err } + r := api.Resource_GLOBAL + if resource == CMD_VRF { + r = api.Resource_VRF + } + if modtype == CMD_ADD { - if resource == CMD_VRF { - _, err = client.AddVRFPath(name, []*api.Path{path}) - } else { - _, err = client.AddPath([]*api.Path{path}) - } + _, err = client.AddPath(ctx, &api.AddPathRequest{ + Resource: r, + VrfId: name, + Path: path, + }) } else { - if resource == CMD_VRF { - err = client.DeleteVRFPath(name, []*api.Path{path}) - } else { - err = client.DeletePath([]*api.Path{path}) - } + _, err = client.DeletePath(ctx, &api.DeletePathRequest{ + Resource: r, + VrfId: name, + Path: path, + }) } return err } func showGlobalConfig() error { - g, err := client.GetServer() + r, err := client.GetBgp(ctx, &api.GetBgpRequest{}) if err != nil { return err } if globalOpts.Json { - j, _ := json.Marshal(g) + j, _ := json.Marshal(r.Global) fmt.Println(string(j)) return nil } - fmt.Println("AS: ", g.Config.As) - fmt.Println("Router-ID:", g.Config.RouterId) - if len(g.Config.LocalAddressList) > 0 { - fmt.Printf("Listening Port: %d, Addresses: %s\n", g.Config.Port, strings.Join(g.Config.LocalAddressList, ", ")) + g := r.Global + fmt.Println("AS: ", g.As) + fmt.Println("Router-ID:", g.RouterId) + if len(g.ListenAddresses) > 0 { + fmt.Printf("Listening Port: %d, Addresses: %s\n", g.ListenPort, strings.Join(g.ListenAddresses, ", ")) } - if g.UseMultiplePaths.Config.Enabled { + if g.UseMultiplePaths { fmt.Printf("Multipath: enabled") } return nil @@ -1515,19 +1520,16 @@ func modGlobalConfig(args []string) error { if _, ok := m["use-multipath"]; ok { useMultipath = true } - return client.StartServer(&config.Global{ - Config: config.GlobalConfig{ + _, err = client.StartBgp(ctx, &api.StartBgpRequest{ + Global: &api.Global{ As: uint32(asn), RouterId: id.String(), - Port: int32(port), - LocalAddressList: m["listen-addresses"], - }, - UseMultiplePaths: config.UseMultiplePaths{ - Config: config.UseMultiplePathsConfig{ - Enabled: useMultipath, - }, + ListenPort: int32(port), + ListenAddresses: m["listen-addresses"], + UseMultiplePaths: useMultipath, }, }) + return err } func NewGlobalCmd() *cobra.Command { @@ -1577,7 +1579,10 @@ func NewGlobalCmd() *cobra.Command { if err != nil { exitWithError(err) } - if err = client.DeletePathByFamily(family); err != nil { + if _, err = client.DeletePath(ctx, &api.DeletePathRequest{ + Resource: api.Resource_GLOBAL, + Family: uint32(family), + }); err != nil { exitWithError(err) } }, @@ -1643,7 +1648,7 @@ func NewGlobalCmd() *cobra.Command { allCmd := &cobra.Command{ Use: CMD_ALL, Run: func(cmd *cobra.Command, args []string) { - if err := client.StopServer(); err != nil { + if _, err := client.StopBgp(ctx, &api.StopBgpRequest{}); err != nil { exitWithError(err) } }, diff --git a/cmd/gobgp/cmd/monitor.go b/cmd/gobgp/cmd/monitor.go index 9055ecf5..e1c18e9b 100644 --- a/cmd/gobgp/cmd/monitor.go +++ b/cmd/gobgp/cmd/monitor.go @@ -93,20 +93,20 @@ func NewMonitorCmd() *cobra.Command { var current bool monitor := func(recver interface { - Recv() (*api.Destination, error) + Recv() (*api.MonitorTableResponse, error) }, showIdentifier bgp.BGPAddPathMode) { for { - dst, err := recver.Recv() + r, err := recver.Recv() if err == io.EOF { break } else if err != nil { exitWithError(err) } if globalOpts.Json { - j, _ := json.Marshal(apiutil.NewDestination(dst)) + j, _ := json.Marshal(apiutil.NewDestination(&api.Destination{Paths: []*api.Path{r.Path}})) fmt.Println(string(j)) } else { - monitorRoute(dst.Paths, showIdentifier) + monitorRoute([]*api.Path{r.Path}, bgp.BGP_ADD_PATH_NONE) } } } @@ -118,7 +118,11 @@ func NewMonitorCmd() *cobra.Command { if err != nil { exitWithError(err) } - recver, err := client.MonitorRIB(family, current) + recver, err := client.MonitorTable(ctx, &api.MonitorTableRequest{ + Type: api.Resource_GLOBAL, + Family: uint32(family), + Current: current, + }) if err != nil { exitWithError(err) } @@ -140,24 +144,28 @@ func NewMonitorCmd() *cobra.Command { if len(args) > 0 { name = args[0] } - stream, err := client.MonitorNeighborState(name, current) + stream, err := client.MonitorPeer(ctx, &api.MonitorPeerRequest{ + Address: name, + Current: current, + }) if err != nil { exitWithError(err) } for { - s, err := stream.Recv() + r, err := stream.Recv() if err == io.EOF { break } else if err != nil { exitWithError(err) } + s := r.Peer if globalOpts.Json { j, _ := json.Marshal(s) fmt.Println(string(j)) } else { - addr := s.State.NeighborAddress - if s.Config.NeighborInterface != "" { - addr = fmt.Sprintf("%s(%s)", addr, s.Config.NeighborInterface) + addr := s.Conf.NeighborAddress + if s.Conf.NeighborInterface != "" { + addr = fmt.Sprintf("%s(%s)", addr, s.Conf.NeighborInterface) } fmt.Printf("[NEIGH] %s fsm: %s admin: %s\n", addr, s.State.SessionState, s.State.AdminState) } @@ -180,7 +188,12 @@ func NewMonitorCmd() *cobra.Command { if err != nil { exitWithError(err) } - recver, err := client.MonitorAdjRIBIn(name, family, current) + recver, err := client.MonitorTable(ctx, &api.MonitorTableRequest{ + Type: api.Resource_ADJ_IN, + Name: name, + Family: uint32(family), + Current: current, + }) if err != nil { exitWithError(err) } diff --git a/cmd/gobgp/cmd/mrt.go b/cmd/gobgp/cmd/mrt.go index 58b4381d..8fd40791 100644 --- a/cmd/gobgp/cmd/mrt.go +++ b/cmd/gobgp/cmd/mrt.go @@ -171,21 +171,20 @@ func injectMrt() error { close(ch) }() - stream, err := client.AddPathByStream() + stream, err := client.AddPathStream(ctx) if err != nil { return fmt.Errorf("failed to add path: %s", err) } for paths := range ch { - err = stream.Send(paths...) + err = stream.Send(&api.AddPathStreamRequest{ + Resource: api.Resource_GLOBAL, + Paths: paths, + }) if err != nil { return fmt.Errorf("failed to send: %s", err) } } - - if err := stream.Close(); err != nil { - return fmt.Errorf("failed to send: %s", err) - } return nil } diff --git a/cmd/gobgp/cmd/neighbor.go b/cmd/gobgp/cmd/neighbor.go index 9b1e96ee..73670196 100644 --- a/cmd/gobgp/cmd/neighbor.go +++ b/cmd/gobgp/cmd/neighbor.go @@ -19,6 +19,7 @@ import ( "bytes" "encoding/json" "fmt" + "io" "net" "sort" "strconv" @@ -56,27 +57,36 @@ func updateColumnWidth(nlri, nexthop, aspath, label string) { } } -func getNeighbors(vrf string) (neighbors, error) { +func getNeighbors(vrf string) ([]*api.Peer, error) { + adv := true if vrf != "" { - n, err := client.ListNeighborByVRF(vrf) - return neighbors(n), err + adv = false } else if t := neighborsOpts.Transport; t != "" { switch t { - case "ipv4": - n, err := client.ListNeighborByTransport(bgp.AFI_IP) - return neighbors(n), err - case "ipv6": - n, err := client.ListNeighborByTransport(bgp.AFI_IP6) - return neighbors(n), err + case "ipv4", "ipv6": + adv = false default: return nil, fmt.Errorf("invalid transport: %s", t) } } - n, err := client.ListNeighbor() - return neighbors(n), err + stream, err := client.ListPeer(ctx, &api.ListPeerRequest{ + EnableAdvertised: adv, + }) + + l := make([]*api.Peer, 0, 1024) + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + l = append(l, r.Peer) + } + return l, err } -func getASN(p *config.Neighbor) string { +func getASN(p *api.Peer) string { asn := "*" if p.State.PeerAs > 0 { asn = fmt.Sprint(p.State.PeerAs) @@ -106,11 +116,26 @@ func showNeighbors(vrf string) error { maxtimelen := len("Up/Down") timedelta := []string{} - sort.Sort(m) + sort.Slice(m, func(i, j int) bool { + p1 := m[i].Conf.NeighborAddress + p2 := m[j].Conf.NeighborAddress + p1Isv4 := !strings.Contains(p1, ":") + p2Isv4 := !strings.Contains(p2, ":") + if p1Isv4 != p2Isv4 { + return p1Isv4 + } + addrlen := 128 + if p1Isv4 { + addrlen = 32 + } + strings := sort.StringSlice{cidr2prefix(fmt.Sprintf("%s/%d", p1, addrlen)), + cidr2prefix(fmt.Sprintf("%s/%d", p2, addrlen))} + return strings.Less(0, 1) + }) now := time.Now() for _, n := range m { - if i := len(n.Config.NeighborInterface); i > maxaddrlen { + if i := len(n.Conf.NeighborInterface); i > maxaddrlen { maxaddrlen = i } else if j := len(n.State.NeighborAddress); j > maxaddrlen { maxaddrlen = j @@ -121,7 +146,7 @@ func showNeighbors(vrf string) error { timeStr := "never" if n.Timers.State.Uptime != 0 { t := int64(n.Timers.State.Downtime) - if n.State.SessionState == config.SESSION_STATE_ESTABLISHED { + if n.State.SessionState == api.PeerState_ESTABLISHED { t = int64(n.Timers.State.Uptime) } timeStr = formatTimedelta(int64(now.Sub(time.Unix(int64(t), 0)).Seconds())) @@ -135,26 +160,26 @@ func showNeighbors(vrf string) error { format := "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s" format += " %-11s |%9s %9s\n" fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Received", "Accepted") - formatFsm := func(admin config.AdminState, fsm config.SessionState) string { + formatFsm := func(admin api.PeerState_AdminState, fsm api.PeerState_SessionState) string { switch admin { - case config.ADMIN_STATE_DOWN: + case api.PeerState_UP: return "Idle(Admin)" - case config.ADMIN_STATE_PFX_CT: + case api.PeerState_PFX_CT: return "Idle(PfxCt)" } switch fsm { - case config.SESSION_STATE_IDLE: + case api.PeerState_UNKNOWN: return "Idle" - case config.SESSION_STATE_CONNECT: + case api.PeerState_IDLE: return "Connect" - case config.SESSION_STATE_ACTIVE: + case api.PeerState_ACTIVE: return "Active" - case config.SESSION_STATE_OPENSENT: + case api.PeerState_OPENSENT: return "Sent" - case config.SESSION_STATE_OPENCONFIRM: + case api.PeerState_OPENCONFIRM: return "Confirm" - case config.SESSION_STATE_ESTABLISHED: + case api.PeerState_ESTABLISHED: return "Establ" default: return string(fsm) @@ -163,20 +188,29 @@ func showNeighbors(vrf string) error { for i, n := range m { neigh := n.State.NeighborAddress - if n.Config.NeighborInterface != "" { - neigh = n.Config.NeighborInterface + if n.Conf.NeighborInterface != "" { + neigh = n.Conf.NeighborInterface } - fmt.Printf(format, neigh, getASN(n), timedelta[i], formatFsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.AdjTable.Received), fmt.Sprint(n.State.AdjTable.Accepted)) + fmt.Printf(format, neigh, getASN(n), timedelta[i], formatFsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.Received), fmt.Sprint(n.State.Accepted)) } return nil } func showNeighbor(args []string) error { - p, e := client.GetNeighbor(args[0], true) - if e != nil { - return e + stream, err := client.ListPeer(ctx, &api.ListPeerRequest{ + Address: args[0], + EnableAdvertised: true, + }) + if err != nil { + return err + } + r, err := stream.Recv() + if err != nil && err != io.EOF { + return err } + p := r.Peer + if globalOpts.Json { j, _ := json.Marshal(p) fmt.Println(string(j)) @@ -185,17 +219,17 @@ func showNeighbor(args []string) error { fmt.Printf("BGP neighbor is %s, remote AS %s", p.State.NeighborAddress, getASN(p)) - if p.RouteReflector.Config.RouteReflectorClient { + if p.RouteReflector.RouteReflectorClient { fmt.Printf(", route-reflector-client\n") - } else if p.RouteServer.Config.RouteServerClient { + } else if p.RouteServer.RouteServerClient { fmt.Printf(", route-server-client\n") } else { fmt.Printf("\n") } id := "unknown" - if p.State.RemoteRouterId != "" { - id = p.State.RemoteRouterId + if p.Conf.Id != "" { + id = p.Conf.Id } fmt.Printf(" BGP version 4, remote router ID %s\n", id) fmt.Printf(" BGP state = %s", p.State.SessionState) @@ -209,24 +243,24 @@ func showNeighbor(args []string) error { fmt.Printf(" Configured hold time is %d, keepalive interval is %d seconds\n", int(p.Timers.Config.HoldTime), int(p.Timers.Config.KeepaliveInterval)) elems := make([]string, 0, 3) - if as := p.AsPathOptions.Config.AllowOwnAs; as > 0 { + if as := p.Conf.AllowOwnAs; as > 0 { elems = append(elems, fmt.Sprintf("Allow Own AS: %d", as)) } - switch p.Config.RemovePrivateAs { - case config.REMOVE_PRIVATE_AS_OPTION_ALL: + switch p.Conf.RemovePrivateAs { + case api.PeerConf_ALL: elems = append(elems, "Remove private AS: all") - case config.REMOVE_PRIVATE_AS_OPTION_REPLACE: + case api.PeerConf_REPLACE: elems = append(elems, "Remove private AS: replace") } - if p.AsPathOptions.Config.ReplacePeerAs { + if p.Conf.ReplacePeerAs { elems = append(elems, "Replace peer AS: enabled") } fmt.Printf(" %s\n", strings.Join(elems, ", ")) fmt.Printf(" Neighbor capabilities:\n") - caps := capabilities{} - lookup := func(val bgp.ParameterCapabilityInterface, l capabilities) bgp.ParameterCapabilityInterface { + caps := []bgp.ParameterCapabilityInterface{} + lookup := func(val bgp.ParameterCapabilityInterface, l []bgp.ParameterCapabilityInterface) bgp.ParameterCapabilityInterface { for _, v := range l { if v.Code() == val.Code() { if v.Code() == bgp.BGP_CAP_MULTIPROTOCOL { @@ -242,25 +276,28 @@ func showNeighbor(args []string) error { } return nil } - for _, c := range p.State.LocalCapabilityList { - caps = append(caps, c) - } - for _, c := range p.State.RemoteCapabilityList { + lcaps, _ := apiutil.UnmarshalCapabilities(p.Conf.LocalCap) + caps = append(caps, lcaps...) + + rcaps, _ := apiutil.UnmarshalCapabilities(p.Conf.RemoteCap) + for _, c := range rcaps { if lookup(c, caps) == nil { caps = append(caps, c) } } - sort.Sort(caps) + sort.Slice(caps, func(i, j int) bool { + return caps[i].Code() < caps[j].Code() + }) firstMp := true for _, c := range caps { support := "" - if m := lookup(c, p.State.LocalCapabilityList); m != nil { + if m := lookup(c, lcaps); m != nil { support += "advertised" } - if lookup(c, p.State.RemoteCapabilityList) != nil { + if lookup(c, rcaps) != nil { if len(support) != 0 { support += " and " } @@ -307,13 +344,13 @@ func showNeighbor(args []string) error { } return str } - if m := lookup(c, p.State.LocalCapabilityList); m != nil { + if m := lookup(c, lcaps); m != nil { g := m.(*bgp.CapGracefulRestart) if s := grStr(g); len(s) > 0 { fmt.Printf(" Local: %s", s) } } - if m := lookup(c, p.State.RemoteCapabilityList); m != nil { + if m := lookup(c, rcaps); m != nil { g := m.(*bgp.CapGracefulRestart) if s := grStr(g); len(s) > 0 { fmt.Printf(" Remote: %s", s) @@ -332,13 +369,13 @@ func showNeighbor(args []string) error { } return str } - if m := lookup(c, p.State.LocalCapabilityList); m != nil { + if m := lookup(c, lcaps); m != nil { g := m.(*bgp.CapLongLivedGracefulRestart) if s := grStr(g); len(s) > 0 { fmt.Printf(" Local:\n%s", s) } } - if m := lookup(c, p.State.RemoteCapabilityList); m != nil { + if m := lookup(c, rcaps); m != nil { g := m.(*bgp.CapLongLivedGracefulRestart) if s := grStr(g); len(s) > 0 { fmt.Printf(" Remote:\n%s", s) @@ -363,13 +400,13 @@ func showNeighbor(args []string) error { } return strings.Join(lines, "\n") } - if m := lookup(c, p.State.LocalCapabilityList); m != nil { + if m := lookup(c, lcaps); m != nil { e := m.(*bgp.CapExtendedNexthop) if s := exnhStr(e); len(s) > 0 { fmt.Printf(" Local: %s\n", s) } } - if m := lookup(c, p.State.RemoteCapabilityList); m != nil { + if m := lookup(c, rcaps); m != nil { e := m.(*bgp.CapExtendedNexthop) if s := exnhStr(e); len(s) > 0 { fmt.Printf(" Remote: %s\n", s) @@ -377,13 +414,13 @@ func showNeighbor(args []string) error { } case bgp.BGP_CAP_ADD_PATH: fmt.Printf(" %s:\t%s\n", c.Code(), support) - if m := lookup(c, p.State.LocalCapabilityList); m != nil { + if m := lookup(c, lcaps); m != nil { fmt.Println(" Local:") for _, item := range m.(*bgp.CapAddPath).Tuples { fmt.Printf(" %s:\t%s\n", item.RouteFamily, item.Mode) } } - if m := lookup(c, p.State.RemoteCapabilityList); m != nil { + if m := lookup(c, rcaps); m != nil { fmt.Println(" Remote:") for _, item := range m.(*bgp.CapAddPath).Tuples { fmt.Printf(" %s:\t%s\n", item.RouteFamily, item.Mode) @@ -403,19 +440,19 @@ func showNeighbor(args []string) error { fmt.Printf(" Discarded: %10d %10d\n", p.State.Messages.Sent.Discarded, p.State.Messages.Received.Discarded) fmt.Printf(" Total: %10d %10d\n", p.State.Messages.Sent.Total, p.State.Messages.Received.Total) fmt.Print(" Route statistics:\n") - fmt.Printf(" Advertised: %10d\n", p.State.AdjTable.Advertised) - fmt.Printf(" Received: %10d\n", p.State.AdjTable.Received) - fmt.Printf(" Accepted: %10d\n", p.State.AdjTable.Accepted) + fmt.Printf(" Advertised: %10d\n", p.State.Advertised) + fmt.Printf(" Received: %10d\n", p.State.Received) + fmt.Printf(" Accepted: %10d\n", p.State.Accepted) first := true - for _, afisafi := range p.AfiSafis { - if afisafi.PrefixLimit.Config.MaxPrefixes > 0 { + for _, limit := range p.Conf.PrefixLimits { + if limit.MaxPrefixes > 0 { if first { fmt.Println(" Prefix Limits:") first = false } - fmt.Printf(" %s:\tMaximum prefixes allowed %d", afisafi.Config.AfiSafiName, afisafi.PrefixLimit.Config.MaxPrefixes) - if afisafi.PrefixLimit.Config.ShutdownThresholdPct > 0 { - fmt.Printf(", Threshold for warning message %d%%\n", afisafi.PrefixLimit.Config.ShutdownThresholdPct) + fmt.Printf(" %s:\tMaximum prefixes allowed %d", bgp.AddressFamilyNameMap[bgp.RouteFamily(limit.Family)], limit.MaxPrefixes) + if limit.ShutdownThresholdPct > 0 { + fmt.Printf(", Threshold for warning message %d%%\n", limit.ShutdownThresholdPct) } else { fmt.Printf("\n") } @@ -665,31 +702,36 @@ func showRibInfo(r, name string) error { return err } - var info *api.TableInfo + var t api.Resource switch r { case CMD_GLOBAL: - info, err = client.GetRIBInfo(family) + t = api.Resource_GLOBAL case CMD_LOCAL: - info, err = client.GetLocalRIBInfo(name, family) + t = api.Resource_LOCAL case CMD_ADJ_IN: - info, err = client.GetAdjRIBInInfo(name, family) + t = api.Resource_ADJ_IN case CMD_ADJ_OUT: - info, err = client.GetAdjRIBOutInfo(name, family) + t = api.Resource_ADJ_OUT default: return fmt.Errorf("invalid resource to show RIB info: %s", r) } + rsp, err := client.GetTable(ctx, &api.GetTableRequest{ + Type: t, + Family: uint32(family), + Name: name, + }) if err != nil { return err } if globalOpts.Json { - j, _ := json.Marshal(info) + j, _ := json.Marshal(rsp) fmt.Println(string(j)) return nil } fmt.Printf("Table %s\n", family) - fmt.Printf("Destination: %d, Path: %d\n", info.NumDestination, info.NumPath) + fmt.Printf("Destination: %d, Path: %d\n", rsp.NumDestination, rsp.NumPath) return nil } @@ -769,34 +811,60 @@ func showNeighborRib(r string, name string, args []string) error { } } - var rib *api.Table + var t api.Resource switch r { case CMD_GLOBAL: - rib, err = client.GetRIB(family, filter) + t = api.Resource_GLOBAL case CMD_LOCAL: - rib, err = client.GetLocalRIB(name, family, filter) + t = api.Resource_LOCAL case CMD_ADJ_IN, CMD_ACCEPTED, CMD_REJECTED: + t = api.Resource_ADJ_IN showIdentifier = bgp.BGP_ADD_PATH_RECEIVE - rib, err = client.GetAdjRIBIn(name, family, filter) case CMD_ADJ_OUT: + t = api.Resource_ADJ_OUT showIdentifier = bgp.BGP_ADD_PATH_SEND - rib, err = client.GetAdjRIBOut(name, family, filter) case CMD_VRF: - rib, err = client.GetVRFRIB(name, family, filter) + t = api.Resource_VRF } + stream, err := client.ListPath(ctx, &api.ListPathRequest{ + Type: t, + Family: uint32(family), + Name: name, + Prefixes: filter, + }) if err != nil { return err } + rib := make([]*api.Destination, 0) + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { + return err + } + rib = append(rib, r.Destination) + } + switch r { case CMD_LOCAL, CMD_ADJ_IN, CMD_ACCEPTED, CMD_REJECTED, CMD_ADJ_OUT: - if len(rib.Destinations) == 0 { - peer, err := client.GetNeighbor(name, false) + if len(rib) == 0 { + stream, err := client.ListPeer(ctx, &api.ListPeerRequest{ + Address: name, + }) if err != nil { return err } - if peer.State.SessionState != config.SESSION_STATE_ESTABLISHED { + r, err := stream.Recv() + if err != nil && err != io.EOF { + return err + } + if r == nil { + return fmt.Errorf("Neighbor %v is not found", name) + } + if r.Peer.State.SessionState != api.PeerState_ESTABLISHED { return fmt.Errorf("Neighbor %v's BGP session is not established", name) } } @@ -804,7 +872,7 @@ func showNeighborRib(r string, name string, args []string) error { if globalOpts.Json { d := make(map[string]*apiutil.Destination) - for _, dst := range rib.GetDestinations() { + for _, dst := range rib { d[dst.Prefix] = apiutil.NewDestination(dst) } j, _ := json.Marshal(d) @@ -815,7 +883,7 @@ func showNeighborRib(r string, name string, args []string) error { if validationTarget != "" { // show RPKI validation info d := func() *api.Destination { - for _, dst := range rib.GetDestinations() { + for _, dst := range rib { if dst.Prefix == validationTarget { return dst } @@ -834,15 +902,15 @@ func showNeighborRib(r string, name string, args []string) error { } } else { // show RIB - dsts := rib.GetDestinations() + var dsts []*api.Destination switch family { case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: type d struct { prefix net.IP dst *api.Destination } - l := make([]*d, 0, len(dsts)) - for _, dst := range dsts { + l := make([]*d, 0, len(rib)) + for _, dst := range rib { _, p, _ := net.ParseCIDR(dst.Prefix) l = append(l, &d{prefix: p.IP, dst: dst}) } @@ -851,10 +919,12 @@ func showNeighborRib(r string, name string, args []string) error { return bytes.Compare(l[i].prefix, l[j].prefix) < 0 }) - dsts = make([]*api.Destination, 0, len(dsts)) + dsts = make([]*api.Destination, 0, len(rib)) for _, s := range l { dsts = append(dsts, s.dst) } + default: + dsts = append(dsts, rib...) } for _, d := range dsts { @@ -883,21 +953,29 @@ func showNeighborRib(r string, name string, args []string) error { } func resetNeighbor(cmd string, remoteIP string, args []string) error { - family := bgp.RouteFamily(0) if reasonLen := len(neighborsOpts.Reason); reasonLen > bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX { return fmt.Errorf("Too long reason for shutdown communication (max %d bytes)", bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX) } + var comm string + soft := true + dir := api.ResetPeerRequest_BOTH switch cmd { case CMD_RESET: - return client.ResetNeighbor(remoteIP, neighborsOpts.Reason) + soft = false + comm = neighborsOpts.Reason case CMD_SOFT_RESET: - return client.SoftReset(remoteIP, family) case CMD_SOFT_RESET_IN: - return client.SoftResetIn(remoteIP, family) + dir = api.ResetPeerRequest_IN case CMD_SOFT_RESET_OUT: - return client.SoftResetOut(remoteIP, family) - } - return nil + dir = api.ResetPeerRequest_OUT + } + _, err := client.ResetPeer(ctx, &api.ResetPeerRequest{ + Address: remoteIP, + Communication: comm, + Soft: soft, + Direction: dir, + }) + return err } func stateChangeNeighbor(cmd string, remoteIP string, args []string) error { @@ -907,11 +985,21 @@ func stateChangeNeighbor(cmd string, remoteIP string, args []string) error { switch cmd { case CMD_SHUTDOWN: fmt.Printf("WARNING: command `%s` is deprecated. use `%s` instead\n", CMD_SHUTDOWN, CMD_DISABLE) - return client.ShutdownNeighbor(remoteIP, neighborsOpts.Reason) + _, err := client.ShutdownPeer(ctx, &api.ShutdownPeerRequest{ + Address: remoteIP, + Communication: neighborsOpts.Reason, + }) + return err case CMD_ENABLE: - return client.EnableNeighbor(remoteIP) + _, err := client.EnablePeer(ctx, &api.EnablePeerRequest{ + Address: remoteIP, + }) + return err case CMD_DISABLE: - return client.DisableNeighbor(remoteIP, neighborsOpts.Reason) + _, err := client.DisablePeer(ctx, &api.DisablePeerRequest{ + Address: remoteIP, + }) + return err } return nil } @@ -919,19 +1007,28 @@ func stateChangeNeighbor(cmd string, remoteIP string, args []string) error { func showNeighborPolicy(remoteIP, policyType string, indent int) error { var assignment *api.PolicyAssignment var err error + var dir api.PolicyDirection switch strings.ToLower(policyType) { case "import": - assignment, err = client.GetRouteServerImportPolicy(remoteIP) + dir = api.PolicyDirection_IMPORT case "export": - assignment, err = client.GetRouteServerExportPolicy(remoteIP) + dir = api.PolicyDirection_EXPORT default: return fmt.Errorf("invalid policy type: choose from (in|import|export)") } - + stream, err := client.ListPolicyAssignment(ctx, &api.ListPolicyAssignmentRequest{ + Name: remoteIP, + Direction: dir, + }) + if err != nil { + return err + } + r, err := stream.Recv() if err != nil { return err } + assignment = r.Assignment if globalOpts.Json { j, _ := json.Marshal(assignment) @@ -981,9 +1078,9 @@ func modNeighborPolicy(remoteIP, policyType, cmdType string, args []string) erro switch strings.ToLower(policyType) { case "import": - assign.Type = api.PolicyType_IMPORT + assign.Type = api.PolicyDirection_IMPORT case "export": - assign.Type = api.PolicyType_EXPORT + assign.Type = api.PolicyDirection_EXPORT } usage := fmt.Sprintf("usage: gobgp neighbor %s policy %s %s", remoteIP, policyType, cmdType) @@ -1012,15 +1109,22 @@ func modNeighborPolicy(remoteIP, policyType, cmdType string, args []string) erro assign.Policies = ps switch cmdType { case CMD_ADD: - err = client.AddPolicyAssignment(assign) + _, err = client.AddPolicyAssignment(ctx, &api.AddPolicyAssignmentRequest{ + Assignment: assign, + }) case CMD_SET: - err = client.ReplacePolicyAssignment(assign) + _, err = client.ReplacePolicyAssignment(ctx, &api.ReplacePolicyAssignmentRequest{ + Assignment: assign, + }) case CMD_DEL: all := false if len(args) == 0 { all = true } - err = client.DeletePolicyAssignment(assign, all) + _, err = client.DeletePolicyAssignment(ctx, &api.DeletePolicyAssignmentRequest{ + Assignment: assign, + All: all, + }) } return err } @@ -1067,96 +1171,97 @@ func modNeighbor(cmdType string, args []string) error { return m[""][0], nil } - getNeighborConfig := func() (*config.Neighbor, error) { + getNeighborConfig := func() (*api.Peer, error) { addr, err := getNeighborAddress() if err != nil { return nil, err } - var peer *config.Neighbor + var peer *api.Peer switch cmdType { case CMD_ADD, CMD_DEL: - peer = &config.Neighbor{} + peer = &api.Peer{ + Conf: &api.PeerConf{}, + State: &api.PeerState{}, + } if unnumbered { - peer.Config.NeighborInterface = m["interface"][0] + peer.Conf.NeighborInterface = m["interface"][0] } else { - peer.Config.NeighborAddress = addr + peer.Conf.NeighborAddress = addr } peer.State.NeighborAddress = addr case CMD_UPDATE: - peer, err = client.GetNeighbor(addr) + stream, err := client.ListPeer(ctx, &api.ListPeerRequest{ + Address: addr, + }) + if err != nil { + return nil, err + } + r, err := stream.Recv() if err != nil { return nil, err } + peer = r.Peer default: return nil, fmt.Errorf("invalid command: %s", cmdType) } return peer, nil } - updateNeighborConfig := func(peer *config.Neighbor) error { + updateNeighborConfig := func(peer *api.Peer) error { if len(m["as"]) > 0 { as, err := strconv.ParseUint(m["as"][0], 10, 32) if err != nil { return err } - peer.Config.PeerAs = uint32(as) + peer.Conf.PeerAs = uint32(as) } if len(m["family"]) == 1 { - peer.AfiSafis = make([]config.AfiSafi, 0) // for the case of CMD_UPDATE - for _, family := range strings.Split(m["family"][0], ",") { - afiSafiName := config.AfiSafiType(family) - if afiSafiName.ToInt() == -1 { - return fmt.Errorf("invalid family value: %s", family) - } - peer.AfiSafis = append(peer.AfiSafis, config.AfiSafi{Config: config.AfiSafiConfig{AfiSafiName: afiSafiName}}) + peer.AfiSafis = make([]*api.AfiSafi, 0) // for the case of CMD_UPDATE + for _, f := range strings.Split(m["family"][0], ",") { + family := config.AfiSafiType(f).ToInt() + peer.AfiSafis = append(peer.AfiSafis, &api.AfiSafi{Config: &api.AfiSafiConfig{Family: uint32(family)}}) } } if len(m["vrf"]) == 1 { - peer.Config.Vrf = m["vrf"][0] + peer.Conf.Vrf = m["vrf"][0] } if option, ok := m["route-reflector-client"]; ok { - peer.RouteReflector.Config = config.RouteReflectorConfig{ - RouteReflectorClient: true, - } + peer.RouteReflector.RouteReflectorClient = true if len(option) == 1 { - peer.RouteReflector.Config.RouteReflectorClusterId = config.RrClusterIdType(option[0]) + peer.RouteReflector.RouteReflectorClusterId = option[0] } } if _, ok := m["route-server-client"]; ok { - peer.RouteServer.Config = config.RouteServerConfig{ - RouteServerClient: true, - } + peer.RouteServer.RouteServerClient = true } if option, ok := m["allow-own-as"]; ok { as, err := strconv.ParseUint(option[0], 10, 8) if err != nil { return err } - peer.AsPathOptions.Config.AllowOwnAs = uint8(as) + peer.Conf.AllowOwnAs = uint32(as) } if option, ok := m["remove-private-as"]; ok { switch option[0] { case "all": - peer.Config.RemovePrivateAs = config.REMOVE_PRIVATE_AS_OPTION_ALL + peer.Conf.RemovePrivateAs = api.PeerConf_ALL case "replace": - peer.Config.RemovePrivateAs = config.REMOVE_PRIVATE_AS_OPTION_REPLACE + peer.Conf.RemovePrivateAs = api.PeerConf_REPLACE default: return fmt.Errorf("invalid remove-private-as value: all or replace") } } if _, ok := m["replace-peer-as"]; ok { - peer.AsPathOptions.Config.ReplacePeerAs = true + peer.Conf.ReplacePeerAs = true } if len(m["ebgp-multihop-ttl"]) == 1 { ttl, err := strconv.ParseUint(m["ebgp-multihop-ttl"][0], 10, 32) if err != nil { return err } - peer.EbgpMultihop = config.EbgpMultihop{ - Config: config.EbgpMultihopConfig{ - Enabled: true, - MultihopTtl: uint8(ttl), - }, + peer.EbgpMultihop = &api.EbgpMultihop{ + Enabled: true, + MultihopTtl: uint32(ttl), } } return nil @@ -1169,20 +1274,27 @@ func modNeighbor(cmdType string, args []string) error { switch cmdType { case CMD_ADD: - if err := updateNeighborConfig(n); err != nil { + if err = updateNeighborConfig(n); err != nil { return err } - return client.AddNeighbor(n) + _, err = client.AddPeer(ctx, &api.AddPeerRequest{ + Peer: n, + }) case CMD_DEL: - return client.DeleteNeighbor(n) + _, err = client.DeletePeer(ctx, &api.DeletePeerRequest{ + Address: n.Conf.NeighborAddress, + Interface: n.Conf.NeighborInterface, + }) case CMD_UPDATE: - if err := updateNeighborConfig(n); err != nil { + if err = updateNeighborConfig(n); err != nil { return err } - _, err := client.UpdateNeighbor(n, true) - return err + _, err = client.UpdatePeer(ctx, &api.UpdatePeerRequest{ + Peer: n, + DoSoftResetIn: true, + }) } - return nil + return err } func NewNeighborCmd() *cobra.Command { @@ -1199,6 +1311,20 @@ func NewNeighborCmd() *cobra.Command { c = append(c, cmds{[]string{CMD_RESET, CMD_SOFT_RESET, CMD_SOFT_RESET_IN, CMD_SOFT_RESET_OUT}, resetNeighbor}) c = append(c, cmds{[]string{CMD_SHUTDOWN, CMD_ENABLE, CMD_DISABLE}, stateChangeNeighbor}) + getPeer := func(addr string) (*api.Peer, error) { + var r *api.ListPeerResponse + stream, err := client.ListPeer(ctx, &api.ListPeerRequest{ + Address: addr, + }) + if err == nil { + r, err = stream.Recv() + } + if err != nil && err != io.EOF { + return nil, err + } + return r.Peer, nil + } + for _, v := range c { f := v.f for _, name := range v.names { @@ -1213,11 +1339,11 @@ func NewNeighborCmd() *cobra.Command { } } if addr == "" { - peer, err := client.GetNeighbor(args[len(args)-1], false) + p, err := getPeer(args[len(args)-1]) if err != nil { exitWithError(err) } - addr = peer.State.NeighborAddress + addr = p.State.NeighborAddress } err := f(cmd.Use, addr, args[:len(args)-1]) if err != nil { @@ -1244,7 +1370,7 @@ func NewNeighborCmd() *cobra.Command { policyCmd := &cobra.Command{ Use: CMD_POLICY, Run: func(cmd *cobra.Command, args []string) { - peer, err := client.GetNeighbor(args[0], false) + peer, err := getPeer(args[0]) if err != nil { exitWithError(err) } @@ -1261,7 +1387,7 @@ func NewNeighborCmd() *cobra.Command { cmd := &cobra.Command{ Use: v, Run: func(cmd *cobra.Command, args []string) { - peer, err := client.GetNeighbor(args[0], false) + peer, err := getPeer(args[0]) if err != nil { exitWithError(err) } @@ -1277,7 +1403,7 @@ func NewNeighborCmd() *cobra.Command { subcmd := &cobra.Command{ Use: w, Run: func(subcmd *cobra.Command, args []string) { - peer, err := client.GetNeighbor(args[len(args)-1], false) + peer, err := getPeer(args[len(args)-1]) if err != nil { exitWithError(err) } diff --git a/cmd/gobgp/cmd/policy.go b/cmd/gobgp/cmd/policy.go index 6c50858f..df9c5c8f 100644 --- a/cmd/gobgp/cmd/policy.go +++ b/cmd/gobgp/cmd/policy.go @@ -19,6 +19,7 @@ import ( "bytes" "encoding/json" "fmt" + "io" "net" "regexp" "strconv" @@ -212,20 +213,28 @@ func showDefinedSet(v string, args []string) error { default: return fmt.Errorf("unknown defined type: %s", v) } - var m []*api.DefinedSet + m := make([]*api.DefinedSet, 0) + var name string if len(args) > 0 { - d, err := client.GetDefinedSetByName(typ, args[0]) - if err != nil { - return err - } - m = []*api.DefinedSet{d} - } else { - var err error - m, err = client.GetDefinedSet(typ) - if err != nil { + name = args[0] + } + stream, err := client.ListDefinedSet(ctx, &api.ListDefinedSetRequest{ + Type: typ, + Name: name, + }) + if err != nil { + return err + } + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { return err } + m = append(m, r.Set) } + if globalOpts.Json { j, _ := json.Marshal(m) fmt.Println(string(j)) @@ -433,15 +442,22 @@ func modDefinedSet(settype string, modtype string, args []string) error { } switch modtype { case CMD_ADD: - err = client.AddDefinedSet(d) + _, err = client.AddDefinedSet(ctx, &api.AddDefinedSetRequest{ + Set: d, + }) case CMD_DEL: all := false if len(args) < 2 { all = true } - err = client.DeleteDefinedSet(d, all) + _, err = client.DeleteDefinedSet(ctx, &api.DeleteDefinedSetRequest{ + Set: d, + All: all, + }) case CMD_SET: - err = client.ReplaceDefinedSet(d) + _, err = client.ReplaceDefinedSet(ctx, &api.ReplaceDefinedSetRequest{ + Set: d, + }) } return err } @@ -525,10 +541,21 @@ func printPolicy(indent int, pd *api.Policy) { } func showPolicy(args []string) error { - policies, err := client.GetPolicy() + policies := make([]*api.Policy, 0) + stream, err := client.ListPolicy(ctx, &api.ListPolicyRequest{}) if err != nil { return err } + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { + return nil + } + policies = append(policies, r.Policy) + } + var m []*api.Policy if len(args) > 0 { for _, p := range policies { @@ -563,10 +590,21 @@ func showPolicy(args []string) error { } func showStatement(args []string) error { - stmts, err := client.GetStatement() + stmts := make([]*api.Statement, 0) + stream, err := client.ListStatement(ctx, &api.ListStatementRequest{}) if err != nil { return err } + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { + return err + } + stmts = append(stmts, r.Statement) + } + var m []*api.Statement if len(args) > 0 { for _, s := range stmts { @@ -608,9 +646,14 @@ func modStatement(op string, args []string) error { var err error switch op { case CMD_ADD: - err = client.AddStatement(stmt) + _, err = client.AddStatement(ctx, &api.AddStatementRequest{ + Statement: stmt, + }) case CMD_DEL: - err = client.DeleteStatement(stmt, true) + _, err = client.DeleteStatement(ctx, &api.DeleteStatementRequest{ + Statement: stmt, + All: true, + }) default: return fmt.Errorf("invalid operation: %s", op) } @@ -803,11 +846,17 @@ func modCondition(name, op string, args []string) error { var err error switch op { case CMD_ADD: - err = client.AddStatement(stmt) + _, err = client.AddStatement(ctx, &api.AddStatementRequest{ + Statement: stmt, + }) case CMD_DEL: - err = client.DeleteStatement(stmt, false) + _, err = client.DeleteStatement(ctx, &api.DeleteStatementRequest{ + Statement: stmt, + }) case CMD_SET: - err = client.ReplaceStatement(stmt) + _, err = client.ReplaceStatement(ctx, &api.ReplaceStatementRequest{ + Statement: stmt, + }) default: return fmt.Errorf("invalid operation: %s", op) } @@ -931,11 +980,17 @@ func modAction(name, op string, args []string) error { var err error switch op { case CMD_ADD: - err = client.AddStatement(stmt) + _, err = client.AddStatement(ctx, &api.AddStatementRequest{ + Statement: stmt, + }) case CMD_DEL: - err = client.DeleteStatement(stmt, false) + _, err = client.DeleteStatement(ctx, &api.DeleteStatementRequest{ + Statement: stmt, + }) case CMD_SET: - err = client.ReplaceStatement(stmt) + _, err = client.ReplaceStatement(ctx, &api.ReplaceStatementRequest{ + Statement: stmt, + }) default: return fmt.Errorf("invalid operation: %s", op) } @@ -960,15 +1015,26 @@ func modPolicy(modtype string, args []string) error { var err error switch modtype { case CMD_ADD: - err = client.AddPolicy(policy, true) + _, err = client.AddPolicy(ctx, &api.AddPolicyRequest{ + Policy: policy, + ReferExistingStatements: true, + }) case CMD_DEL: all := false if len(args) < 1 { all = true } - err = client.DeletePolicy(policy, all, true) + _, err = client.DeletePolicy(ctx, &api.DeletePolicyRequest{ + Policy: policy, + All: all, + PreserveStatements: true, + }) case CMD_SET: - err = client.ReplacePolicy(policy, true, true) + _, err = client.ReplacePolicy(ctx, &api.ReplacePolicyRequest{ + Policy: policy, + PreserveStatements: true, + ReferExistingStatements: true, + }) } return err } diff --git a/cmd/gobgp/cmd/root.go b/cmd/gobgp/cmd/root.go index 90df5ee4..e59c8324 100644 --- a/cmd/gobgp/cmd/root.go +++ b/cmd/gobgp/cmd/root.go @@ -16,11 +16,12 @@ package cmd import ( + "context" "fmt" "net/http" _ "net/http/pprof" - cli "github.com/osrg/gobgp/internal/pkg/client" + api "github.com/osrg/gobgp/api" "github.com/spf13/cobra" ) @@ -37,7 +38,8 @@ var globalOpts struct { CaFile string } -var client *cli.Client +var client api.GobgpApiClient +var ctx context.Context func NewRootCmd() *cobra.Command { cobra.EnablePrefixMatching = true @@ -53,7 +55,12 @@ func NewRootCmd() *cobra.Command { } if !globalOpts.GenCmpl { - client = newClient() + var err error + ctx = context.Background() + client, err = newClient(ctx) + if err != nil { + exitWithError(err) + } } }, Run: func(cmd *cobra.Command, args []string) { @@ -64,9 +71,6 @@ func NewRootCmd() *cobra.Command { } }, PersistentPostRun: func(cmd *cobra.Command, args []string) { - if client != nil { - client.Close() - } }, } diff --git a/cmd/gobgp/cmd/rpki.go b/cmd/gobgp/cmd/rpki.go index 853892d4..a4926088 100644 --- a/cmd/gobgp/cmd/rpki.go +++ b/cmd/gobgp/cmd/rpki.go @@ -17,19 +17,32 @@ package cmd import ( "fmt" + "io" "net" + "strconv" "time" + api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/pkg/packet/bgp" "github.com/spf13/cobra" ) func showRPKIServer(args []string) error { - servers, err := client.GetRPKI() + servers := make([]*api.Rpki, 0) + stream, err := client.ListRpki(ctx, &api.ListRpkiRequest{}) if err != nil { fmt.Println(err) return err } + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { + return err + } + servers = append(servers, r.Server) + } if len(args) == 0 { format := "%-23s %-6s %-10s %s\n" fmt.Printf(format, "Session", "State", "Uptime", "#IPv4/IPv6 records") @@ -41,32 +54,32 @@ func showRPKIServer(args []string) error { uptime = fmt.Sprint(formatTimedelta(int64(time.Since(time.Unix(r.State.Uptime, 0)).Seconds()))) } - fmt.Printf(format, net.JoinHostPort(r.Config.Address, fmt.Sprintf("%d", r.Config.Port)), s, uptime, fmt.Sprintf("%d/%d", r.State.RecordsV4, r.State.RecordsV6)) + fmt.Printf(format, net.JoinHostPort(r.Conf.Address, fmt.Sprintf("%d", r.Conf.RemotePort)), s, uptime, fmt.Sprintf("%d/%d", r.State.RecordIpv4, r.State.RecordIpv6)) } return nil } for _, r := range servers { - if r.Config.Address == args[0] { + if r.Conf.Address == args[0] { up := "Down" if r.State.Up { up = "Up" } - fmt.Printf("Session: %s, State: %s\n", r.Config.Address, up) - fmt.Println(" Port:", r.Config.Port) - fmt.Println(" Serial:", r.State.SerialNumber) - fmt.Printf(" Prefix: %d/%d\n", r.State.PrefixesV4, r.State.PrefixesV6) - fmt.Printf(" Record: %d/%d\n", r.State.RecordsV4, r.State.RecordsV6) + fmt.Printf("Session: %s, State: %s\n", r.Conf.Address, up) + fmt.Println(" Port:", r.Conf.RemotePort) + fmt.Println(" Serial:", r.State.Serial) + fmt.Printf(" Prefix: %d/%d\n", r.State.PrefixIpv4, r.State.PrefixIpv6) + fmt.Printf(" Record: %d/%d\n", r.State.RecordIpv4, r.State.RecordIpv6) fmt.Println(" Message statistics:") - fmt.Printf(" Receivedv4: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix) - fmt.Printf(" Receivedv6: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix) - fmt.Printf(" SerialNotify: %10d\n", r.State.RpkiMessages.RpkiReceived.SerialNotify) - fmt.Printf(" CacheReset: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheReset) - fmt.Printf(" CacheResponse: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheResponse) - fmt.Printf(" EndOfData: %10d\n", r.State.RpkiMessages.RpkiReceived.EndOfData) - fmt.Printf(" Error: %10d\n", r.State.RpkiMessages.RpkiReceived.Error) - fmt.Printf(" SerialQuery: %10d\n", r.State.RpkiMessages.RpkiSent.SerialQuery) - fmt.Printf(" ResetQuery: %10d\n", r.State.RpkiMessages.RpkiSent.ResetQuery) + fmt.Printf(" Receivedv4: %10d\n", r.State.ReceivedIpv4) + fmt.Printf(" Receivedv6: %10d\n", r.State.ReceivedIpv6) + fmt.Printf(" SerialNotify: %10d\n", r.State.SerialNotify) + fmt.Printf(" CacheReset: %10d\n", r.State.CacheReset) + fmt.Printf(" CacheResponse: %10d\n", r.State.CacheResponse) + fmt.Printf(" EndOfData: %10d\n", r.State.EndOfData) + fmt.Printf(" Error: %10d\n", r.State.Error) + fmt.Printf(" SerialQuery: %10d\n", r.State.SerialQuery) + fmt.Printf(" ResetQuery: %10d\n", r.State.ResetQuery) } } return nil @@ -77,10 +90,22 @@ func showRPKITable(args []string) error { if err != nil { exitWithError(err) } - roas, err := client.GetROA(family) + stream, err := client.ListRpkiTable(ctx, &api.ListRpkiTableRequest{ + Family: uint32(family), + }) if err != nil { exitWithError(err) } + roas := make([]*api.Roa, 0) + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { + exitWithError(err) + } + roas = append(roas, r.Roa) + } var format string afi, _ := bgp.RouteFamilyToAfiSafi(family) @@ -94,7 +119,7 @@ func showRPKITable(args []string) error { if len(args) > 0 && args[0] != r.Conf.Address { continue } - fmt.Printf(format, r.Prefix, fmt.Sprint(r.Maxlen), fmt.Sprint(r.As), net.JoinHostPort(r.Conf.Address, r.Conf.RemotePort)) + fmt.Printf(format, r.Prefix, fmt.Sprint(r.Maxlen), fmt.Sprint(r.As), net.JoinHostPort(r.Conf.Address, strconv.Itoa(int(r.Conf.RemotePort)))) } return nil } @@ -120,15 +145,25 @@ func NewRPKICmd() *cobra.Command { var err error switch args[1] { case "add": - err = client.AddRPKIServer(addr.String(), 323, 0) - case "reset": - err = client.ResetRPKIServer(addr.String()) - case "softreset": - err = client.SoftResetRPKIServer(addr.String()) + _, err = client.AddRpki(ctx, &api.AddRpkiRequest{ + Address: addr.String(), + Port: 323, + }) + case "reset", "softreset": + _, err = client.ResetRpki(ctx, &api.ResetRpkiRequest{ + Address: addr.String(), + Soft: func() bool { + return args[1] != "reset" + }(), + }) case "enable": - err = client.EnableRPKIServer(addr.String()) + _, err = client.EnableRpki(ctx, &api.EnableRpkiRequest{ + Address: addr.String(), + }) case "disable": - err = client.DisableRPKIServer(addr.String()) + _, err = client.DisableRpki(ctx, &api.DisableRpkiRequest{ + Address: addr.String(), + }) default: exitWithError(fmt.Errorf("unknown operation: %s", args[1])) } @@ -146,17 +181,6 @@ func NewRPKICmd() *cobra.Command { }, } tableCmd.PersistentFlags().StringVarP(&subOpts.AddressFamily, "address-family", "a", "", "address family") - - validateCmd := &cobra.Command{ - Use: "validate", - Run: func(cmd *cobra.Command, args []string) { - if err := client.ValidateRIBWithRPKI(args...); err != nil { - exitWithError(err) - } - }, - } - rpkiCmd.AddCommand(validateCmd) - rpkiCmd.AddCommand(tableCmd) return rpkiCmd } diff --git a/cmd/gobgp/cmd/rpki_test.go b/cmd/gobgp/cmd/rpki_test.go index 432d0bbc..72e28d52 100644 --- a/cmd/gobgp/cmd/rpki_test.go +++ b/cmd/gobgp/cmd/rpki_test.go @@ -16,6 +16,7 @@ package cmd import ( + "context" "testing" "time" @@ -54,8 +55,9 @@ func TestShowRPKITable(test *testing.T) { globalOpts.Host = "127.0.0.1" globalOpts.Port = 50052 - client = newClient() - defer client.Close() + ctx = context.Background() + client, err = newClient(ctx) + assert.Nil(err) // Wait for downloading ROA info for i := 0; ; i++ { diff --git a/cmd/gobgp/cmd/vrf.go b/cmd/gobgp/cmd/vrf.go index a8c2fcd8..9af7e11c 100644 --- a/cmd/gobgp/cmd/vrf.go +++ b/cmd/gobgp/cmd/vrf.go @@ -18,10 +18,12 @@ package cmd import ( "encoding/json" "fmt" + "io" "sort" "strconv" "strings" + api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/internal/pkg/apiutil" "github.com/osrg/gobgp/pkg/packet/bgp" @@ -29,13 +31,25 @@ import ( "github.com/spf13/cobra" ) -func getVrfs() (vrfs, error) { - ret, err := client.GetVRF() +func getVrfs() ([]*api.Vrf, error) { + stream, err := client.ListVrf(ctx, &api.ListVrfRequest{}) if err != nil { return nil, err } - sort.Sort(vrfs(ret)) - return ret, nil + vrfs := make([]*api.Vrf, 0) + for { + r, err := stream.Recv() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + vrfs = append(vrfs, r.Vrf) + } + sort.Slice(vrfs, func(i, j int) bool { + return vrfs[i].Name < vrfs[j].Name + }) + return vrfs, nil } func showVrfs() error { @@ -106,7 +120,6 @@ func showVrf(name string) error { } func modVrf(typ string, args []string) error { - var err error switch typ { case CMD_ADD: a, err := extractReserved(args, map[string]int{ @@ -153,16 +166,26 @@ func modVrf(typ string, args []string) error { return err } } - if err := client.AddVRF(name, int(id), rd, importRt, exportRt); err != nil { - return err - } + _, err = client.AddVrf(ctx, &api.AddVrfRequest{ + Vrf: &api.Vrf{ + Name: name, + Rd: apiutil.MarshalRD(rd), + ImportRt: apiutil.MarshalRTs(importRt), + ExportRt: apiutil.MarshalRTs(exportRt), + Id: uint32(id), + }, + }) + return err case CMD_DEL: if len(args) != 1 { return fmt.Errorf("Usage: gobgp vrf del <vrf name>") } - err = client.DeleteVRF(args[0]) + _, err := client.DeleteVrf(ctx, &api.DeleteVrfRequest{ + Name: args[0], + }) + return err } - return err + return nil } func NewVrfCmd() *cobra.Command { @@ -199,7 +222,7 @@ func NewVrfCmd() *cobra.Command { Run: func(cmd *cobra.Command, args []string) { var err error if len(args) == 1 { - var vs vrfs + var vs []*api.Vrf vs, err = getVrfs() if err != nil { exitWithError(err) diff --git a/cmd/gobgpd/main.go b/cmd/gobgpd/main.go index 31af0f67..146facad 100644 --- a/cmd/gobgpd/main.go +++ b/cmd/gobgpd/main.go @@ -175,7 +175,7 @@ func main() { for { select { case <-sigCh: - apiServer.Shutdown(context.Background(), &api.ShutdownRequest{}) + apiServer.StopBgp(context.Background(), &api.StopBgpRequest{}) return case newConfig := <-configCh: var added, deleted, updated []config.Neighbor @@ -184,7 +184,7 @@ func main() { if c == nil { c = newConfig - if _, err := apiServer.StartServer(context.Background(), &api.StartServerRequest{ + if _, err := apiServer.StartBgp(context.Background(), &api.StartBgpRequest{ Global: server.NewGlobalFromConfigStruct(&c.Global), }); err != nil { log.Fatalf("failed to set global config: %s", err) @@ -208,13 +208,7 @@ func main() { } if len(newConfig.Collector.Config.Url) > 0 { - if _, err := apiServer.AddCollector(context.Background(), &api.AddCollectorRequest{ - Url: c.Collector.Config.Url, - DbName: c.Collector.Config.DbName, - TableDumpInterval: c.Collector.Config.TableDumpInterval, - }); err != nil { - log.Fatalf("failed to set collector config: %s", err) - } + log.Fatal("collector feature is not supported") } for _, c := range newConfig.RpkiServers { @@ -374,7 +368,7 @@ func main() { for _, pg := range deletedPg { log.Infof("PeerGroup %s is deleted", pg.Config.PeerGroupName) if _, err := apiServer.DeletePeerGroup(context.Background(), &api.DeletePeerGroupRequest{ - PeerGroup: server.NewPeerGroupFromConfigStruct(&pg), + Name: pg.Config.PeerGroupName, }); err != nil { log.Warn(err) } @@ -410,7 +404,7 @@ func main() { } for _, p := range added { log.Infof("Peer %v is added", p.State.NeighborAddress) - if _, err := apiServer.AddNeighbor(context.Background(), &api.AddNeighborRequest{ + if _, err := apiServer.AddPeer(context.Background(), &api.AddPeerRequest{ Peer: server.NewPeerFromConfigStruct(&p), }); err != nil { log.Warn(err) @@ -418,15 +412,15 @@ func main() { } for _, p := range deleted { log.Infof("Peer %v is deleted", p.State.NeighborAddress) - if _, err := apiServer.DeleteNeighbor(context.Background(), &api.DeleteNeighborRequest{ - Peer: server.NewPeerFromConfigStruct(&p), + if _, err := apiServer.DeletePeer(context.Background(), &api.DeletePeerRequest{ + Address: p.State.NeighborAddress, }); err != nil { log.Warn(err) } } for _, p := range updated { log.Infof("Peer %v is updated", p.State.NeighborAddress) - if u, err := apiServer.UpdateNeighbor(context.Background(), &api.UpdateNeighborRequest{ + if u, err := apiServer.UpdatePeer(context.Background(), &api.UpdatePeerRequest{ Peer: server.NewPeerFromConfigStruct(&p), }); err != nil { log.Warn(err) @@ -436,9 +430,10 @@ func main() { } if updatePolicy { - if _, err := apiServer.SoftResetNeighbor(context.Background(), &api.SoftResetNeighborRequest{ + if _, err := apiServer.ResetPeer(context.Background(), &api.ResetPeerRequest{ Address: "", - Direction: api.SoftResetNeighborRequest_IN, + Direction: api.ResetPeerRequest_IN, + Soft: true, }); err != nil { log.Warn(err) } |