Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add stats poller service for retrieving VPP stats #1495

Merged
merged 8 commits into from
Oct 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

393 changes: 347 additions & 46 deletions api/configurator/configurator.pb.go

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions api/configurator/configurator.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ message Notification {
}
}

message Stats {
oneof stats {
vpp.Stats vpp_stats = 1;
}
}

// Configurator provides basic operations for managing configuration
// and monitoring state.
service Configurator {
Expand Down Expand Up @@ -95,3 +101,20 @@ message NotificationResponse {
// Notification data
Notification notification = 2;
}

// StatsPoller provides operations for retrieving statistics.
service StatsPoller {
// PollStats is used for polling metrics using poll period.
rpc PollStats(PollStatsRequest) returns (stream PollStatsResponse) {};
}

message PollStatsRequest {
// PeriodSec defines polling period (in seconds)
uint32 period_sec = 1;
}


message PollStatsResponse {
uint32 poll_seq = 1;
Stats stats = 2;
}
353 changes: 299 additions & 54 deletions api/models/vpp/interfaces/state.pb.go

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions api/models/vpp/interfaces/state.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,35 @@ option (gogoproto.messagename_all) = true;

import "models/vpp/interfaces/interface.proto";

message InterfaceStats {
string name = 1;

message CombinedCounter {
uint64 packets = 1;
uint64 bytes = 2;
}
CombinedCounter rx = 2;
CombinedCounter tx = 3;

CombinedCounter rx_unicast = 4;
CombinedCounter rx_multicast = 5;
CombinedCounter rx_broadcast = 6;
CombinedCounter tx_unicast = 7;
CombinedCounter tx_multicast = 8;
CombinedCounter tx_broadcast = 9;

uint64 rx_error = 12;
uint64 tx_error = 13;

uint64 rx_no_buf = 10;
uint64 rx_miss = 11;
uint64 drops = 14;
uint64 punts = 15;
uint64 ip4 = 16;
uint64 ip6 = 17;
uint64 mpls = 18;
}

message InterfaceState {
string name = 1;
string internal_name = 2;
Expand Down
145 changes: 93 additions & 52 deletions api/models/vpp/vpp.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/models/vpp/vpp.proto
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ message ConfigData {
message Notification {
interfaces.InterfaceNotification interface = 1;
}

message Stats {
interfaces.InterfaceStats interface = 1;
}
115 changes: 115 additions & 0 deletions examples/grpc_vpp/stats_poller/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) 2019 Cisco and/or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"log"
"net"
"time"

"github.com/ligato/cn-infra/agent"
"github.com/ligato/cn-infra/infra"
"github.com/namsral/flag"
"golang.org/x/net/context"
"google.golang.org/grpc"

"github.com/ligato/vpp-agent/api/configurator"
)

var (
address = flag.String("address", "localhost:9111", "address of GRPC server")
socketType = flag.String("socket-type", "tcp", "[tcp, tcp4, tcp6, unix, unixpacket]")
period = flag.Uint("period", 3, "Polling period (in seconds)")
)

func main() {
ep := &ExamplePlugin{}
ep.SetName("stats-poller-example")
ep.Setup()

a := agent.NewAgent(
agent.AllPlugins(ep),
)
if err := a.Run(); err != nil {
log.Fatal()
}
}

// ExamplePlugin demonstrates the use of grpc to watch on VPP notifications using vpp-agent.
type ExamplePlugin struct {
infra.PluginDeps

conn *grpc.ClientConn
}

// Init initializes example plugin.
func (p *ExamplePlugin) Init() (err error) {
// Set up connection to the server.
p.conn, err = grpc.Dial("unix",
grpc.WithInsecure(),
grpc.WithDialer(dialer(*socketType, *address, time.Second*3)))

if err != nil {
return err
}

client := configurator.NewStatsPollerClient(p.conn)

// Start stats poller.
go p.pollStats(client)

return err
}

// Get is an implementation of client-side statistics streaming.
func (p *ExamplePlugin) pollStats(client configurator.StatsPollerClient) {
p.Log.Infof("Polling every %v seconds..", *period)

req := &configurator.PollStatsRequest{
PeriodSec: uint32(*period),
}

ctx := context.Background()
stream, err := client.PollStats(ctx, req)
if err != nil {
p.Log.Fatalln("PollStats failed:", err)
}

var lastSeq uint32
for {
resp, err := stream.Recv()
if err != nil {
p.Log.Fatalln("Recv failed:", err)
}

if resp.PollSeq != lastSeq {
p.Log.Infof(" --- Poll sequence: %-3v", resp.PollSeq)
}
lastSeq = resp.PollSeq

vppStats := resp.GetStats().GetVppStats()
p.Log.Infof("VPP stats: %v", vppStats)
}
}

// Dialer for unix domain socket
func dialer(socket, address string, timeoutVal time.Duration) func(string, time.Duration) (net.Conn, error) {
return func(addr string, timeout time.Duration) (net.Conn, error) {
// Pass values
addr, timeout = address, timeoutVal
// Dial with timeout
return net.DialTimeout(socket, addr, timeoutVal)
}
}
File renamed without changes.
4 changes: 2 additions & 2 deletions plugins/govppmux/mock/mock_govppmux.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ func (p *GoVPPMux) ListStats(patterns ...string) ([]string, error) {
}

// DumpStats dumps stats from mocked stats API
func (p *GoVPPMux) DumpStats(patterns ...string) ([]*adapter.StatEntry, error) {
func (p *GoVPPMux) DumpStats(patterns ...string) ([]adapter.StatEntry, error) {
if p.stats == nil {
return nil, fmt.Errorf("failed to dump VPP stats, nil stats adapter")
}
return p.stats.DumpStats(patterns...)
}

// MockStats allows to set required stats which are then returned by 'ListStats' or 'DumpStats'
func (p *GoVPPMux) MockStats(stats []*adapter.StatEntry) error {
func (p *GoVPPMux) MockStats(stats []adapter.StatEntry) error {
if p.stats == nil {
return fmt.Errorf("failed to mock VPP stats, nil stats adapter")
}
Expand Down
Loading