From 50a652c4e8beccbb77d119241940ef1e21952af5 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 15:53:32 +0200 Subject: [PATCH 01/10] Add DumpInterface to vppcalls in ifplugin Signed-off-by: Ondrej Fabry --- plugins/vpp/ifplugin/vppcalls/if_vppcalls.go | 4 ++- .../vpp1901/dump_interface_vppcalls.go | 6 ++++ .../vpp1904/dump_interface_vppcalls.go | 6 ++++ .../vpp1908/dump_interface_vppcalls.go | 29 +++++++++++++++++-- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/plugins/vpp/ifplugin/vppcalls/if_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/if_vppcalls.go index 04d84dd4e2..9acdd70185 100644 --- a/plugins/vpp/ifplugin/vppcalls/if_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/if_vppcalls.go @@ -175,7 +175,7 @@ type InterfaceVppAPI interface { AttachInterfaceToBond(ifIdx, bondIfIdx uint32, isPassive, isLongTimeout bool) error // DetachInterfaceFromBond removes interface slave status from any bond interfaces. DetachInterfaceFromBond(ifIdx uint32) error - // SetVLanTagRewrite sets VLan tag rewrite rule for given sub-interface + // SetVLanTagRewrite sets VLan tag rewrite rule for given sub-interface SetVLanTagRewrite(ifIdx uint32, subIf *interfaces.SubInterface) error } @@ -189,6 +189,8 @@ type InterfaceVppRead interface { DumpInterfaces() (map[uint32]*InterfaceDetails, error) // DumpInterfacesByType returns all VPP interfaces of the specified type DumpInterfacesByType(reqType interfaces.Interface_Type) (map[uint32]*InterfaceDetails, error) + // DumpInterface dumps specific interface. + DumpInterface(ifIdx uint32) (*InterfaceDetails, error) // GetInterfaceVrf reads VRF table to interface GetInterfaceVrf(ifIdx uint32) (vrfID uint32, err error) // GetInterfaceVrfIPv6 reads IPv6 VRF table to interface diff --git a/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go index 1f89e22f74..fff7f64457 100644 --- a/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go @@ -16,6 +16,7 @@ package vpp1901 import ( "bytes" + "errors" "fmt" "net" "strings" @@ -47,6 +48,11 @@ func getMtu(vppMtu uint16) uint32 { return uint32(vppMtu) } +// DumpInterface dumps specific interface. +func (h *InterfaceVppHandler) DumpInterface(ifIdx uint32) (*vppcalls.InterfaceDetails, error) { + return nil, errors.New("not supported") +} + // DumpInterfacesByType implements interface handler. func (h *InterfaceVppHandler) DumpInterfacesByType(reqType interfaces.Interface_Type) (map[uint32]*vppcalls.InterfaceDetails, error) { // Dump all diff --git a/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go index e6f82cca2d..e44b23f08a 100644 --- a/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go @@ -17,6 +17,7 @@ package vpp1904 import ( "bytes" "encoding/hex" + "errors" "fmt" "net" "strings" @@ -46,6 +47,11 @@ func getMtu(vppMtu uint16) uint32 { return uint32(vppMtu) } +// DumpInterface dumps specific interface. +func (h *InterfaceVppHandler) DumpInterface(ifIdx uint32) (*vppcalls.InterfaceDetails, error) { + return nil, errors.New("not supported") +} + // DumpInterfacesByType implements interface handler. func (h *InterfaceVppHandler) DumpInterfacesByType(reqType interfaces.Interface_Type) (map[uint32]*vppcalls.InterfaceDetails, error) { // Dump all diff --git a/plugins/vpp/ifplugin/vppcalls/vpp1908/dump_interface_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vpp1908/dump_interface_vppcalls.go index 67bd9e53cb..8694e01b13 100644 --- a/plugins/vpp/ifplugin/vppcalls/vpp1908/dump_interface_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vpp1908/dump_interface_vppcalls.go @@ -17,7 +17,9 @@ package vpp1908 import ( "bytes" "encoding/hex" + "errors" "fmt" + "math" "net" "strings" @@ -46,6 +48,22 @@ func getMtu(vppMtu uint16) uint32 { return uint32(vppMtu) } +// DumpInterface dumps specific interface. +func (h *InterfaceVppHandler) DumpInterface(ifIdx uint32) (*vppcalls.InterfaceDetails, error) { + var iface *vppcalls.InterfaceDetails + + ifaces, err := h.dumpInterfaces(ifIdx) + if err != nil { + return nil, err + } + iface, ok := ifaces[ifIdx] + if !ok { + return nil, errors.New("interface not found in dump") + } + + return iface, nil +} + // DumpInterfacesByType implements interface handler. func (h *InterfaceVppHandler) DumpInterfacesByType(reqType interfaces.Interface_Type) (map[uint32]*vppcalls.InterfaceDetails, error) { // Dump all @@ -63,12 +81,19 @@ func (h *InterfaceVppHandler) DumpInterfacesByType(reqType interfaces.Interface_ return ifs, nil } -func (h *InterfaceVppHandler) dumpInterfaces() (map[uint32]*vppcalls.InterfaceDetails, error) { +func (h *InterfaceVppHandler) dumpInterfaces(ifIdxs ...uint32) (map[uint32]*vppcalls.InterfaceDetails, error) { // map for the resulting interfaces ifs := make(map[uint32]*vppcalls.InterfaceDetails) + var ifIdx uint32 = math.MaxUint32 + if len(ifIdxs) > 0 { + ifIdx = ifIdxs[0] + } + // First, dump all interfaces to create initial data. - reqCtx := h.callsChannel.SendMultiRequest(&binapi_interface.SwInterfaceDump{}) + reqCtx := h.callsChannel.SendMultiRequest(&binapi_interface.SwInterfaceDump{ + SwIfIndex: binapi_interface.InterfaceIndex(ifIdx), + }) for { ifDetails := &binapi_interface.SwInterfaceDetails{} stop, err := reqCtx.ReceiveReply(ifDetails) From dd28d03a8fc76e146dce2278d4caaa41a2eb85e1 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 15:54:07 +0200 Subject: [PATCH 02/10] Cleanup vpp integration tests Signed-off-by: Ondrej Fabry --- ...1_basic_test.go => 001_interfaces_test.go} | 108 +++++++++--------- tests/integration/vpp/002_routes_test.go | 65 +++++++++++ tests/integration/vpp/integration_test.go | 91 +++++++++------ tests/integration/vpp_integration.sh | 47 +++++--- 4 files changed, 209 insertions(+), 102 deletions(-) rename tests/integration/vpp/{001_basic_test.go => 001_interfaces_test.go} (55%) create mode 100644 tests/integration/vpp/002_routes_test.go diff --git a/tests/integration/vpp/001_basic_test.go b/tests/integration/vpp/001_interfaces_test.go similarity index 55% rename from tests/integration/vpp/001_basic_test.go rename to tests/integration/vpp/001_interfaces_test.go index 0a6830b81e..4b4c3f8852 100644 --- a/tests/integration/vpp/001_basic_test.go +++ b/tests/integration/vpp/001_interfaces_test.go @@ -15,47 +15,83 @@ package vpp import ( - "net" "testing" "github.com/ligato/cn-infra/logging/logrus" vpp_interfaces "github.com/ligato/vpp-agent/api/models/vpp/interfaces" - vpp_l3 "github.com/ligato/vpp-agent/api/models/vpp/l3" _ "github.com/ligato/vpp-agent/plugins/vpp/ifplugin" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" ifplugin_vppcalls "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - _ "github.com/ligato/vpp-agent/plugins/vpp/l3plugin" - l3plugin_vppcalls "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vrfidx" ) +func TestInterfaceDump(t *testing.T) { + ctx := setupVPP(t) + defer ctx.teardownVPP() + + h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.Chan, logrus.NewLogger("test")) + + ifIdx0, err := h.AddLoopbackInterface("loop0") + if err != nil { + t.Fatalf("creating loopback interface failed: %v", err) + } + t.Logf("loop0 index: %+v", ifIdx0) + + ifIdx, err := h.AddLoopbackInterface("loop1") + if err != nil { + t.Fatalf("creating loopback interface failed: %v", err) + } + t.Logf("loop1 index: %+v", ifIdx) + + ifaces, err := h.DumpInterfaces() + if err != nil { + t.Fatalf("dumping interfaces failed: %v", err) + } + if len(ifaces) != 3 { + t.Fatalf("expected 3 interfaces in dump, got %d", len(ifaces)) + } + + iface, err := h.DumpInterface(ifIdx) + if err != nil { + t.Fatalf("dumping interface failed: %v", err) + } + t.Logf("interface: %+v", iface.Interface) + if iface.Interface == nil { + t.Fatalf("expected interface, got nil") + } + if iface.Interface.Name != "loop1" { + t.Errorf("expected interface name to be loop1, got %v", iface.Interface.Name) + } + if iface.Interface.Type != vpp_interfaces.Interface_SOFTWARE_LOOPBACK { + t.Errorf("expected interface type to be loopback, got %v", iface.Interface.Type) + } +} + func TestLoopbackInterface(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.Chan, logrus.NewLogger("test")) - index, err := h.AddLoopbackInterface("loop1") + ifIdx, err := h.AddLoopbackInterface("loop1") if err != nil { t.Fatalf("creating loopback interface failed: %v", err) } - t.Logf("loopback index: %+v", index) + t.Logf("loopback index: %+v", ifIdx) ifaces, err := h.DumpInterfaces() if err != nil { t.Fatalf("dumping interfaces failed: %v", err) } - iface, ok := ifaces[index] + iface, ok := ifaces[ifIdx] if !ok { t.Fatalf("loopback interface not found in dump") } t.Logf("interface: %+v", iface.Interface) if iface.Interface.Name != "loop1" { - t.Fatalf("expected interface name to be loop1, got %v", iface.Interface.Name) + t.Errorf("expected interface name to be loop1, got %v", iface.Interface.Name) } if iface.Interface.Type != vpp_interfaces.Interface_SOFTWARE_LOOPBACK { - t.Fatalf("expected interface type to be loopback, got %v", iface.Interface.Type) + t.Errorf("expected interface type to be loopback, got %v", iface.Interface.Type) } } @@ -65,68 +101,30 @@ func TestMemifInterface(t *testing.T) { h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.Chan, logrus.NewLogger("test")) - index, err := h.AddMemifInterface("memif1", &vpp_interfaces.MemifLink{ + ifIdx, err := h.AddMemifInterface("memif1", &vpp_interfaces.MemifLink{ Id: 1, Mode: vpp_interfaces.MemifLink_IP, Secret: "secret", Master: true, - }, 0 ) - + }, 0) if err != nil { t.Fatalf("creating memif interface failed: %v", err) } - t.Logf("memif index: %+v", index) + t.Logf("memif index: %+v", ifIdx) ifaces, err := h.DumpInterfaces() if err != nil { t.Fatalf("dumping interfaces failed: %v", err) } - iface, ok := ifaces[index] + iface, ok := ifaces[ifIdx] if !ok { t.Fatalf("Memif interface not found in dump") } t.Logf("interface: %+v", iface.Interface) if iface.Interface.Name != "memif1" { - t.Fatalf("expected interface name to be memif1, got %v", iface.Interface.Name) + t.Errorf("expected interface name to be memif1, got %v", iface.Interface.Name) } if iface.Interface.Type != vpp_interfaces.Interface_MEMIF { - t.Fatalf("expected interface type to be memif, got %v", iface.Interface.Type) - } -} - -func TestRoutes(t *testing.T) { - ctx := setupVPP(t) - defer ctx.teardownVPP() - - ifIndexes := ifaceidx.NewIfaceIndex(logrus.NewLogger("test-if"), "test-if") - vrfIndexes := vrfidx.NewVRFIndex(logrus.NewLogger("test-vrf"), "test-vrf") - vrfIndexes.Put("vrf1-ipv4", &vrfidx.VRFMetadata{Index: 0, Protocol: vpp_l3.VrfTable_IPV4}) - vrfIndexes.Put("vrf1-ipv6", &vrfidx.VRFMetadata{Index: 0, Protocol: vpp_l3.VrfTable_IPV6}) - - h := l3plugin_vppcalls.CompatibleL3VppHandler(ctx.Chan, ifIndexes, vrfIndexes, logrus.NewLogger("test")) - - routes, err := h.DumpRoutes() - if err != nil { - t.Fatalf("dumping routes failed: %v", err) - } - t.Logf("%d routes dumped", len(routes)) - - var hasIPv4, hasIPv6 bool - for _, route := range routes { - t.Logf(" - route: %+v", route.Route) - - ip, _, err := net.ParseCIDR(route.Route.DstNetwork) - if err != nil { - t.Fatalf("invalid dst network: %v", route.Route.DstNetwork) - } - if ip.To4() == nil { - hasIPv4 = true - } else { - hasIPv6 = true - } - } - - if !hasIPv4 || !hasIPv6 { - t.Fatalf("expected dump to contain both IPv4 and IPv6 routes") + t.Errorf("expected interface type to be memif, got %v", iface.Interface.Type) } } diff --git a/tests/integration/vpp/002_routes_test.go b/tests/integration/vpp/002_routes_test.go new file mode 100644 index 0000000000..264e3d6c8f --- /dev/null +++ b/tests/integration/vpp/002_routes_test.go @@ -0,0 +1,65 @@ +// 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 vpp + +import ( + "net" + "testing" + + "github.com/ligato/cn-infra/logging/logrus" + + vpp_l3 "github.com/ligato/vpp-agent/api/models/vpp/l3" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + _ "github.com/ligato/vpp-agent/plugins/vpp/l3plugin" + l3plugin_vppcalls "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" + "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vrfidx" +) + +func TestRoutes(t *testing.T) { + ctx := setupVPP(t) + defer ctx.teardownVPP() + + ifIndexes := ifaceidx.NewIfaceIndex(logrus.NewLogger("test-if"), "test-if") + vrfIndexes := vrfidx.NewVRFIndex(logrus.NewLogger("test-vrf"), "test-vrf") + vrfIndexes.Put("vrf1-ipv4", &vrfidx.VRFMetadata{Index: 0, Protocol: vpp_l3.VrfTable_IPV4}) + vrfIndexes.Put("vrf1-ipv6", &vrfidx.VRFMetadata{Index: 0, Protocol: vpp_l3.VrfTable_IPV6}) + + h := l3plugin_vppcalls.CompatibleL3VppHandler(ctx.Chan, ifIndexes, vrfIndexes, logrus.NewLogger("test")) + + routes, err := h.DumpRoutes() + if err != nil { + t.Fatalf("dumping routes failed: %v", err) + } + t.Logf("%d routes dumped", len(routes)) + + var hasIPv4, hasIPv6 bool + for _, route := range routes { + t.Logf(" - route: %+v", route.Route) + + ip, _, err := net.ParseCIDR(route.Route.DstNetwork) + if err != nil { + t.Fatalf("invalid dst network: %v", route.Route.DstNetwork) + } + if ip.To4() == nil { + hasIPv4 = true + } else { + hasIPv6 = true + } + } + + if !hasIPv4 || !hasIPv6 { + t.Fatalf("expected dump to contain both IPv4 and IPv6 routes") + } +} diff --git a/tests/integration/vpp/integration_test.go b/tests/integration/vpp/integration_test.go index 1271423629..44bd039db0 100644 --- a/tests/integration/vpp/integration_test.go +++ b/tests/integration/vpp/integration_test.go @@ -17,6 +17,7 @@ package vpp import ( "bytes" "flag" + "fmt" "log" "os" "os/exec" @@ -42,6 +43,14 @@ var ( debug = flag.Bool("debug", false, "Turn on debug mode.") ) +const ( + vppExitTimeout = time.Second * 1 + vppBootDelay = time.Millisecond * 100 + vppTermDelay = time.Millisecond * 50 + vppConnectRetryDelay = time.Second + vppConnectRetries = 3 +) + func init() { log.SetFlags(log.Lmicroseconds | log.Lshortfile) flag.Parse() @@ -62,7 +71,7 @@ func setupVPP(t *testing.T) *testCtx { if os.Getenv("TRAVIS") != "" { t.Skip("skipping test for Travis") } - t.Logf("=== VPP setup ===") + t.Logf("--- setupVPP ---") RegisterTestingT(t) @@ -72,15 +81,16 @@ func setupVPP(t *testing.T) *testCtx { t.Fatalf("listing processes failed: %v", err) } for _, process := range processes { - if strings.Contains(process.Executable(), "vpp") { - t.Logf("- found VPP process: %q (PID: %d)", process.Executable(), process.Pid()) + proc := process.Executable() + if strings.Contains(proc, "vpp") && process.Pid() != os.Getpid() { + t.Logf(" - found process: %+v", process) } - if process.Executable() == *vppPath || process.Executable() == "vpp" || process.Executable() == "vpp_main" { - t.Fatalf("VPP is already running, PID: %v", process.Pid()) + switch proc { + case *vppPath, "vpp", "vpp_main": + t.Fatalf("VPP is already running (PID: %v)", process.Pid()) } } - // remove binapi files from previous run var removeFile = func(path string) { if err := os.Remove(path); err == nil { t.Logf("removed file %q", path) @@ -88,51 +98,65 @@ func setupVPP(t *testing.T) *testCtx { t.Fatalf("removing file %q failed: %v", path, err) } } - removeFile("/run/vpp-api.sock") - - t.Logf("starting VPP process: %q", *vppPath) + // remove binapi files from previous run + removeFile(*vppSockAddr) - cmd := exec.Command(*vppPath, "-c", *vppConfig) var stderr, stdout bytes.Buffer + cmd := exec.Command(*vppPath, "-c", *vppConfig) cmd.Stderr = &stderr cmd.Stdout = &stdout // ensure that process is killed when current process exits cmd.SysProcAttr = &syscall.SysProcAttr{Pdeathsig: syscall.SIGKILL} + t.Logf("starting VPP: %v", strings.Join(cmd.Args, " ")) + if err := cmd.Start(); err != nil { t.Fatalf("starting VPP failed: %v", err) } - t.Logf("VPP process started (PID: %v)", cmd.Process.Pid) + t.Logf("VPP start OK (PID: %v)", cmd.Process.Pid) adapter := govppmux.NewVppAdapter(*vppSockAddr, false) + + // wait until the socket is ready if err := adapter.WaitReady(); err != nil { t.Logf("WaitReady failed: %v", err) } - - time.Sleep(time.Millisecond * 100) - - t.Logf("connecting to VPP..") - conn, err := govppcore.Connect(adapter) + time.Sleep(vppBootDelay) + + connectRetry := func(retries int) (conn *govppcore.Connection, err error) { + for i := 1; i <= retries; i++ { + conn, err = govppcore.Connect(adapter) + if err != nil { + t.Logf("connect attempt #%d failed: %v", i, err) + time.Sleep(vppConnectRetryDelay) + continue + } + return + } + return nil, fmt.Errorf("failed to connect after %d retries", retries) + } + conn, err := connectRetry(vppConnectRetries) if err != nil { - t.Logf("sending KILL signal to VPP") + t.Errorf("connecting to VPP failed: %v", err) if err := cmd.Process.Kill(); err != nil { t.Fatalf("killing VPP failed: %v", err) } if state, err := cmd.Process.Wait(); err != nil { - t.Logf("VPP process wait failed: %v", err) + t.Logf("VPP wait failed: %v", err) } else { - t.Logf("VPP killed: %v", state) + t.Logf("VPP wait OK: %v", state) } - t.Fatalf("connecting to VPP failed: %v", err) - } else { - t.Logf("connected to VPP successfully") + t.FailNow() } + t.Logf("VPP connect OK") ch, err := conn.NewAPIChannel() if err != nil { t.Fatalf("creating channel failed: %v", err) } + t.Logf("---------------") + return &testCtx{ t: t, VPP: cmd, @@ -144,7 +168,7 @@ func setupVPP(t *testing.T) *testCtx { } func (ctx *testCtx) teardownVPP() { - ctx.t.Logf("--- VPP teardown ---") + ctx.t.Logf("--- teardownVPP ---") // disconnect sometimes hangs done := make(chan struct{}) @@ -155,19 +179,18 @@ func (ctx *testCtx) teardownVPP() { }() select { case <-done: - ctx.t.Logf("VPP disconnected") + ctx.t.Logf("VPP disconnect OK") + time.Sleep(vppTermDelay) - case <-time.After(time.Second * 1): + case <-time.After(vppExitTimeout): ctx.t.Logf("VPP disconnect timeout") } - time.Sleep(time.Millisecond * 100) - - ctx.t.Logf("sending SIGTERM to VPP") if err := ctx.VPP.Process.Signal(syscall.SIGTERM); err != nil { - ctx.t.Fatalf("sending SIGTERM signal to VPP failed: %v", err) + ctx.t.Fatalf("sending SIGTERM to VPP failed: %v", err) } + // wait until VPP exits exit := make(chan struct{}) go func() { if err := ctx.VPP.Wait(); err != nil { @@ -177,15 +200,15 @@ func (ctx *testCtx) teardownVPP() { }() select { case <-exit: - ctx.t.Logf("VPP exited") + ctx.t.Logf("VPP exit OK") - case <-time.After(time.Second * 1): + case <-time.After(vppExitTimeout): ctx.t.Logf("VPP exit timeout") - - ctx.t.Logf("sending SIGKILL to VPP") + ctx.t.Logf("sending SIGKILL to VPP..") if err := ctx.VPP.Process.Signal(syscall.SIGKILL); err != nil { - ctx.t.Fatalf("sending SIGKILL signal to VPP failed: %v", err) + ctx.t.Fatalf("sending SIGKILL to VPP failed: %v", err) } } + ctx.t.Logf("-------------------") } diff --git a/tests/integration/vpp_integration.sh b/tests/integration/vpp_integration.sh index 9943ce7241..21644ed86c 100755 --- a/tests/integration/vpp_integration.sh +++ b/tests/integration/vpp_integration.sh @@ -1,24 +1,45 @@ -#!/usr/bin/env bash +#!/bin/bash +set -eu -set -euo pipefail +# compile test +go test -c ./tests/integration/vpp -o ./tests/integration/vpp/vpp-integration.test +# start vpp image +cid=$(docker run -d -it \ + -v $(pwd)/tests/integration/vpp/vpp-integration.test:/vpp-integration.test:ro \ + --label vpp.integration.test="$*" \ + "$VPP_IMG" bash) -function on_exit() { - echo "-> cleaning up" - docker stop -t 3 vpp-integration +on_exit() { + docker stop -t 2 "$cid" >/dev/null + docker rm "$cid" >/dev/null } -# compile vpp integration test -go test -v -c ./tests/integration/vpp +vppver=$(docker exec -i "$cid" dpkg-query -f '${Version}' -W vpp) -# start vpp image -docker run --rm --name vpp-integration -d -i -v $(pwd):/data:ro "${VPP_IMG}" bash -i trap 'on_exit' EXIT +echo "=============================================================" +echo -e " VPP Integration Test - \e[1;33m${vppver}\e[0m" +echo "=============================================================" + # run integration test -docker exec -it vpp-integration /data/vpp.test -test.v -vpp-config=/etc/vpp/startup.conf || { +if docker exec -i "$cid" /vpp-integration.test -vpp-config=/etc/vpp/startup.conf $*; then + echo >&2 "-------------------------------------------------------------" + echo >&2 -e " \e[32mPASSED\e[0m (took: ${SECONDS}s)" + echo >&2 "-------------------------------------------------------------" + exit 0 +else res=$? - echo >&2 "VPP integration tests FAILED!" - docker logs vpp-integration + echo >&2 "-------------------------------------------------------------" + echo >&2 -e " \e[31mFAILED!\e[0m (exit code: $res)" + echo >&2 "-------------------------------------------------------------" + + # dump container logs + logs=$(docker logs --tail 50 "$cid") + if [[ -n "$logs" ]]; then + echo >&2 "$logs" + fi + exit $res -} +fi From a75bb398f0169cbb9c00ea831d75fd777a98995d Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 22:36:59 +0200 Subject: [PATCH 03/10] Fix file name Signed-off-by: Ondrej Fabry --- .../vpp1908/{subif_vppcals_test.go => subif_vppcalls_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/vpp/ifplugin/vppcalls/vpp1908/{subif_vppcals_test.go => subif_vppcalls_test.go} (100%) diff --git a/plugins/vpp/ifplugin/vppcalls/vpp1908/subif_vppcals_test.go b/plugins/vpp/ifplugin/vppcalls/vpp1908/subif_vppcalls_test.go similarity index 100% rename from plugins/vpp/ifplugin/vppcalls/vpp1908/subif_vppcals_test.go rename to plugins/vpp/ifplugin/vppcalls/vpp1908/subif_vppcalls_test.go From cc87d6c719967d52aaafb0db0b8fd18f497bcb36 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 23:43:44 +0200 Subject: [PATCH 04/10] Hide iptables warning when no config found Signed-off-by: Ondrej Fabry --- plugins/linux/iptablesplugin/iptablesplugin.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/linux/iptablesplugin/iptablesplugin.go b/plugins/linux/iptablesplugin/iptablesplugin.go index ff5fd7ab52..4c3e1c21cd 100644 --- a/plugins/linux/iptablesplugin/iptablesplugin.go +++ b/plugins/linux/iptablesplugin/iptablesplugin.go @@ -36,7 +36,8 @@ type IPTablesPlugin struct { Deps // From configuration file - disabled bool + disabled bool + configFound bool // system handlers iptHandler linuxcalls.IPTablesAPI @@ -75,7 +76,7 @@ func (p *IPTablesPlugin) Init() error { // init iptables handler p.iptHandler = linuxcalls.NewIPTablesHandler() err = p.iptHandler.Init() - if err != nil { + if err != nil && p.configFound { // just warn here, iptables / ip6tables just may not be installed - will return // an error by attempt to configure it p.Log.Warnf("Error by initializing iptables handler: %v", err) @@ -112,5 +113,6 @@ func (p *IPTablesPlugin) retrieveConfig() (*Config, error) { if err != nil { return nil, err } + p.configFound = true return config, err } From 0218c2f907114acc460432b3bcf5a0eabad26668 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 23:44:08 +0200 Subject: [PATCH 05/10] Print shm warning directly into stderr Signed-off-by: Ondrej Fabry --- plugins/govppmux/adapter_puregoclient.go | 26 ++++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/plugins/govppmux/adapter_puregoclient.go b/plugins/govppmux/adapter_puregoclient.go index 4e8e6c9357..0f542641f8 100644 --- a/plugins/govppmux/adapter_puregoclient.go +++ b/plugins/govppmux/adapter_puregoclient.go @@ -17,29 +17,33 @@ package govppmux import ( + "fmt" + "os" + "git.fd.io/govpp.git/adapter" "git.fd.io/govpp.git/adapter/socketclient" "git.fd.io/govpp.git/adapter/statsclient" - "github.com/ligato/cn-infra/logging" ) +const noShmWarning = `Using shared memory for VPP binary API is not currently supported in pure Go client! + + To use socket client for VPP binary API (recommended): + - unset GOVPPMUX_NOSOCK environment variable + - remove these settings from govpp.conf config: shm-prefix, connect-via-shm + + If you still want to use shared memory for VPP binary API: + - compile your agent with this build tag: vppapiclient + - vppapiclient requires CGo and needs VPP to be installed +` + // NewVppAdapter returns VPP binary API adapter, implemented as pure Go client. func NewVppAdapter(addr string, useShm bool) adapter.VppAPI { if useShm { - logging.Warnf(`Using shared memory for VPP binary API is not currently supported in pure Go client! - - To use socket client for VPP binary API: - - unset GOVPPMUX_NOSOCK environment variable - - remove these settings from govpp.conf config: shm-prefix, connect-via-shm - - If you still want to use shared memory for VPP binary API (not recommended): - - compile your agent with this build tag: vppapiclient -`) + fmt.Fprintf(os.Stderr, noShmWarning) panic("No implementation for shared memory in pure Go client!") } // addr is used as socket path return socketclient.NewVppClient(addr) - } // NewStatsAdapter returns VPP stats API adapter, implemented as pure Go client. From 7362406164320a5b83539debd68eabd89376fe2d Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 23:44:53 +0200 Subject: [PATCH 06/10] Fix single interface dump for older VPP Signed-off-by: Ondrej Fabry --- .../vppcalls/vpp1901/dump_interface_vppcalls.go | 11 ++++++++++- .../vppcalls/vpp1904/dump_interface_vppcalls.go | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go index fff7f64457..4a95de10c2 100644 --- a/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vpp1901/dump_interface_vppcalls.go @@ -50,7 +50,16 @@ func getMtu(vppMtu uint16) uint32 { // DumpInterface dumps specific interface. func (h *InterfaceVppHandler) DumpInterface(ifIdx uint32) (*vppcalls.InterfaceDetails, error) { - return nil, errors.New("not supported") + ifaces, err := h.DumpInterfaces() + if err != nil { + return nil, err + } + + iface, ok := ifaces[ifIdx] + if !ok { + return nil, errors.New("interface index not found in dump") + } + return iface, nil } // DumpInterfacesByType implements interface handler. diff --git a/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go index e44b23f08a..7ce358e3a4 100644 --- a/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vpp1904/dump_interface_vppcalls.go @@ -49,7 +49,16 @@ func getMtu(vppMtu uint16) uint32 { // DumpInterface dumps specific interface. func (h *InterfaceVppHandler) DumpInterface(ifIdx uint32) (*vppcalls.InterfaceDetails, error) { - return nil, errors.New("not supported") + ifaces, err := h.DumpInterfaces() + if err != nil { + return nil, err + } + + iface, ok := ifaces[ifIdx] + if !ok { + return nil, errors.New("interface index not found in dump") + } + return iface, nil } // DumpInterfacesByType implements interface handler. From 6e420e02c22a2f6a4c52a8674519b5d66272b5d6 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 23:47:03 +0200 Subject: [PATCH 07/10] Fix retrieving memory stats in telemetry for VPP 19.08 Signed-off-by: Ondrej Fabry --- .../vppcalls/vpp1908/telemetry_vppcalls.go | 6 ++--- .../vpp1908/telemetry_vppcalls_test.go | 26 +++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go b/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go index 0a1e71a0d4..dd6cc83e4a 100644 --- a/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go +++ b/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go @@ -57,8 +57,8 @@ var ( // Regular expression to parse output from `show memory` memoryRe = regexp.MustCompile( `Thread\s+(\d+)\s+(\w+).?\s+` + - `virtual memory start 0x[0-9abcdef]+, size ([\dkmg\.]+), ([\dkmg\.]+) pages, page size ([\dkmg\.]+)\s+` + - `(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)+\s+` + + `virtual memory start 0x[0-9a-f]+, size ([\dkmg\.]+), ([\dkmg\.]+) pages, page size ([\dkmg\.]+)\s+` + + `(?:(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)*|page information not available.*)\s+` + `\s+total: ([\dkmgKMG\.]+), used: ([\dkmgKMG\.]+), free: ([\dkmgKMG\.]+), trimmable: ([\dkmgKMG\.]+)`, ) ) @@ -69,7 +69,7 @@ func (h *TelemetryHandler) GetMemory(ctx context.Context) (*vppcalls.MemoryInfo, } func (h *TelemetryHandler) getMemoryCLI(ctx context.Context) (*vppcalls.MemoryInfo, error) { - data, err := h.vpe.RunCli("show memory") + data, err := h.vpe.RunCli("show memory main-heap") if err != nil { return nil, err } diff --git a/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls_test.go b/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls_test.go index 1ca9b4803e..dda265d1dc 100644 --- a/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls_test.go +++ b/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls_test.go @@ -16,13 +16,14 @@ package vpp1908_test import ( "context" - "github.com/ligato/vpp-agent/plugins/telemetry/vppcalls/vpp1908" "testing" + . "github.com/onsi/gomega" + "github.com/ligato/vpp-agent/plugins/telemetry/vppcalls" + "github.com/ligato/vpp-agent/plugins/telemetry/vppcalls/vpp1908" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpp1908/vpe" "github.com/ligato/vpp-agent/plugins/vpp/vppcallmock" - . "github.com/onsi/gomega" ) func TestGetBuffers(t *testing.T) { @@ -410,6 +411,27 @@ no traced allocations Reclaimed: 996.12e6, }, }, + { + name: "19.08 update", + reply: `Thread 0 vpp_main + virtual memory start 0x7ff41b3ca000, size 1048640k, 262160 pages, page size 4k + page information not available (errno 1) + total: 1.00G, used: 19.81M, free: 1004.25M, trimmable: 1004.24M +`, + threadCount: 1, + threadIdx: 0, + thread: vppcalls.MemoryThread{ + ID: 0, + Name: "vpp_main", + Size: 1048.64e6, + Pages: 262160, + PageSize: 4000, + Used: 19.81e6, + Total: 1e9, + Free: 1004.25e6, + Reclaimed: 1004.24e6, + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { From 99ac9f10acc73bf7645e54134095923251e1e1b3 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Thu, 18 Jul 2019 23:48:25 +0200 Subject: [PATCH 08/10] Add tests for telemetry to VPP integration tests Signed-off-by: Ondrej Fabry --- plugins/telemetry/vppcalls/vppcalls_api.go | 7 +- tests/integration/vpp/000_initial_test.go | 4 +- tests/integration/vpp/001_telemetry_test.go | 64 +++++++++++++++++++ ...erfaces_test.go => 010_interfaces_test.go} | 6 +- ...{002_routes_test.go => 020_routes_test.go} | 2 +- tests/integration/vpp/integration_test.go | 46 ++++++++----- tests/integration/vpp_integration.sh | 2 +- 7 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 tests/integration/vpp/001_telemetry_test.go rename tests/integration/vpp/{001_interfaces_test.go => 010_interfaces_test.go} (92%) rename tests/integration/vpp/{002_routes_test.go => 020_routes_test.go} (94%) diff --git a/plugins/telemetry/vppcalls/vppcalls_api.go b/plugins/telemetry/vppcalls/vppcalls_api.go index d77804167d..36c0f77d2f 100644 --- a/plugins/telemetry/vppcalls/vppcalls_api.go +++ b/plugins/telemetry/vppcalls/vppcalls_api.go @@ -19,7 +19,6 @@ import ( govppapi "git.fd.io/govpp.git/api" log "github.com/ligato/cn-infra/logging" - "github.com/ligato/vpp-agent/plugins/govppmux" ) var Versions = map[string]HandlerVersion{} @@ -152,8 +151,8 @@ type BuffersItem struct { NumFree uint64 `json:"num_free"` } -func CompatibleTelemetryHandler(ch govppapi.Channel, vpp govppmux.StatsAPI) TelemetryVppAPI { - status, err := vpp.VPPInfo() +func CompatibleTelemetryHandler(ch govppapi.Channel, vpp govppapi.StatsProvider) TelemetryVppAPI { + /*status, err := vpp.VPPInfo() if err != nil { log.Warnf("retrieving VPP status failed: %v", err) return nil @@ -167,7 +166,7 @@ func CompatibleTelemetryHandler(ch govppapi.Channel, vpp govppmux.StatsAPI) Tele log.Debug("found compatible version: ", ver) return h.New(ch, vpp) } - } + }*/ for ver, h := range Versions { if err := ch.CheckCompatiblity(h.Msgs...); err != nil { log.Debugf("version %s not compatible", ver) diff --git a/tests/integration/vpp/000_initial_test.go b/tests/integration/vpp/000_initial_test.go index b502b264be..87a9059684 100644 --- a/tests/integration/vpp/000_initial_test.go +++ b/tests/integration/vpp/000_initial_test.go @@ -24,7 +24,7 @@ func TestPing(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() - h := vppcalls.CompatibleVpeHandler(ctx.Chan) + h := vppcalls.CompatibleVpeHandler(ctx.vppBinapi) if err := h.Ping(); err != nil { t.Fatalf("control ping failed: %v", err) @@ -35,7 +35,7 @@ func TestVersion(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() - h := vppcalls.CompatibleVpeHandler(ctx.Chan) + h := vppcalls.CompatibleVpeHandler(ctx.vppBinapi) info, err := h.GetVersionInfo() if err != nil { diff --git a/tests/integration/vpp/001_telemetry_test.go b/tests/integration/vpp/001_telemetry_test.go new file mode 100644 index 0000000000..ee43af66cb --- /dev/null +++ b/tests/integration/vpp/001_telemetry_test.go @@ -0,0 +1,64 @@ +// 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 vpp + +import ( + "context" + "testing" + + _ "github.com/ligato/vpp-agent/plugins/telemetry" + "github.com/ligato/vpp-agent/plugins/telemetry/vppcalls" +) + +func TestTelemetryNodeCounters(t *testing.T) { + ctx := setupVPP(t) + defer ctx.teardownVPP() + + h := vppcalls.CompatibleTelemetryHandler(ctx.vppBinapi, ctx.vppStats) + + nodeCounters, err := h.GetNodeCounters(context.Background()) + if err != nil { + t.Fatalf("getting node counters failed: %v", err) + } + t.Logf("retrieved %d node counters", len(nodeCounters.Counters)) + if nodeCounters.Counters == nil { + t.Fatal("expected node counters, got nil") + } + if len(nodeCounters.Counters) == 0 { + t.Fatalf("expected node counters length > 0, got %v", len(nodeCounters.Counters)) + } +} + +func TestTelemetryMemory(t *testing.T) { + ctx := setupVPP(t) + defer ctx.teardownVPP() + + h := vppcalls.CompatibleTelemetryHandler(ctx.vppBinapi, ctx.vppStats) + + memStats, err := h.GetMemory(context.Background()) + if err != nil { + t.Fatalf("getting memory stats failed: %v", err) + } + t.Logf("retrieved memory stats: %+v", memStats) + if memStats.Threads == nil { + t.Fatal("expected memory stats, got nil") + } + if len(memStats.Threads) == 0 { + t.Fatalf("expected memory stats length > 0, got %v", len(memStats.Threads)) + } + if memStats.Threads[0].Total == 0 { + t.Errorf("expected memory stats - total > 0, got %v", memStats.Threads[0].Total) + } +} diff --git a/tests/integration/vpp/001_interfaces_test.go b/tests/integration/vpp/010_interfaces_test.go similarity index 92% rename from tests/integration/vpp/001_interfaces_test.go rename to tests/integration/vpp/010_interfaces_test.go index 4b4c3f8852..910067325b 100644 --- a/tests/integration/vpp/001_interfaces_test.go +++ b/tests/integration/vpp/010_interfaces_test.go @@ -28,7 +28,7 @@ func TestInterfaceDump(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() - h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.Chan, logrus.NewLogger("test")) + h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.vppBinapi, logrus.NewLogger("test")) ifIdx0, err := h.AddLoopbackInterface("loop0") if err != nil { @@ -70,7 +70,7 @@ func TestLoopbackInterface(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() - h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.Chan, logrus.NewLogger("test")) + h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.vppBinapi, logrus.NewLogger("test")) ifIdx, err := h.AddLoopbackInterface("loop1") if err != nil { @@ -99,7 +99,7 @@ func TestMemifInterface(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() - h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.Chan, logrus.NewLogger("test")) + h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.vppBinapi, logrus.NewLogger("test")) ifIdx, err := h.AddMemifInterface("memif1", &vpp_interfaces.MemifLink{ Id: 1, diff --git a/tests/integration/vpp/002_routes_test.go b/tests/integration/vpp/020_routes_test.go similarity index 94% rename from tests/integration/vpp/002_routes_test.go rename to tests/integration/vpp/020_routes_test.go index 264e3d6c8f..85160657f5 100644 --- a/tests/integration/vpp/002_routes_test.go +++ b/tests/integration/vpp/020_routes_test.go @@ -36,7 +36,7 @@ func TestRoutes(t *testing.T) { vrfIndexes.Put("vrf1-ipv4", &vrfidx.VRFMetadata{Index: 0, Protocol: vpp_l3.VrfTable_IPV4}) vrfIndexes.Put("vrf1-ipv6", &vrfidx.VRFMetadata{Index: 0, Protocol: vpp_l3.VrfTable_IPV6}) - h := l3plugin_vppcalls.CompatibleL3VppHandler(ctx.Chan, ifIndexes, vrfIndexes, logrus.NewLogger("test")) + h := l3plugin_vppcalls.CompatibleL3VppHandler(ctx.vppBinapi, ifIndexes, vrfIndexes, logrus.NewLogger("test")) routes, err := h.DumpRoutes() if err != nil { diff --git a/tests/integration/vpp/integration_test.go b/tests/integration/vpp/integration_test.go index 44bd039db0..721e2c2363 100644 --- a/tests/integration/vpp/integration_test.go +++ b/tests/integration/vpp/integration_test.go @@ -26,6 +26,7 @@ import ( "testing" "time" + "git.fd.io/govpp.git/adapter/statsclient" govppapi "git.fd.io/govpp.git/api" govppcore "git.fd.io/govpp.git/core" "github.com/mitchellh/go-ps" @@ -44,11 +45,11 @@ var ( ) const ( - vppExitTimeout = time.Second * 1 - vppBootDelay = time.Millisecond * 100 - vppTermDelay = time.Millisecond * 50 - vppConnectRetryDelay = time.Second vppConnectRetries = 3 + vppConnectRetryDelay = time.Millisecond * 500 + vppBootDelay = time.Millisecond * 200 + vppTermDelay = time.Millisecond * 50 + vppExitTimeout = time.Second * 1 ) func init() { @@ -64,14 +65,17 @@ type testCtx struct { VPP *exec.Cmd stderr, stdout *bytes.Buffer Conn *govppcore.Connection - Chan govppapi.Channel + StatsConn *govppcore.StatsConnection + vppBinapi govppapi.Channel + vppStats govppapi.StatsProvider } func setupVPP(t *testing.T) *testCtx { if os.Getenv("TRAVIS") != "" { t.Skip("skipping test for Travis") } - t.Logf("--- setupVPP ---") + t.Logf("--------------") + t.Logf("-- setupVPP --") RegisterTestingT(t) @@ -100,6 +104,9 @@ func setupVPP(t *testing.T) *testCtx { } // remove binapi files from previous run removeFile(*vppSockAddr) + if err := os.Mkdir("/run/vpp", 0755); err != nil && !os.IsExist(err) { + t.Logf("mkdir failed: %v", err) + } var stderr, stdout bytes.Buffer cmd := exec.Command(*vppPath, "-c", *vppConfig) @@ -127,7 +134,7 @@ func setupVPP(t *testing.T) *testCtx { for i := 1; i <= retries; i++ { conn, err = govppcore.Connect(adapter) if err != nil { - t.Logf("connect attempt #%d failed: %v", i, err) + t.Logf("attempt #%d failed: %v, retrying in %v", i, err, vppConnectRetryDelay) time.Sleep(vppConnectRetryDelay) continue } @@ -155,25 +162,34 @@ func setupVPP(t *testing.T) *testCtx { t.Fatalf("creating channel failed: %v", err) } + statsClient := statsclient.NewStatsClient("") + statsConn, err := govppcore.ConnectStats(statsClient) + if err != nil { + t.Fatalf("connecting to VPP stats API failed: %v", err) + } + t.Logf("---------------") return &testCtx{ - t: t, - VPP: cmd, - stderr: &stderr, - stdout: &stdout, - Conn: conn, - Chan: ch, + t: t, + VPP: cmd, + stderr: &stderr, + stdout: &stdout, + Conn: conn, + vppBinapi: ch, + vppStats: statsConn, } } func (ctx *testCtx) teardownVPP() { - ctx.t.Logf("--- teardownVPP ---") + ctx.t.Logf("-----------------") + ctx.t.Logf("-- teardownVPP --") // disconnect sometimes hangs done := make(chan struct{}) go func() { - ctx.Chan.Close() + ctx.StatsConn.Disconnect() + ctx.vppBinapi.Close() ctx.Conn.Disconnect() close(done) }() diff --git a/tests/integration/vpp_integration.sh b/tests/integration/vpp_integration.sh index 21644ed86c..57eb9555c0 100755 --- a/tests/integration/vpp_integration.sh +++ b/tests/integration/vpp_integration.sh @@ -36,7 +36,7 @@ else echo >&2 "-------------------------------------------------------------" # dump container logs - logs=$(docker logs --tail 50 "$cid") + logs=$(docker logs --tail 30 "$cid") if [[ -n "$logs" ]]; then echo >&2 "$logs" fi From badd68f204c68287f5e99c85c1afa01bcd009bca Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Fri, 19 Jul 2019 08:46:35 +0200 Subject: [PATCH 09/10] Fix integration tests - Skip some telemetry integration tests for VPP<=19.04 - Fix GetMemory in telemetry for VPP<=19.04 - Use hard-coded config for VPP - Use DOCKER_ARGS for custom arguments for docker Signed-off-by: Ondrej Fabry --- .../govppmux/vppcalls/vpp1901/vpe_vppcalls.go | 2 +- .../govppmux/vppcalls/vpp1904/vpe_vppcalls.go | 2 +- .../govppmux/vppcalls/vpp1908/vpe_vppcalls.go | 2 +- plugins/govppmux/vppcalls/vppcalls_api.go | 8 +++ .../vppcalls/vpp1901/telemetry_vppcalls.go | 5 +- .../vppcalls/vpp1904/telemetry_vppcalls.go | 7 +- .../vppcalls/vpp1908/telemetry_vppcalls.go | 3 +- plugins/telemetry/vppcalls/vppcalls_api.go | 17 +++-- tests/integration/vpp/000_initial_test.go | 16 ----- tests/integration/vpp/001_telemetry_test.go | 4 ++ tests/integration/vpp/integration_test.go | 65 ++++++++++++++----- tests/integration/vpp_integration.sh | 7 +- 12 files changed, 87 insertions(+), 51 deletions(-) diff --git a/plugins/govppmux/vppcalls/vpp1901/vpe_vppcalls.go b/plugins/govppmux/vppcalls/vpp1901/vpe_vppcalls.go index 5c41fe464b..f217d22883 100644 --- a/plugins/govppmux/vppcalls/vpp1901/vpe_vppcalls.go +++ b/plugins/govppmux/vppcalls/vpp1901/vpe_vppcalls.go @@ -31,7 +31,7 @@ func init() { msgs = append(msgs, vpe.AllMessages()...) msgs = append(msgs, memclnt.AllMessages()...) - vppcalls.Versions["vpp1901"] = vppcalls.HandlerVersion{ + vppcalls.Versions["19.01"] = vppcalls.HandlerVersion{ Msgs: msgs, New: func(ch govppapi.Channel) vppcalls.VpeVppAPI { return NewVpeHandler(ch) diff --git a/plugins/govppmux/vppcalls/vpp1904/vpe_vppcalls.go b/plugins/govppmux/vppcalls/vpp1904/vpe_vppcalls.go index 745e7bfca6..f5950165c6 100644 --- a/plugins/govppmux/vppcalls/vpp1904/vpe_vppcalls.go +++ b/plugins/govppmux/vppcalls/vpp1904/vpe_vppcalls.go @@ -31,7 +31,7 @@ func init() { msgs = append(msgs, vpe.AllMessages()...) msgs = append(msgs, memclnt.AllMessages()...) - vppcalls.Versions["vpp1904"] = vppcalls.HandlerVersion{ + vppcalls.Versions["19.04"] = vppcalls.HandlerVersion{ Msgs: msgs, New: func(ch govppapi.Channel) vppcalls.VpeVppAPI { return NewVpeHandler(ch) diff --git a/plugins/govppmux/vppcalls/vpp1908/vpe_vppcalls.go b/plugins/govppmux/vppcalls/vpp1908/vpe_vppcalls.go index d02b394662..6673d4a628 100644 --- a/plugins/govppmux/vppcalls/vpp1908/vpe_vppcalls.go +++ b/plugins/govppmux/vppcalls/vpp1908/vpe_vppcalls.go @@ -31,7 +31,7 @@ func init() { msgs = append(msgs, vpe.AllMessages()...) msgs = append(msgs, memclnt.AllMessages()...) - vppcalls.Versions["vpp1908"] = vppcalls.HandlerVersion{ + vppcalls.Versions["19.08"] = vppcalls.HandlerVersion{ Msgs: msgs, New: func(ch govppapi.Channel) vppcalls.VpeVppAPI { return NewVpeHandler(ch) diff --git a/plugins/govppmux/vppcalls/vppcalls_api.go b/plugins/govppmux/vppcalls/vppcalls_api.go index 4bf8b6de89..7c17c4b033 100644 --- a/plugins/govppmux/vppcalls/vppcalls_api.go +++ b/plugins/govppmux/vppcalls/vppcalls_api.go @@ -15,6 +15,14 @@ type VersionInfo struct { BuildDirectory string } +// Release returns version in shortened format YY.MM that describes release. +func (v VersionInfo) Release() string { + if len(v.Version) < 5 { + return "" + } + return v.Version[:5] +} + // VpeInfo contains information about VPP connection and process. type VpeInfo struct { PID uint32 diff --git a/plugins/telemetry/vppcalls/vpp1901/telemetry_vppcalls.go b/plugins/telemetry/vppcalls/vpp1901/telemetry_vppcalls.go index 67b6583874..84a522a633 100644 --- a/plugins/telemetry/vppcalls/vpp1901/telemetry_vppcalls.go +++ b/plugins/telemetry/vppcalls/vpp1901/telemetry_vppcalls.go @@ -63,14 +63,15 @@ var ( memoryRe = regexp.MustCompile( `Thread\s+(\d+)\s+(\w+).?\s+` + `virtual memory start 0x[0-9abcdef]+, size ([\dkmg\.]+), ([\dkmg\.]+) pages, page size ([\dkmg\.]+)\s+` + - `(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)+\s+` + + `(?:page information not available.*\s+)*` + + `(?:(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)+\s+)*` + `\s+total: ([\dkmgKMG\.]+), used: ([\dkmgKMG\.]+), free: ([\dkmgKMG\.]+), trimmable: ([\dkmgKMG\.]+)`, ) ) // GetMemory retrieves `show memory` info. func (h *TelemetryHandler) GetMemory(ctx context.Context) (*vppcalls.MemoryInfo, error) { - data, err := h.RunCli("show memory") + data, err := h.RunCli("show memory main-heap") if err != nil { return nil, err } diff --git a/plugins/telemetry/vppcalls/vpp1904/telemetry_vppcalls.go b/plugins/telemetry/vppcalls/vpp1904/telemetry_vppcalls.go index 5a86ae358b..a8ee54bd03 100644 --- a/plugins/telemetry/vppcalls/vpp1904/telemetry_vppcalls.go +++ b/plugins/telemetry/vppcalls/vpp1904/telemetry_vppcalls.go @@ -57,8 +57,9 @@ var ( // Regular expression to parse output from `show memory` memoryRe = regexp.MustCompile( `Thread\s+(\d+)\s+(\w+).?\s+` + - `virtual memory start 0x[0-9abcdef]+, size ([\dkmg\.]+), ([\dkmg\.]+) pages, page size ([\dkmg\.]+)\s+` + - `(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)+\s+` + + `virtual memory start 0x[0-9a-f]+, size ([\dkmg\.]+), ([\dkmg\.]+) pages, page size ([\dkmg\.]+)\s+` + + `(?:page information not available.*\s+)*` + + `(?:(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)+\s+)*` + `\s+total: ([\dkmgKMG\.]+), used: ([\dkmgKMG\.]+), free: ([\dkmgKMG\.]+), trimmable: ([\dkmgKMG\.]+)`, ) ) @@ -69,7 +70,7 @@ func (h *TelemetryHandler) GetMemory(ctx context.Context) (*vppcalls.MemoryInfo, } func (h *TelemetryHandler) getMemoryCLI(ctx context.Context) (*vppcalls.MemoryInfo, error) { - data, err := h.vpe.RunCli("show memory") + data, err := h.vpe.RunCli("show memory main-heap") if err != nil { return nil, err } diff --git a/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go b/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go index dd6cc83e4a..fb7f18c24c 100644 --- a/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go +++ b/plugins/telemetry/vppcalls/vpp1908/telemetry_vppcalls.go @@ -58,7 +58,8 @@ var ( memoryRe = regexp.MustCompile( `Thread\s+(\d+)\s+(\w+).?\s+` + `virtual memory start 0x[0-9a-f]+, size ([\dkmg\.]+), ([\dkmg\.]+) pages, page size ([\dkmg\.]+)\s+` + - `(?:(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)*|page information not available.*)\s+` + + `(?:page information not available.*\s+)*` + + `(?:(?:\s+(?:numa [\d]+|not mapped|unknown): [\dkmg\.]+ pages, [\dkmg\.]+\s+)*\s+)*` + `\s+total: ([\dkmgKMG\.]+), used: ([\dkmgKMG\.]+), free: ([\dkmgKMG\.]+), trimmable: ([\dkmgKMG\.]+)`, ) ) diff --git a/plugins/telemetry/vppcalls/vppcalls_api.go b/plugins/telemetry/vppcalls/vppcalls_api.go index 36c0f77d2f..ead710f2e7 100644 --- a/plugins/telemetry/vppcalls/vppcalls_api.go +++ b/plugins/telemetry/vppcalls/vppcalls_api.go @@ -19,6 +19,8 @@ import ( govppapi "git.fd.io/govpp.git/api" log "github.com/ligato/cn-infra/logging" + + "github.com/ligato/vpp-agent/plugins/govppmux/vppcalls" ) var Versions = map[string]HandlerVersion{} @@ -152,21 +154,22 @@ type BuffersItem struct { } func CompatibleTelemetryHandler(ch govppapi.Channel, vpp govppapi.StatsProvider) TelemetryVppAPI { - /*status, err := vpp.VPPInfo() + vpe := vppcalls.CompatibleVpeHandler(ch) + info, err := vpe.GetVersionInfo() if err != nil { - log.Warnf("retrieving VPP status failed: %v", err) + log.Warnf("retrieving VPP info failed: %v", err) return nil } - if status.Connected { - ver := status.GetReleaseVersion() + if ver := info.Release(); ver != "" { + log.Debug("telemetry checking release: ", ver) if h, ok := Versions[ver]; ok { if err := ch.CheckCompatiblity(h.Msgs...); err != nil { - log.Debugf("version %s not compatible", ver) + log.Debugf("telemetry version %s not compatible: %v", ver, err) } - log.Debug("found compatible version: ", ver) + log.Debug("telemetry found compatible release: ", ver) return h.New(ch, vpp) } - }*/ + } for ver, h := range Versions { if err := ch.CheckCompatiblity(h.Msgs...); err != nil { log.Debugf("version %s not compatible", ver) diff --git a/tests/integration/vpp/000_initial_test.go b/tests/integration/vpp/000_initial_test.go index 87a9059684..a9103eb2e2 100644 --- a/tests/integration/vpp/000_initial_test.go +++ b/tests/integration/vpp/000_initial_test.go @@ -30,19 +30,3 @@ func TestPing(t *testing.T) { t.Fatalf("control ping failed: %v", err) } } - -func TestVersion(t *testing.T) { - ctx := setupVPP(t) - defer ctx.teardownVPP() - - h := vppcalls.CompatibleVpeHandler(ctx.vppBinapi) - - info, err := h.GetVersionInfo() - if err != nil { - t.Fatalf("getting version info failed: %v", err) - } - t.Logf("version info: %+v", info) - if info.Version == "" { - t.Error("invalid version info") - } -} diff --git a/tests/integration/vpp/001_telemetry_test.go b/tests/integration/vpp/001_telemetry_test.go index ee43af66cb..237032a28e 100644 --- a/tests/integration/vpp/001_telemetry_test.go +++ b/tests/integration/vpp/001_telemetry_test.go @@ -26,6 +26,10 @@ func TestTelemetryNodeCounters(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() + if ctx.versionInfo.Release() <= "19.04" { + t.Skipf("SKIP for VPP %s", ctx.versionInfo.Release()) + } + h := vppcalls.CompatibleTelemetryHandler(ctx.vppBinapi, ctx.vppStats) nodeCounters, err := h.GetNodeCounters(context.Background()) diff --git a/tests/integration/vpp/integration_test.go b/tests/integration/vpp/integration_test.go index 721e2c2363..1eb5e2b666 100644 --- a/tests/integration/vpp/integration_test.go +++ b/tests/integration/vpp/integration_test.go @@ -34,11 +34,12 @@ import ( "github.com/sirupsen/logrus" "github.com/ligato/vpp-agent/plugins/govppmux" + "github.com/ligato/vpp-agent/plugins/govppmux/vppcalls" ) var ( - vppPath = flag.String("vpp-path", "/usr/bin/vpp", "VPP program path") - vppConfig = flag.String("vpp-config", "/etc/vpp/vpp.conf", "VPP config file") + vppPath = flag.String("vpp-path", "/usr/bin/vpp", "VPP program path") + //vppConfig = flag.String("vpp-config", "/etc/vpp/vpp.conf", "VPP config file") vppSockAddr = flag.String("vpp-sock-addr", "", "VPP binapi socket address") debug = flag.Bool("debug", false, "Turn on debug mode.") @@ -50,6 +51,28 @@ const ( vppBootDelay = time.Millisecond * 200 vppTermDelay = time.Millisecond * 50 vppExitTimeout = time.Second * 1 + + vppConf = ` + unix { + nodaemon + cli-listen /run/vpp/cli.sock + cli-no-pager + log /tmp/vpp.log + full-coredump + } + api-trace { + on + } + socksvr { + default + } + statseg { + default + per-node-counters on + } + plugins { + plugin dpdk_plugin.so { disable } + }` ) func init() { @@ -68,14 +91,14 @@ type testCtx struct { StatsConn *govppcore.StatsConnection vppBinapi govppapi.Channel vppStats govppapi.StatsProvider + vpe vppcalls.VpeVppAPI + versionInfo *vppcalls.VersionInfo } func setupVPP(t *testing.T) *testCtx { if os.Getenv("TRAVIS") != "" { t.Skip("skipping test for Travis") } - t.Logf("--------------") - t.Logf("-- setupVPP --") RegisterTestingT(t) @@ -109,13 +132,14 @@ func setupVPP(t *testing.T) *testCtx { } var stderr, stdout bytes.Buffer - cmd := exec.Command(*vppPath, "-c", *vppConfig) + + cmd := exec.Command(*vppPath, vppConf) //"-c", *vppConfig) cmd.Stderr = &stderr cmd.Stdout = &stdout // ensure that process is killed when current process exits cmd.SysProcAttr = &syscall.SysProcAttr{Pdeathsig: syscall.SIGKILL} - t.Logf("starting VPP: %v", strings.Join(cmd.Args, " ")) + t.Logf("starting VPP") if err := cmd.Start(); err != nil { t.Fatalf("starting VPP failed: %v", err) @@ -162,6 +186,16 @@ func setupVPP(t *testing.T) *testCtx { t.Fatalf("creating channel failed: %v", err) } + vpeHandler := vppcalls.CompatibleVpeHandler(ch) + versionInfo, err := vpeHandler.GetVersionInfo() + if err != nil { + t.Fatalf("getting version info failed: %v", err) + } + t.Logf("version info: %+v", versionInfo) + if versionInfo.Version == "" { + t.Error("invalid version") + } + statsClient := statsclient.NewStatsClient("") statsConn, err := govppcore.ConnectStats(statsClient) if err != nil { @@ -171,19 +205,20 @@ func setupVPP(t *testing.T) *testCtx { t.Logf("---------------") return &testCtx{ - t: t, - VPP: cmd, - stderr: &stderr, - stdout: &stdout, - Conn: conn, - vppBinapi: ch, - vppStats: statsConn, + t: t, + versionInfo: versionInfo, + vpe: vpeHandler, + VPP: cmd, + stderr: &stderr, + stdout: &stdout, + Conn: conn, + vppBinapi: ch, + vppStats: statsConn, } } func (ctx *testCtx) teardownVPP() { ctx.t.Logf("-----------------") - ctx.t.Logf("-- teardownVPP --") // disconnect sometimes hangs done := make(chan struct{}) @@ -225,6 +260,4 @@ func (ctx *testCtx) teardownVPP() { ctx.t.Fatalf("sending SIGKILL to VPP failed: %v", err) } } - - ctx.t.Logf("-------------------") } diff --git a/tests/integration/vpp_integration.sh b/tests/integration/vpp_integration.sh index 57eb9555c0..645bb8a38d 100755 --- a/tests/integration/vpp_integration.sh +++ b/tests/integration/vpp_integration.sh @@ -8,6 +8,7 @@ go test -c ./tests/integration/vpp -o ./tests/integration/vpp/vpp-integration.te cid=$(docker run -d -it \ -v $(pwd)/tests/integration/vpp/vpp-integration.test:/vpp-integration.test:ro \ --label vpp.integration.test="$*" \ + ${DOCKER_ARGS-} \ "$VPP_IMG" bash) on_exit() { @@ -24,7 +25,7 @@ echo -e " VPP Integration Test - \e[1;33m${vppver}\e[0m" echo "=============================================================" # run integration test -if docker exec -i "$cid" /vpp-integration.test -vpp-config=/etc/vpp/startup.conf $*; then +if docker exec -i "$cid" /vpp-integration.test $*; then echo >&2 "-------------------------------------------------------------" echo >&2 -e " \e[32mPASSED\e[0m (took: ${SECONDS}s)" echo >&2 "-------------------------------------------------------------" @@ -36,9 +37,9 @@ else echo >&2 "-------------------------------------------------------------" # dump container logs - logs=$(docker logs --tail 30 "$cid") + logs=$(docker logs --tail 10 "$cid") if [[ -n "$logs" ]]; then - echo >&2 "$logs" + echo >&2 -e "\e[1;30m$logs\e[0m" fi exit $res From 4d306e1185c86354b8a3f34612a8c62d9a30301a Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Fri, 19 Jul 2019 10:14:36 +0200 Subject: [PATCH 10/10] Update GoVPP Signed-off-by: Ondrej Fabry --- Gopkg.lock | 4 +-- .../adapter/socketclient/socketclient.go | 26 ++++++++++++-- .../adapter/statsclient/stat_segment.go | 4 +-- .../adapter/statsclient/statsclient.go | 35 +++++++++++-------- vendor/git.fd.io/govpp.git/api/stats.go | 14 ++++++++ 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 8915f59584..1989161da5 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,7 +3,7 @@ [[projects]] branch = "master" - digest = "1:2f8279ed810b92fb539860ddc3d0ddf120af9deb7ab91516472ac0b88b112165" + digest = "1:576638fbd32f0237520d280e7df80092293efd6780f639546bb258768f150c83" name = "git.fd.io/govpp.git" packages = [ "adapter", @@ -19,7 +19,7 @@ "examples/binapi/memclnt", ] pruneopts = "UT" - revision = "4dca07c803308611275f78b490ac0352c1052fe2" + revision = "bde85d422c7949ec32fb067e9c36320ccc47fb9e" [[projects]] branch = "master" diff --git a/vendor/git.fd.io/govpp.git/adapter/socketclient/socketclient.go b/vendor/git.fd.io/govpp.git/adapter/socketclient/socketclient.go index 96f23e6067..2144d24b37 100644 --- a/vendor/git.fd.io/govpp.git/adapter/socketclient/socketclient.go +++ b/vendor/git.fd.io/govpp.git/adapter/socketclient/socketclient.go @@ -40,6 +40,20 @@ const ( DefaultSocketName = adapter.DefaultBinapiSocket ) +const socketMissing = ` +------------------------------------------------------------ + VPP binary API socket file %s is missing! + + - is VPP running with socket for binapi enabled? + - is the correct socket name configured? + + To enable it add following section to your VPP config: + socksvr { + default + } +------------------------------------------------------------ +` + var ( // DefaultConnectTimeout is default timeout for connecting DefaultConnectTimeout = time.Second * 3 @@ -165,7 +179,13 @@ func (c *vppClient) SetMsgCallback(cb adapter.MsgCallback) { } func (c *vppClient) Connect() error { - Log.Debugf("Connecting to: %v", c.sockAddr) + // check if socket exists + if _, err := os.Stat(c.sockAddr); os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, socketMissing, c.sockAddr) + return fmt.Errorf("VPP API socket file %s does not exist", c.sockAddr) + } else if err != nil { + return fmt.Errorf("VPP API socket error: %v", err) + } if err := c.connect(c.sockAddr); err != nil { return err @@ -212,12 +232,14 @@ func (c *vppClient) Disconnect() error { func (c *vppClient) connect(sockAddr string) error { addr := &net.UnixAddr{Name: sockAddr, Net: "unix"} + Log.Debugf("Connecting to: %v", c.sockAddr) + conn, err := net.DialUnix("unix", nil, addr) if err != nil { // we try different type of socket for backwards compatbility with VPP<=19.04 if strings.Contains(err.Error(), "wrong type for socket") { addr.Net = "unixpacket" - Log.Warnf("%s, retrying connect with type unixpacket", err) + Log.Debugf("%s, retrying connect with type unixpacket", err) conn, err = net.DialUnix("unixpacket", nil, addr) } if err != nil { diff --git a/vendor/git.fd.io/govpp.git/adapter/statsclient/stat_segment.go b/vendor/git.fd.io/govpp.git/adapter/statsclient/stat_segment.go index 1875f17ab2..e8d20b01b5 100644 --- a/vendor/git.fd.io/govpp.git/adapter/statsclient/stat_segment.go +++ b/vendor/git.fd.io/govpp.git/adapter/statsclient/stat_segment.go @@ -117,11 +117,11 @@ func (c *statSegment) connect(sockName string) error { header := c.readHeader() Log.Debugf("stat segment header: %+v", header) - // older VPP (19.04) did not have version in stat segment header + // older VPP (<=19.04) did not have version in stat segment header // we try to provide fallback support by skipping it in header if header.version > MaxVersion && header.inProgress > 1 && header.epoch == 0 { h := c.readHeaderOld() - Log.Warnf("statsclient: falling back to old stat segment version (VPP 19.04): %+v", h) + Log.Debugf("statsclient: falling back to old stat segment version (VPP <=19.04): %+v", h) c.oldHeader = true } diff --git a/vendor/git.fd.io/govpp.git/adapter/statsclient/statsclient.go b/vendor/git.fd.io/govpp.git/adapter/statsclient/statsclient.go index f715a70968..6381b9fd8a 100644 --- a/vendor/git.fd.io/govpp.git/adapter/statsclient/statsclient.go +++ b/vendor/git.fd.io/govpp.git/adapter/statsclient/statsclient.go @@ -27,6 +27,25 @@ import ( "git.fd.io/govpp.git/adapter" ) +const ( + // DefaultSocketName is default VPP stats socket file path. + DefaultSocketName = adapter.DefaultStatsSocket +) + +const socketMissing = ` +------------------------------------------------------------ + VPP stats socket file %s is missing! + + - is VPP running with stats segment enabled? + - is the correct socket name configured? + + To enable it add following section to your VPP config: + statseg { + default + } +------------------------------------------------------------ +` + var ( // Debug is global variable that determines debug mode Debug = os.Getenv("DEBUG_GOVPP_STATS") != "" @@ -55,29 +74,17 @@ type StatsClient struct { // NewStatsClient returns new VPP stats API client. func NewStatsClient(sockAddr string) *StatsClient { if sockAddr == "" { - sockAddr = adapter.DefaultStatsSocket + sockAddr = DefaultSocketName } return &StatsClient{ sockAddr: sockAddr, } } -const sockNotFoundWarn = `stats socket not found at: %s ------------------------------------------------------------- - VPP stats socket is missing! - Is VPP running with stats segment enabled? - - To enable it add following section to startup config: - statseg { - default - } ------------------------------------------------------------- -` - func (c *StatsClient) Connect() error { // check if socket exists if _, err := os.Stat(c.sockAddr); os.IsNotExist(err) { - Log.Warnf(sockNotFoundWarn, c.sockAddr) + fmt.Fprintf(os.Stderr, socketMissing, c.sockAddr) return fmt.Errorf("stats socket file %s does not exist", c.sockAddr) } else if err != nil { return fmt.Errorf("stats socket error: %v", err) diff --git a/vendor/git.fd.io/govpp.git/api/stats.go b/vendor/git.fd.io/govpp.git/api/stats.go index 0bf9908291..e254eae45d 100644 --- a/vendor/git.fd.io/govpp.git/api/stats.go +++ b/vendor/git.fd.io/govpp.git/api/stats.go @@ -1,3 +1,17 @@ +// 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 api // SystemStats represents global system statistics.