From fa631462eb1cd0c0a8911dddc596dbf62735d8b3 Mon Sep 17 00:00:00 2001 From: Alexander Peretyatko Date: Fri, 17 Nov 2023 12:06:48 +0700 Subject: [PATCH 1/5] Add interface names into NSM metrics Signed-off-by: Alexander Peretyatko --- pkg/networkservice/chains/forwarder/server.go | 4 +- pkg/networkservice/stats/client.go | 9 ++- pkg/networkservice/stats/common.go | 68 ++++++++++++++++++- pkg/networkservice/stats/server.go | 9 ++- 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/pkg/networkservice/chains/forwarder/server.go b/pkg/networkservice/chains/forwarder/server.go index 0f7e1a86..151d3860 100644 --- a/pkg/networkservice/chains/forwarder/server.go +++ b/pkg/networkservice/chains/forwarder/server.go @@ -121,7 +121,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn sendfd.NewServer(), discover.NewServer(nsClient, nseClient), roundrobin.NewServer(), - stats.NewServer(ctx, opts.statsOpts...), + stats.NewServer(ctx, vppConn, opts.statsOpts...), up.NewServer(ctx, vppConn), xconnect.NewServer(vppConn), l2bridgedomain.NewServer(vppConn), @@ -151,7 +151,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn cleanup.NewClient(ctx, opts.cleanupOpts...), mechanismtranslation.NewClient(), connectioncontextkernel.NewClient(), - stats.NewClient(ctx, opts.statsOpts...), + stats.NewClient(ctx, vppConn, opts.statsOpts...), up.NewClient(ctx, vppConn), mtu.NewClient(vppConn), tag.NewClient(ctx, vppConn), diff --git a/pkg/networkservice/stats/client.go b/pkg/networkservice/stats/client.go index b4df126c..d99d4c01 100644 --- a/pkg/networkservice/stats/client.go +++ b/pkg/networkservice/stats/client.go @@ -26,6 +26,7 @@ import ( "sync" "github.com/golang/protobuf/ptypes/empty" + "go.fd.io/govpp/api" "go.fd.io/govpp/core" "google.golang.org/grpc" @@ -37,13 +38,14 @@ import ( type statsClient struct { chainCtx context.Context statsConn *core.StatsConnection + vppConn api.Connection statsSock string once sync.Once initErr error } // NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics. -func NewClient(ctx context.Context, options ...Option) networkservice.NetworkServiceClient { +func NewClient(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceClient { opts := &statsOptions{} for _, opt := range options { opt(opts) @@ -51,6 +53,7 @@ func NewClient(ctx context.Context, options ...Option) networkservice.NetworkSer return &statsClient{ chainCtx: ctx, + vppConn: vppConn, statsSock: opts.socket, } } @@ -66,7 +69,7 @@ func (s *statsClient) Request(ctx context.Context, request *networkservice.Netwo return conn, err } - retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], true) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true) return conn, nil } @@ -76,7 +79,7 @@ func (s *statsClient) Close(ctx context.Context, conn *networkservice.Connection return rv, err } - retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], true) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true) return &empty.Empty{}, nil } diff --git a/pkg/networkservice/stats/common.go b/pkg/networkservice/stats/common.go index 52ba69fd..c41a1721 100644 --- a/pkg/networkservice/stats/common.go +++ b/pkg/networkservice/stats/common.go @@ -23,6 +23,8 @@ package stats import ( "context" + "fmt" + "io" "strconv" "go.fd.io/govpp/adapter" @@ -31,21 +33,45 @@ import ( "go.fd.io/govpp/core" "github.com/networkservicemesh/api/pkg/api/networkservice" + interfaces "github.com/networkservicemesh/govpp/binapi/interface" + "github.com/networkservicemesh/govpp/binapi/interface_types" "github.com/networkservicemesh/sdk/pkg/tools/log" "github.com/pkg/errors" "github.com/networkservicemesh/sdk-vpp/pkg/tools/ifindex" ) +type interfacesInfo struct { + interfaceName string + interfaceFwdName string + interfaceType string +} + +func (i *interfacesInfo) getInterfaceDetails() string { + return combineDetails(i.interfaceType, i.interfaceName) +} + +func (i *interfacesInfo) getInterfaceFwdDetails() string { + return combineDetails(i.interfaceType, i.interfaceFwdName) +} + // Save retrieved vpp interface metrics in pathSegment -func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, segment *networkservice.PathSegment, isClient bool) { +func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, vppConn api.Connection, conn *networkservice.Connection, isClient bool) { + segment := conn.Path.PathSegments[conn.Path.Index] + swIfIndex, ok := ifindex.Load(ctx, isClient) if !ok { return } stats := new(api.InterfaceStats) - if e := statsConn.GetInterfaceStats(stats); e != nil { - log.FromContext(ctx).Errorf("getting interface stats failed:", e) + if err := statsConn.GetInterfaceStats(stats); err != nil { + log.FromContext(ctx).Errorf("getting interface stats failed:", err) + return + } + + info, err := getInterfacesInfo(ctx, vppConn, conn, swIfIndex) + if err != nil { + log.FromContext(ctx).Errorf("getting interfaces info failed:", err) return } @@ -66,6 +92,8 @@ func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, segme segment.Metrics[addName+"tx_bytes"] = strconv.FormatUint(iface.Tx.Bytes, 10) segment.Metrics[addName+"rx_packets"] = strconv.FormatUint(iface.Rx.Packets, 10) segment.Metrics[addName+"tx_packets"] = strconv.FormatUint(iface.Tx.Packets, 10) + segment.Metrics[addName+"interface"] = info.getInterfaceDetails() + segment.Metrics[addName+"interface_fwd"] = info.getInterfaceFwdDetails() segment.Metrics[addName+"drops"] = strconv.FormatUint(iface.Drops, 10) break } @@ -85,3 +113,37 @@ func initFunc(chainCtx context.Context, statsSocket string) (*core.StatsConnecti }() return statsConn, nil } + +func getInterfacesInfo(ctx context.Context, vppConn api.Connection, conn *networkservice.Connection, swIfIndex interface_types.InterfaceIndex) (*interfacesInfo, error) { + info := &interfacesInfo{ + interfaceName: conn.Mechanism.Parameters["name"], + } + + client, err := interfaces.NewServiceClient(vppConn).SwInterfaceDump(ctx, &interfaces.SwInterfaceDump{ + SwIfIndex: swIfIndex, + }) + + if err != nil { + return nil, err + } + + for { + details, err := client.Recv() + if err == io.EOF { + break + } + + if err != nil { + return nil, err + } + + info.interfaceFwdName = details.InterfaceName + info.interfaceType = details.InterfaceDevType + } + + return info, nil +} + +func combineDetails(iType, iName string) string { + return fmt.Sprintf("%s/%s", iType, iName) +} diff --git a/pkg/networkservice/stats/server.go b/pkg/networkservice/stats/server.go index a003ea92..11547bb3 100644 --- a/pkg/networkservice/stats/server.go +++ b/pkg/networkservice/stats/server.go @@ -29,19 +29,21 @@ import ( "github.com/networkservicemesh/api/pkg/api/networkservice" "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" "github.com/networkservicemesh/sdk/pkg/tools/log" + "go.fd.io/govpp/api" "go.fd.io/govpp/core" ) type statsServer struct { chainCtx context.Context statsConn *core.StatsConnection + vppConn api.Connection statsSock string once sync.Once initErr error } // NewServer provides a NetworkServiceServer chain elements that retrieves vpp interface metrics. -func NewServer(ctx context.Context, options ...Option) networkservice.NetworkServiceServer { +func NewServer(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceServer { opts := &statsOptions{} for _, opt := range options { opt(opts) @@ -49,6 +51,7 @@ func NewServer(ctx context.Context, options ...Option) networkservice.NetworkSer return &statsServer{ chainCtx: ctx, + vppConn: vppConn, statsSock: opts.socket, } } @@ -64,7 +67,7 @@ func (s *statsServer) Request(ctx context.Context, request *networkservice.Netwo return conn, err } - retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], false) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false) return conn, nil } @@ -74,7 +77,7 @@ func (s *statsServer) Close(ctx context.Context, conn *networkservice.Connection return rv, err } - retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], false) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false) return &empty.Empty{}, nil } From 4c96c608dbf162a75e9e36f2862a7546eacb607f Mon Sep 17 00:00:00 2001 From: Alexander Peretyatko Date: Fri, 24 Nov 2023 11:44:51 +0700 Subject: [PATCH 2/5] Task:768 Add interface names into NSM metrics Signed-off-by: Alexander Peretyatko --- pkg/networkservice/stats/client.go | 26 +++++++++------- pkg/networkservice/stats/common.go | 49 ++++++++++++------------------ pkg/networkservice/stats/option.go | 12 ++++++-- pkg/networkservice/stats/server.go | 26 +++++++++------- 4 files changed, 59 insertions(+), 54 deletions(-) diff --git a/pkg/networkservice/stats/client.go b/pkg/networkservice/stats/client.go index d99d4c01..cc98b435 100644 --- a/pkg/networkservice/stats/client.go +++ b/pkg/networkservice/stats/client.go @@ -36,12 +36,13 @@ import ( ) type statsClient struct { - chainCtx context.Context - statsConn *core.StatsConnection - vppConn api.Connection - statsSock string - once sync.Once - initErr error + chainCtx context.Context + statsConn *core.StatsConnection + vppConn api.Connection + statsSock string + once sync.Once + isInterfaceOnly bool + initErr error } // NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics. @@ -52,9 +53,10 @@ func NewClient(ctx context.Context, vppConn api.Connection, options ...Option) n } return &statsClient{ - chainCtx: ctx, - vppConn: vppConn, - statsSock: opts.socket, + chainCtx: ctx, + vppConn: vppConn, + statsSock: opts.socket, + isInterfaceOnly: opts.isInterfaceOnly, } } @@ -69,7 +71,8 @@ func (s *statsClient) Request(ctx context.Context, request *networkservice.Netwo return conn, err } - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true, s.isInterfaceOnly) + return conn, nil } @@ -79,7 +82,8 @@ func (s *statsClient) Close(ctx context.Context, conn *networkservice.Connection return rv, err } - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true, s.isInterfaceOnly) + return &empty.Empty{}, nil } diff --git a/pkg/networkservice/stats/common.go b/pkg/networkservice/stats/common.go index c41a1721..1eb52155 100644 --- a/pkg/networkservice/stats/common.go +++ b/pkg/networkservice/stats/common.go @@ -26,6 +26,7 @@ import ( "fmt" "io" "strconv" + "strings" "go.fd.io/govpp/adapter" "go.fd.io/govpp/adapter/statsclient" @@ -35,28 +36,22 @@ import ( "github.com/networkservicemesh/api/pkg/api/networkservice" interfaces "github.com/networkservicemesh/govpp/binapi/interface" "github.com/networkservicemesh/govpp/binapi/interface_types" - "github.com/networkservicemesh/sdk/pkg/tools/log" "github.com/pkg/errors" "github.com/networkservicemesh/sdk-vpp/pkg/tools/ifindex" ) type interfacesInfo struct { - interfaceName string - interfaceFwdName string - interfaceType string + interfaceName string + interfaceType string } func (i *interfacesInfo) getInterfaceDetails() string { - return combineDetails(i.interfaceType, i.interfaceName) -} - -func (i *interfacesInfo) getInterfaceFwdDetails() string { - return combineDetails(i.interfaceType, i.interfaceFwdName) + return fmt.Sprintf("%s/%s", i.interfaceType, i.interfaceName) } // Save retrieved vpp interface metrics in pathSegment -func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, vppConn api.Connection, conn *networkservice.Connection, isClient bool) { +func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, vppConn api.Connection, conn *networkservice.Connection, isClient, isInterfaceOnly bool) { segment := conn.Path.PathSegments[conn.Path.Index] swIfIndex, ok := ifindex.Load(ctx, isClient) @@ -65,13 +60,11 @@ func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, vppCo } stats := new(api.InterfaceStats) if err := statsConn.GetInterfaceStats(stats); err != nil { - log.FromContext(ctx).Errorf("getting interface stats failed:", err) return } - info, err := getInterfacesInfo(ctx, vppConn, conn, swIfIndex) + info, err := getInterfacesInfo(ctx, vppConn, swIfIndex) if err != nil { - log.FromContext(ctx).Errorf("getting interfaces info failed:", err) return } @@ -88,13 +81,16 @@ func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, vppCo if segment.Metrics == nil { segment.Metrics = make(map[string]string) } - segment.Metrics[addName+"rx_bytes"] = strconv.FormatUint(iface.Rx.Bytes, 10) - segment.Metrics[addName+"tx_bytes"] = strconv.FormatUint(iface.Tx.Bytes, 10) - segment.Metrics[addName+"rx_packets"] = strconv.FormatUint(iface.Rx.Packets, 10) - segment.Metrics[addName+"tx_packets"] = strconv.FormatUint(iface.Tx.Packets, 10) + + if !isInterfaceOnly { + segment.Metrics[addName+"rx_bytes"] = strconv.FormatUint(iface.Rx.Bytes, 10) + segment.Metrics[addName+"tx_bytes"] = strconv.FormatUint(iface.Tx.Bytes, 10) + segment.Metrics[addName+"rx_packets"] = strconv.FormatUint(iface.Rx.Packets, 10) + segment.Metrics[addName+"tx_packets"] = strconv.FormatUint(iface.Tx.Packets, 10) + segment.Metrics[addName+"drops"] = strconv.FormatUint(iface.Drops, 10) + } + segment.Metrics[addName+"interface"] = info.getInterfaceDetails() - segment.Metrics[addName+"interface_fwd"] = info.getInterfaceFwdDetails() - segment.Metrics[addName+"drops"] = strconv.FormatUint(iface.Drops, 10) break } } @@ -114,11 +110,7 @@ func initFunc(chainCtx context.Context, statsSocket string) (*core.StatsConnecti return statsConn, nil } -func getInterfacesInfo(ctx context.Context, vppConn api.Connection, conn *networkservice.Connection, swIfIndex interface_types.InterfaceIndex) (*interfacesInfo, error) { - info := &interfacesInfo{ - interfaceName: conn.Mechanism.Parameters["name"], - } - +func getInterfacesInfo(ctx context.Context, vppConn api.Connection, swIfIndex interface_types.InterfaceIndex) (*interfacesInfo, error) { client, err := interfaces.NewServiceClient(vppConn).SwInterfaceDump(ctx, &interfaces.SwInterfaceDump{ SwIfIndex: swIfIndex, }) @@ -127,6 +119,7 @@ func getInterfacesInfo(ctx context.Context, vppConn api.Connection, conn *networ return nil, err } + info := &interfacesInfo{} for { details, err := client.Recv() if err == io.EOF { @@ -137,13 +130,9 @@ func getInterfacesInfo(ctx context.Context, vppConn api.Connection, conn *networ return nil, err } - info.interfaceFwdName = details.InterfaceName - info.interfaceType = details.InterfaceDevType + info.interfaceName = details.InterfaceName + info.interfaceType = strings.ToUpper(details.InterfaceDevType) } return info, nil } - -func combineDetails(iType, iName string) string { - return fmt.Sprintf("%s/%s", iType, iName) -} diff --git a/pkg/networkservice/stats/option.go b/pkg/networkservice/stats/option.go index 3a667a5c..a413f880 100644 --- a/pkg/networkservice/stats/option.go +++ b/pkg/networkservice/stats/option.go @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Cisco and/or its affiliates. +// Copyright (c) 2022-2023 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // @@ -17,7 +17,8 @@ package stats type statsOptions struct { - socket string + socket string + isInterfaceOnly bool } // Option is an option pattern for stats server/client @@ -29,3 +30,10 @@ func WithSocket(socket string) Option { o.socket = socket } } + +// InterfaceOnly allows to print only interface details for server/client +func InterfaceOnly(isInterfaceOnly bool) Option { + return func(o *statsOptions) { + o.isInterfaceOnly = isInterfaceOnly + } +} diff --git a/pkg/networkservice/stats/server.go b/pkg/networkservice/stats/server.go index 11547bb3..7a273f02 100644 --- a/pkg/networkservice/stats/server.go +++ b/pkg/networkservice/stats/server.go @@ -34,12 +34,13 @@ import ( ) type statsServer struct { - chainCtx context.Context - statsConn *core.StatsConnection - vppConn api.Connection - statsSock string - once sync.Once - initErr error + chainCtx context.Context + statsConn *core.StatsConnection + vppConn api.Connection + statsSock string + once sync.Once + isInterfaceOnly bool + initErr error } // NewServer provides a NetworkServiceServer chain elements that retrieves vpp interface metrics. @@ -50,9 +51,10 @@ func NewServer(ctx context.Context, vppConn api.Connection, options ...Option) n } return &statsServer{ - chainCtx: ctx, - vppConn: vppConn, - statsSock: opts.socket, + chainCtx: ctx, + vppConn: vppConn, + statsSock: opts.socket, + isInterfaceOnly: opts.isInterfaceOnly, } } @@ -67,7 +69,8 @@ func (s *statsServer) Request(ctx context.Context, request *networkservice.Netwo return conn, err } - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false, s.isInterfaceOnly) + return conn, nil } @@ -77,7 +80,8 @@ func (s *statsServer) Close(ctx context.Context, conn *networkservice.Connection return rv, err } - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false) + retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false, s.isInterfaceOnly) + return &empty.Empty{}, nil } From d9eb482c254315df37e72959cad7cee1170d8390 Mon Sep 17 00:00:00 2001 From: Nikita Skrynnik Date: Tue, 9 Jan 2024 20:06:37 +1100 Subject: [PATCH 3/5] Add interface names into NSM metrics Signed-off-by: Nikita Skrynnik --- pkg/networkservice/stats/client.go | 71 +++------------ pkg/networkservice/stats/ifacename/client.go | 91 +++++++++++++++++++ .../stats/{ => ifacename}/common.go | 19 +--- pkg/networkservice/stats/ifacename/doc.go | 18 ++++ pkg/networkservice/stats/ifacename/option.go | 31 +++++++ pkg/networkservice/stats/ifacename/server.go | 89 ++++++++++++++++++ pkg/networkservice/stats/metrics/client.go | 88 ++++++++++++++++++ pkg/networkservice/stats/metrics/common.go | 87 ++++++++++++++++++ pkg/networkservice/stats/{ => metrics}/doc.go | 6 +- pkg/networkservice/stats/metrics/option.go | 31 +++++++ pkg/networkservice/stats/metrics/server.go | 86 ++++++++++++++++++ pkg/networkservice/stats/option.go | 12 +-- pkg/networkservice/stats/server.go | 72 +++------------ 13 files changed, 554 insertions(+), 147 deletions(-) create mode 100644 pkg/networkservice/stats/ifacename/client.go rename pkg/networkservice/stats/{ => ifacename}/common.go (78%) create mode 100644 pkg/networkservice/stats/ifacename/doc.go create mode 100644 pkg/networkservice/stats/ifacename/option.go create mode 100644 pkg/networkservice/stats/ifacename/server.go create mode 100644 pkg/networkservice/stats/metrics/client.go create mode 100644 pkg/networkservice/stats/metrics/common.go rename pkg/networkservice/stats/{ => metrics}/doc.go (81%) create mode 100644 pkg/networkservice/stats/metrics/option.go create mode 100644 pkg/networkservice/stats/metrics/server.go diff --git a/pkg/networkservice/stats/client.go b/pkg/networkservice/stats/client.go index cc98b435..6c2cb70f 100644 --- a/pkg/networkservice/stats/client.go +++ b/pkg/networkservice/stats/client.go @@ -1,6 +1,4 @@ -// Copyright (c) 2021-2023 Doc.ai and/or its affiliates. -// -// Copyright (c) 2022-2023 Cisco and/or its affiliates. +// Copyright (c) 2024 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // @@ -19,77 +17,30 @@ //go:build linux // +build linux +// Package stats provides chain elements for retrieving statistics from vpp package stats import ( "context" - "sync" - "github.com/golang/protobuf/ptypes/empty" "go.fd.io/govpp/api" - "go.fd.io/govpp/core" - "google.golang.org/grpc" "github.com/networkservicemesh/api/pkg/api/networkservice" - "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" - "github.com/networkservicemesh/sdk/pkg/tools/log" -) + "github.com/networkservicemesh/sdk/pkg/networkservice/core/chain" -type statsClient struct { - chainCtx context.Context - statsConn *core.StatsConnection - vppConn api.Connection - statsSock string - once sync.Once - isInterfaceOnly bool - initErr error -} + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/ifacename" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/metrics" +) -// NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics. +// NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics and names. func NewClient(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceClient { opts := &statsOptions{} for _, opt := range options { opt(opts) } - return &statsClient{ - chainCtx: ctx, - vppConn: vppConn, - statsSock: opts.socket, - isInterfaceOnly: opts.isInterfaceOnly, - } -} - -func (s *statsClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) { - initErr := s.init() - if initErr != nil { - log.FromContext(ctx).Errorf("%v", initErr) - } - - conn, err := next.Client(ctx).Request(ctx, request, opts...) - if err != nil || initErr != nil { - return conn, err - } - - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true, s.isInterfaceOnly) - - return conn, nil -} - -func (s *statsClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) { - rv, err := next.Client(ctx).Close(ctx, conn, opts...) - if err != nil || s.initErr != nil { - return rv, err - } - - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, true, s.isInterfaceOnly) - - return &empty.Empty{}, nil -} - -func (s *statsClient) init() error { - s.once.Do(func() { - s.statsConn, s.initErr = initFunc(s.chainCtx, s.statsSock) - }) - return s.initErr + return chain.NewNetworkServiceClient( + metrics.NewClient(ctx, metrics.WithSocket(opts.socket)), + ifacename.NewClient(ctx, vppConn, ifacename.WithSocket(opts.socket)), + ) } diff --git a/pkg/networkservice/stats/ifacename/client.go b/pkg/networkservice/stats/ifacename/client.go new file mode 100644 index 00000000..aebba1a2 --- /dev/null +++ b/pkg/networkservice/stats/ifacename/client.go @@ -0,0 +1,91 @@ +// Copyright (c) 2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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. + +//go:build linux +// +build linux + +package ifacename + +import ( + "context" + "sync" + + "github.com/golang/protobuf/ptypes/empty" + "go.fd.io/govpp/api" + "go.fd.io/govpp/core" + "google.golang.org/grpc" + + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" + "github.com/networkservicemesh/sdk/pkg/tools/log" +) + +type ifaceNamesClient struct { + chainCtx context.Context + statsConn *core.StatsConnection + vppConn api.Connection + statsSock string + once sync.Once + initErr error +} + +// NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics. +func NewClient(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceClient { + opts := &ifacenameOptions{} + for _, opt := range options { + opt(opts) + } + + return &ifaceNamesClient{ + chainCtx: ctx, + vppConn: vppConn, + statsSock: opts.Socket, + } +} + +func (s *ifaceNamesClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) { + initErr := s.init() + if initErr != nil { + log.FromContext(ctx).Errorf("%v", initErr) + } + + conn, err := next.Client(ctx).Request(ctx, request, opts...) + if err != nil || initErr != nil { + return conn, err + } + + retrieveIfaceNames(ctx, s.statsConn, s.vppConn, conn, true) + + return conn, nil +} + +func (s *ifaceNamesClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) { + rv, err := next.Client(ctx).Close(ctx, conn, opts...) + if err != nil || s.initErr != nil { + return rv, err + } + + retrieveIfaceNames(ctx, s.statsConn, s.vppConn, conn, true) + + return &empty.Empty{}, nil +} + +func (s *ifaceNamesClient) init() error { + s.once.Do(func() { + s.statsConn, s.initErr = initFunc(s.chainCtx, s.statsSock) + }) + return s.initErr +} diff --git a/pkg/networkservice/stats/common.go b/pkg/networkservice/stats/ifacename/common.go similarity index 78% rename from pkg/networkservice/stats/common.go rename to pkg/networkservice/stats/ifacename/common.go index 1eb52155..451a2697 100644 --- a/pkg/networkservice/stats/common.go +++ b/pkg/networkservice/stats/ifacename/common.go @@ -1,6 +1,4 @@ -// Copyright (c) 2021-2022 Doc.ai and/or its affiliates. -// -// Copyright (c) 2022-2023 Cisco and/or its affiliates. +// Copyright (c) 2024 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // @@ -19,13 +17,12 @@ //go:build linux // +build linux -package stats +package ifacename import ( "context" "fmt" "io" - "strconv" "strings" "go.fd.io/govpp/adapter" @@ -50,8 +47,8 @@ func (i *interfacesInfo) getInterfaceDetails() string { return fmt.Sprintf("%s/%s", i.interfaceType, i.interfaceName) } -// Save retrieved vpp interface metrics in pathSegment -func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, vppConn api.Connection, conn *networkservice.Connection, isClient, isInterfaceOnly bool) { +// Save retrieved vpp interface names in pathSegment +func retrieveIfaceNames(ctx context.Context, statsConn *core.StatsConnection, vppConn api.Connection, conn *networkservice.Connection, isClient bool) { segment := conn.Path.PathSegments[conn.Path.Index] swIfIndex, ok := ifindex.Load(ctx, isClient) @@ -82,14 +79,6 @@ func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, vppCo segment.Metrics = make(map[string]string) } - if !isInterfaceOnly { - segment.Metrics[addName+"rx_bytes"] = strconv.FormatUint(iface.Rx.Bytes, 10) - segment.Metrics[addName+"tx_bytes"] = strconv.FormatUint(iface.Tx.Bytes, 10) - segment.Metrics[addName+"rx_packets"] = strconv.FormatUint(iface.Rx.Packets, 10) - segment.Metrics[addName+"tx_packets"] = strconv.FormatUint(iface.Tx.Packets, 10) - segment.Metrics[addName+"drops"] = strconv.FormatUint(iface.Drops, 10) - } - segment.Metrics[addName+"interface"] = info.getInterfaceDetails() break } diff --git a/pkg/networkservice/stats/ifacename/doc.go b/pkg/networkservice/stats/ifacename/doc.go new file mode 100644 index 00000000..5981db7a --- /dev/null +++ b/pkg/networkservice/stats/ifacename/doc.go @@ -0,0 +1,18 @@ +// Copyright (c) 2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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 ifacename provides chain elements for retrieving names from vpp interfaces +package ifacename diff --git a/pkg/networkservice/stats/ifacename/option.go b/pkg/networkservice/stats/ifacename/option.go new file mode 100644 index 00000000..b350c392 --- /dev/null +++ b/pkg/networkservice/stats/ifacename/option.go @@ -0,0 +1,31 @@ +// Copyright (c) 2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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 ifacename + +type ifacenameOptions struct { + Socket string +} + +// Option is an option pattern for ifacename server/client +type Option func(o *ifacenameOptions) + +// WithSocket sets stats socket name +func WithSocket(socket string) Option { + return func(o *ifacenameOptions) { + o.Socket = socket + } +} diff --git a/pkg/networkservice/stats/ifacename/server.go b/pkg/networkservice/stats/ifacename/server.go new file mode 100644 index 00000000..cff3e029 --- /dev/null +++ b/pkg/networkservice/stats/ifacename/server.go @@ -0,0 +1,89 @@ +// Copyright (c) 2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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. + +//go:build linux +// +build linux + +package ifacename + +import ( + "context" + "sync" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" + "github.com/networkservicemesh/sdk/pkg/tools/log" + "go.fd.io/govpp/api" + "go.fd.io/govpp/core" +) + +type ifaceNamesServer struct { + chainCtx context.Context + statsConn *core.StatsConnection + vppConn api.Connection + statsSock string + once sync.Once + initErr error +} + +// NewServer provides a NetworkServiceServer chain elements that retrieves vpp interface metrics. +func NewServer(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceServer { + opts := &ifacenameOptions{} + for _, opt := range options { + opt(opts) + } + + return &ifaceNamesServer{ + chainCtx: ctx, + vppConn: vppConn, + statsSock: opts.Socket, + } +} + +func (s *ifaceNamesServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) { + initErr := s.init() + if initErr != nil { + log.FromContext(ctx).Errorf("%v", initErr) + } + + conn, err := next.Server(ctx).Request(ctx, request) + if err != nil || initErr != nil { + return conn, err + } + + retrieveIfaceNames(ctx, s.statsConn, s.vppConn, conn, false) + + return conn, nil +} + +func (s *ifaceNamesServer) Close(ctx context.Context, conn *networkservice.Connection) (*empty.Empty, error) { + rv, err := next.Server(ctx).Close(ctx, conn) + if err != nil || s.initErr != nil { + return rv, err + } + + retrieveIfaceNames(ctx, s.statsConn, s.vppConn, conn, false) + + return &empty.Empty{}, nil +} + +func (s *ifaceNamesServer) init() error { + s.once.Do(func() { + s.statsConn, s.initErr = initFunc(s.chainCtx, s.statsSock) + }) + return s.initErr +} diff --git a/pkg/networkservice/stats/metrics/client.go b/pkg/networkservice/stats/metrics/client.go new file mode 100644 index 00000000..7625594a --- /dev/null +++ b/pkg/networkservice/stats/metrics/client.go @@ -0,0 +1,88 @@ +// Copyright (c) 2021-2023 Doc.ai and/or its affiliates. +// +// Copyright (c) 2022-2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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. + +//go:build linux +// +build linux + +package metrics + +import ( + "context" + "sync" + + "github.com/golang/protobuf/ptypes/empty" + "go.fd.io/govpp/core" + "google.golang.org/grpc" + + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" + "github.com/networkservicemesh/sdk/pkg/tools/log" +) + +type statsClient struct { + chainCtx context.Context + statsConn *core.StatsConnection + statsSock string + once sync.Once + initErr error +} + +// NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics. +func NewClient(ctx context.Context, options ...Option) networkservice.NetworkServiceClient { + opts := &metricsOptions{} + for _, opt := range options { + opt(opts) + } + + return &statsClient{ + chainCtx: ctx, + statsSock: opts.socket, + } +} + +func (s *statsClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) { + initErr := s.init() + if initErr != nil { + log.FromContext(ctx).Errorf("%v", initErr) + } + + conn, err := next.Client(ctx).Request(ctx, request, opts...) + if err != nil || initErr != nil { + return conn, err + } + + retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], true) + return conn, nil +} + +func (s *statsClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) { + rv, err := next.Client(ctx).Close(ctx, conn, opts...) + if err != nil || s.initErr != nil { + return rv, err + } + + retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], true) + return &empty.Empty{}, nil +} + +func (s *statsClient) init() error { + s.once.Do(func() { + s.statsConn, s.initErr = initFunc(s.chainCtx, s.statsSock) + }) + return s.initErr +} diff --git a/pkg/networkservice/stats/metrics/common.go b/pkg/networkservice/stats/metrics/common.go new file mode 100644 index 00000000..2c8a84aa --- /dev/null +++ b/pkg/networkservice/stats/metrics/common.go @@ -0,0 +1,87 @@ +// Copyright (c) 2021-2022 Doc.ai and/or its affiliates. +// +// Copyright (c) 2022-2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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. + +//go:build linux +// +build linux + +package metrics + +import ( + "context" + "strconv" + + "go.fd.io/govpp/adapter" + "go.fd.io/govpp/adapter/statsclient" + "go.fd.io/govpp/api" + "go.fd.io/govpp/core" + + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/sdk/pkg/tools/log" + "github.com/pkg/errors" + + "github.com/networkservicemesh/sdk-vpp/pkg/tools/ifindex" +) + +// Save retrieved vpp interface metrics in pathSegment +func retrieveMetrics(ctx context.Context, statsConn *core.StatsConnection, segment *networkservice.PathSegment, isClient bool) { + swIfIndex, ok := ifindex.Load(ctx, isClient) + if !ok { + return + } + stats := new(api.InterfaceStats) + if e := statsConn.GetInterfaceStats(stats); e != nil { + log.FromContext(ctx).Errorf("getting interface stats failed:", e) + return + } + + addName := "server_" + if isClient { + addName = "client_" + } + for idx := range stats.Interfaces { + iface := &stats.Interfaces[idx] + if iface.InterfaceIndex != uint32(swIfIndex) { + continue + } + + if segment.Metrics == nil { + segment.Metrics = make(map[string]string) + } + segment.Metrics[addName+"rx_bytes"] = strconv.FormatUint(iface.Rx.Bytes, 10) + segment.Metrics[addName+"tx_bytes"] = strconv.FormatUint(iface.Tx.Bytes, 10) + segment.Metrics[addName+"rx_packets"] = strconv.FormatUint(iface.Rx.Packets, 10) + segment.Metrics[addName+"tx_packets"] = strconv.FormatUint(iface.Tx.Packets, 10) + segment.Metrics[addName+"drops"] = strconv.FormatUint(iface.Drops, 10) + break + } +} + +func initFunc(chainCtx context.Context, statsSocket string) (*core.StatsConnection, error) { + if statsSocket == "" { + statsSocket = adapter.DefaultStatsSocket + } + statsConn, err := core.ConnectStats(statsclient.NewStatsClient(statsSocket)) + if err != nil { + return nil, errors.Wrap(err, "failed to connect to Stats API") + } + go func() { + <-chainCtx.Done() + statsConn.Disconnect() + }() + return statsConn, nil +} diff --git a/pkg/networkservice/stats/doc.go b/pkg/networkservice/stats/metrics/doc.go similarity index 81% rename from pkg/networkservice/stats/doc.go rename to pkg/networkservice/stats/metrics/doc.go index cbde214d..5d253a84 100644 --- a/pkg/networkservice/stats/doc.go +++ b/pkg/networkservice/stats/metrics/doc.go @@ -1,5 +1,7 @@ // Copyright (c) 2021 Doc.ai and/or its affiliates. // +// Copyright (c) 2024 Cisco and/or its affiliates. +// // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,5 +16,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package stats provides chain elements for retrieving statistics from vpp -package stats +// Package metrics provides chain elements for retrieving statistics from vpp +package metrics diff --git a/pkg/networkservice/stats/metrics/option.go b/pkg/networkservice/stats/metrics/option.go new file mode 100644 index 00000000..78e1260b --- /dev/null +++ b/pkg/networkservice/stats/metrics/option.go @@ -0,0 +1,31 @@ +// Copyright (c) 2022-2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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 metrics + +type metricsOptions struct { + socket string +} + +// Option is an option pattern for metrics server/client +type Option func(o *metricsOptions) + +// WithSocket sets stats socket name +func WithSocket(socket string) Option { + return func(o *metricsOptions) { + o.socket = socket + } +} diff --git a/pkg/networkservice/stats/metrics/server.go b/pkg/networkservice/stats/metrics/server.go new file mode 100644 index 00000000..d70a3cbc --- /dev/null +++ b/pkg/networkservice/stats/metrics/server.go @@ -0,0 +1,86 @@ +// Copyright (c) 2021-2023 Doc.ai and/or its affiliates. +// +// Copyright (c) 2022-2024 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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. + +//go:build linux +// +build linux + +package metrics + +import ( + "context" + "sync" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" + "github.com/networkservicemesh/sdk/pkg/tools/log" + "go.fd.io/govpp/core" +) + +type statsServer struct { + chainCtx context.Context + statsConn *core.StatsConnection + statsSock string + once sync.Once + initErr error +} + +// NewServer provides a NetworkServiceServer chain elements that retrieves vpp interface metrics. +func NewServer(ctx context.Context, options ...Option) networkservice.NetworkServiceServer { + opts := &metricsOptions{} + for _, opt := range options { + opt(opts) + } + + return &statsServer{ + chainCtx: ctx, + statsSock: opts.socket, + } +} + +func (s *statsServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) { + initErr := s.init() + if initErr != nil { + log.FromContext(ctx).Errorf("%v", initErr) + } + + conn, err := next.Server(ctx).Request(ctx, request) + if err != nil || initErr != nil { + return conn, err + } + + retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], false) + return conn, nil +} + +func (s *statsServer) Close(ctx context.Context, conn *networkservice.Connection) (*empty.Empty, error) { + rv, err := next.Server(ctx).Close(ctx, conn) + if err != nil || s.initErr != nil { + return rv, err + } + + retrieveMetrics(ctx, s.statsConn, conn.Path.PathSegments[conn.Path.Index], false) + return &empty.Empty{}, nil +} + +func (s *statsServer) init() error { + s.once.Do(func() { + s.statsConn, s.initErr = initFunc(s.chainCtx, s.statsSock) + }) + return s.initErr +} diff --git a/pkg/networkservice/stats/option.go b/pkg/networkservice/stats/option.go index a413f880..b00b766f 100644 --- a/pkg/networkservice/stats/option.go +++ b/pkg/networkservice/stats/option.go @@ -1,4 +1,4 @@ -// Copyright (c) 2022-2023 Cisco and/or its affiliates. +// Copyright (c) 2022-2024 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // @@ -17,8 +17,7 @@ package stats type statsOptions struct { - socket string - isInterfaceOnly bool + socket string } // Option is an option pattern for stats server/client @@ -30,10 +29,3 @@ func WithSocket(socket string) Option { o.socket = socket } } - -// InterfaceOnly allows to print only interface details for server/client -func InterfaceOnly(isInterfaceOnly bool) Option { - return func(o *statsOptions) { - o.isInterfaceOnly = isInterfaceOnly - } -} diff --git a/pkg/networkservice/stats/server.go b/pkg/networkservice/stats/server.go index 7a273f02..3906ae21 100644 --- a/pkg/networkservice/stats/server.go +++ b/pkg/networkservice/stats/server.go @@ -1,6 +1,4 @@ -// Copyright (c) 2021-2023 Doc.ai and/or its affiliates. -// -// Copyright (c) 2022-2023 Cisco and/or its affiliates. +// Copyright (c) 2024 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // @@ -23,71 +21,25 @@ package stats import ( "context" - "sync" - "github.com/golang/protobuf/ptypes/empty" - "github.com/networkservicemesh/api/pkg/api/networkservice" - "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" - "github.com/networkservicemesh/sdk/pkg/tools/log" "go.fd.io/govpp/api" - "go.fd.io/govpp/core" -) -type statsServer struct { - chainCtx context.Context - statsConn *core.StatsConnection - vppConn api.Connection - statsSock string - once sync.Once - isInterfaceOnly bool - initErr error -} + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/sdk/pkg/networkservice/core/chain" -// NewServer provides a NetworkServiceServer chain elements that retrieves vpp interface metrics. + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/ifacename" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/metrics" +) + +// NewServer provides NetworkServiceServer chain elements that retrieve vpp interface metrics and names. func NewServer(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceServer { opts := &statsOptions{} for _, opt := range options { opt(opts) } - return &statsServer{ - chainCtx: ctx, - vppConn: vppConn, - statsSock: opts.socket, - isInterfaceOnly: opts.isInterfaceOnly, - } -} - -func (s *statsServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) { - initErr := s.init() - if initErr != nil { - log.FromContext(ctx).Errorf("%v", initErr) - } - - conn, err := next.Server(ctx).Request(ctx, request) - if err != nil || initErr != nil { - return conn, err - } - - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false, s.isInterfaceOnly) - - return conn, nil -} - -func (s *statsServer) Close(ctx context.Context, conn *networkservice.Connection) (*empty.Empty, error) { - rv, err := next.Server(ctx).Close(ctx, conn) - if err != nil || s.initErr != nil { - return rv, err - } - - retrieveMetrics(ctx, s.statsConn, s.vppConn, conn, false, s.isInterfaceOnly) - - return &empty.Empty{}, nil -} - -func (s *statsServer) init() error { - s.once.Do(func() { - s.statsConn, s.initErr = initFunc(s.chainCtx, s.statsSock) - }) - return s.initErr + return chain.NewNetworkServiceServer( + metrics.NewServer(ctx, metrics.WithSocket(opts.socket)), + ifacename.NewServer(ctx, vppConn, ifacename.WithSocket(opts.socket)), + ) } From 9d7d5f181360d883e9eb85b4028ee6983608cd52 Mon Sep 17 00:00:00 2001 From: Nikita Skrynnik Date: Tue, 9 Jan 2024 20:10:11 +1100 Subject: [PATCH 4/5] cleanup Signed-off-by: Nikita Skrynnik --- pkg/networkservice/stats/option.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/networkservice/stats/option.go b/pkg/networkservice/stats/option.go index b00b766f..3a667a5c 100644 --- a/pkg/networkservice/stats/option.go +++ b/pkg/networkservice/stats/option.go @@ -1,4 +1,4 @@ -// Copyright (c) 2022-2024 Cisco and/or its affiliates. +// Copyright (c) 2022 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // From 50d47be56bbb1c8ebd4809474e83dafd398ec2e8 Mon Sep 17 00:00:00 2001 From: Nikita Skrynnik Date: Wed, 10 Jan 2024 16:21:43 +1100 Subject: [PATCH 5/5] change folder names Signed-off-by: Nikita Skrynnik --- pkg/networkservice/chains/forwarder/options.go | 10 +++++----- pkg/networkservice/chains/forwarder/server.go | 8 +++++--- pkg/networkservice/{stats => metrics}/client.go | 12 ++++++------ .../{stats => metrics}/ifacename/client.go | 0 .../{stats => metrics}/ifacename/common.go | 0 .../{stats => metrics}/ifacename/doc.go | 0 .../{stats => metrics}/ifacename/option.go | 0 .../{stats => metrics}/ifacename/server.go | 0 pkg/networkservice/{stats => }/metrics/option.go | 0 pkg/networkservice/{stats => metrics}/server.go | 12 ++++++------ .../{stats/metrics => metrics/stats}/client.go | 4 ++-- .../{stats/metrics => metrics/stats}/common.go | 2 +- .../{stats/metrics => metrics/stats}/doc.go | 4 ++-- pkg/networkservice/{ => metrics}/stats/option.go | 2 +- .../{stats/metrics => metrics/stats}/server.go | 6 +++--- 15 files changed, 31 insertions(+), 29 deletions(-) rename pkg/networkservice/{stats => metrics}/client.go (79%) rename pkg/networkservice/{stats => metrics}/ifacename/client.go (100%) rename pkg/networkservice/{stats => metrics}/ifacename/common.go (100%) rename pkg/networkservice/{stats => metrics}/ifacename/doc.go (100%) rename pkg/networkservice/{stats => metrics}/ifacename/option.go (100%) rename pkg/networkservice/{stats => metrics}/ifacename/server.go (100%) rename pkg/networkservice/{stats => }/metrics/option.go (100%) rename pkg/networkservice/{stats => metrics}/server.go (80%) rename pkg/networkservice/{stats/metrics => metrics/stats}/client.go (98%) rename pkg/networkservice/{stats/metrics => metrics/stats}/common.go (99%) rename pkg/networkservice/{stats/metrics => metrics/stats}/doc.go (87%) rename pkg/networkservice/{ => metrics}/stats/option.go (94%) rename pkg/networkservice/{stats/metrics => metrics/stats}/server.go (96%) diff --git a/pkg/networkservice/chains/forwarder/options.go b/pkg/networkservice/chains/forwarder/options.go index 797cfef8..f907e4b7 100644 --- a/pkg/networkservice/chains/forwarder/options.go +++ b/pkg/networkservice/chains/forwarder/options.go @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Cisco and/or its affiliates. +// Copyright (c) 2022-2024 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // @@ -29,7 +29,7 @@ import ( "github.com/networkservicemesh/sdk/pkg/networkservice/common/cleanup" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vxlan" - "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/metrics" ) type forwarderOptions struct { @@ -40,7 +40,7 @@ type forwarderOptions struct { dialTimeout time.Duration domain2Device map[string]string mechanismPrioriyList []string - statsOpts []stats.Option + statsOpts []metrics.Option cleanupOpts []cleanup.Option vxlanOpts []vxlan.Option dialOpts []grpc.DialOption @@ -105,8 +105,8 @@ func WithMechanismPriority(priorityList []string) Option { } } -// WithStatsOptions sets stats options -func WithStatsOptions(opts ...stats.Option) Option { +// WithStatsOptions sets metrics options +func WithStatsOptions(opts ...metrics.Option) Option { return func(o *forwarderOptions) { o.statsOpts = opts } diff --git a/pkg/networkservice/chains/forwarder/server.go b/pkg/networkservice/chains/forwarder/server.go index 151d3860..c2ffc832 100644 --- a/pkg/networkservice/chains/forwarder/server.go +++ b/pkg/networkservice/chains/forwarder/server.go @@ -2,6 +2,8 @@ // // Copyright (c) 2021-2023 Nordix Foundation. // +// Copyright (c) 2024 Cisco and/or its affiliates. +// // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -66,9 +68,9 @@ import ( "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vlan" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vxlan" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/wireguard" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/metrics" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/nsmonitor" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/pinhole" - "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/tag" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/up" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/xconnect" @@ -121,7 +123,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn sendfd.NewServer(), discover.NewServer(nsClient, nseClient), roundrobin.NewServer(), - stats.NewServer(ctx, vppConn, opts.statsOpts...), + metrics.NewServer(ctx, vppConn, opts.statsOpts...), up.NewServer(ctx, vppConn), xconnect.NewServer(vppConn), l2bridgedomain.NewServer(vppConn), @@ -151,7 +153,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn cleanup.NewClient(ctx, opts.cleanupOpts...), mechanismtranslation.NewClient(), connectioncontextkernel.NewClient(), - stats.NewClient(ctx, vppConn, opts.statsOpts...), + metrics.NewClient(ctx, vppConn, opts.statsOpts...), up.NewClient(ctx, vppConn), mtu.NewClient(vppConn), tag.NewClient(ctx, vppConn), diff --git a/pkg/networkservice/stats/client.go b/pkg/networkservice/metrics/client.go similarity index 79% rename from pkg/networkservice/stats/client.go rename to pkg/networkservice/metrics/client.go index 6c2cb70f..cd86af37 100644 --- a/pkg/networkservice/stats/client.go +++ b/pkg/networkservice/metrics/client.go @@ -17,8 +17,8 @@ //go:build linux // +build linux -// Package stats provides chain elements for retrieving statistics from vpp -package stats +// Package metrics provides chain elements for retrieving metrics from vpp +package metrics import ( "context" @@ -28,19 +28,19 @@ import ( "github.com/networkservicemesh/api/pkg/api/networkservice" "github.com/networkservicemesh/sdk/pkg/networkservice/core/chain" - "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/ifacename" - "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/metrics" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/metrics/ifacename" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/metrics/stats" ) // NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics and names. func NewClient(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceClient { - opts := &statsOptions{} + opts := &metricsOptions{} for _, opt := range options { opt(opts) } return chain.NewNetworkServiceClient( - metrics.NewClient(ctx, metrics.WithSocket(opts.socket)), + stats.NewClient(ctx, stats.WithSocket(opts.socket)), ifacename.NewClient(ctx, vppConn, ifacename.WithSocket(opts.socket)), ) } diff --git a/pkg/networkservice/stats/ifacename/client.go b/pkg/networkservice/metrics/ifacename/client.go similarity index 100% rename from pkg/networkservice/stats/ifacename/client.go rename to pkg/networkservice/metrics/ifacename/client.go diff --git a/pkg/networkservice/stats/ifacename/common.go b/pkg/networkservice/metrics/ifacename/common.go similarity index 100% rename from pkg/networkservice/stats/ifacename/common.go rename to pkg/networkservice/metrics/ifacename/common.go diff --git a/pkg/networkservice/stats/ifacename/doc.go b/pkg/networkservice/metrics/ifacename/doc.go similarity index 100% rename from pkg/networkservice/stats/ifacename/doc.go rename to pkg/networkservice/metrics/ifacename/doc.go diff --git a/pkg/networkservice/stats/ifacename/option.go b/pkg/networkservice/metrics/ifacename/option.go similarity index 100% rename from pkg/networkservice/stats/ifacename/option.go rename to pkg/networkservice/metrics/ifacename/option.go diff --git a/pkg/networkservice/stats/ifacename/server.go b/pkg/networkservice/metrics/ifacename/server.go similarity index 100% rename from pkg/networkservice/stats/ifacename/server.go rename to pkg/networkservice/metrics/ifacename/server.go diff --git a/pkg/networkservice/stats/metrics/option.go b/pkg/networkservice/metrics/option.go similarity index 100% rename from pkg/networkservice/stats/metrics/option.go rename to pkg/networkservice/metrics/option.go diff --git a/pkg/networkservice/stats/server.go b/pkg/networkservice/metrics/server.go similarity index 80% rename from pkg/networkservice/stats/server.go rename to pkg/networkservice/metrics/server.go index 3906ae21..40ba0272 100644 --- a/pkg/networkservice/stats/server.go +++ b/pkg/networkservice/metrics/server.go @@ -17,7 +17,7 @@ //go:build linux // +build linux -package stats +package metrics import ( "context" @@ -27,19 +27,19 @@ import ( "github.com/networkservicemesh/api/pkg/api/networkservice" "github.com/networkservicemesh/sdk/pkg/networkservice/core/chain" - "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/ifacename" - "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/stats/metrics" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/metrics/ifacename" + "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/metrics/stats" ) -// NewServer provides NetworkServiceServer chain elements that retrieve vpp interface metrics and names. +// NewServer provides NetworkServiceServer chain elements that retrieve vpp interface statistics and names. func NewServer(ctx context.Context, vppConn api.Connection, options ...Option) networkservice.NetworkServiceServer { - opts := &statsOptions{} + opts := &metricsOptions{} for _, opt := range options { opt(opts) } return chain.NewNetworkServiceServer( - metrics.NewServer(ctx, metrics.WithSocket(opts.socket)), + stats.NewServer(ctx, stats.WithSocket(opts.socket)), ifacename.NewServer(ctx, vppConn, ifacename.WithSocket(opts.socket)), ) } diff --git a/pkg/networkservice/stats/metrics/client.go b/pkg/networkservice/metrics/stats/client.go similarity index 98% rename from pkg/networkservice/stats/metrics/client.go rename to pkg/networkservice/metrics/stats/client.go index 7625594a..6c82f7e4 100644 --- a/pkg/networkservice/stats/metrics/client.go +++ b/pkg/networkservice/metrics/stats/client.go @@ -19,7 +19,7 @@ //go:build linux // +build linux -package metrics +package stats import ( "context" @@ -44,7 +44,7 @@ type statsClient struct { // NewClient provides a NetworkServiceClient chain elements that retrieves vpp interface metrics. func NewClient(ctx context.Context, options ...Option) networkservice.NetworkServiceClient { - opts := &metricsOptions{} + opts := &statsOptions{} for _, opt := range options { opt(opts) } diff --git a/pkg/networkservice/stats/metrics/common.go b/pkg/networkservice/metrics/stats/common.go similarity index 99% rename from pkg/networkservice/stats/metrics/common.go rename to pkg/networkservice/metrics/stats/common.go index 2c8a84aa..60d613d1 100644 --- a/pkg/networkservice/stats/metrics/common.go +++ b/pkg/networkservice/metrics/stats/common.go @@ -19,7 +19,7 @@ //go:build linux // +build linux -package metrics +package stats import ( "context" diff --git a/pkg/networkservice/stats/metrics/doc.go b/pkg/networkservice/metrics/stats/doc.go similarity index 87% rename from pkg/networkservice/stats/metrics/doc.go rename to pkg/networkservice/metrics/stats/doc.go index 5d253a84..87162ab5 100644 --- a/pkg/networkservice/stats/metrics/doc.go +++ b/pkg/networkservice/metrics/stats/doc.go @@ -16,5 +16,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package metrics provides chain elements for retrieving statistics from vpp -package metrics +// Package stats provides chain elements for retrieving statistics from vpp interfaces +package stats diff --git a/pkg/networkservice/stats/option.go b/pkg/networkservice/metrics/stats/option.go similarity index 94% rename from pkg/networkservice/stats/option.go rename to pkg/networkservice/metrics/stats/option.go index 3a667a5c..b00b766f 100644 --- a/pkg/networkservice/stats/option.go +++ b/pkg/networkservice/metrics/stats/option.go @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Cisco and/or its affiliates. +// Copyright (c) 2022-2024 Cisco and/or its affiliates. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/pkg/networkservice/stats/metrics/server.go b/pkg/networkservice/metrics/stats/server.go similarity index 96% rename from pkg/networkservice/stats/metrics/server.go rename to pkg/networkservice/metrics/stats/server.go index d70a3cbc..24209b5e 100644 --- a/pkg/networkservice/stats/metrics/server.go +++ b/pkg/networkservice/metrics/stats/server.go @@ -19,7 +19,7 @@ //go:build linux // +build linux -package metrics +package stats import ( "context" @@ -40,9 +40,9 @@ type statsServer struct { initErr error } -// NewServer provides a NetworkServiceServer chain elements that retrieves vpp interface metrics. +// NewServer provides a NetworkServiceServer chain elements that retrieves vpp interface statistics. func NewServer(ctx context.Context, options ...Option) networkservice.NetworkServiceServer { - opts := &metricsOptions{} + opts := &statsOptions{} for _, opt := range options { opt(opts) }