aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/nsh/nsh.c
diff options
context:
space:
mode:
authorPaul Vinciguerra <pvinci@vinciconsulting.com>2019-08-06 22:02:45 -0400
committerDamjan Marion <dmarion@me.com>2019-09-23 12:40:39 +0000
commit4db04c021de72491a191b799d70976741c4b997b (patch)
tree40adb89c3e0a9701e28c56a849393a2083829755 /src/plugins/nsh/nsh.c
parent1be8581c6f7c6b45393019fccee69ca53622dee5 (diff)
vppapigen: remove python2 support
vppapigen has been running under python3 for months. Remove the python2 conditional code. In case of an error, explicitly log and return non-0. Type: refactor Change-Id: I20a73e0f2cb875aab6441959a85a35e88c9f8250 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com> (cherry picked from commit 2cd3cc8a605a062c7900dbcc3fad53d04723c298)
Diffstat (limited to 'src/plugins/nsh/nsh.c')
0 files changed, 0 insertions, 0 deletions
80'>180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
// Copyright (c) 2018 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.

// +build !windows,!darwin,!novpp,!beyond18.10

package vppapiclient

/*
#cgo CFLAGS: -DPNG_DEBUG=1
#cgo LDFLAGS: -lvppapiclient

#include "stat_client_wrapper.h"
*/
import "C"

import (
	"fmt"
	"os"
	"unsafe"

	"git.fd.io/govpp.git/adapter"
)

// global VPP stats API client, library vppapiclient only supports
// single connection at a time
var globalStatClient *statClient

// statClient is the default implementation of StatsAPI.
type statClient struct {
	socketName string
}

// NewStatClient returns new VPP stats API client.
func NewStatClient(socketName string) adapter.StatsAPI {
	return &statClient{
		socketName: socketName,
	}
}

func (c *statClient) Connect() error {
	if globalStatClient != nil {
		return fmt.Errorf("already connected to stats API, disconnect first")
	}

	var sockName string
	if c.socketName == "" {
		sockName = adapter.DefaultStatsSocket
	} else {
		sockName = c.socketName
	}

	if _, err := os.Stat(sockName); err != nil {
		if os.IsNotExist(err) {
			return fmt.Errorf("stats socket file %q does not exists, ensure that VPP is running with `statseg { ... }` section in config", sockName)
		}
		return fmt.Errorf("stats socket file error: %v", err)
	}

	rc := C.govpp_stat_connect(C.CString(sockName))
	if rc != 0 {
		return fmt.Errorf("connecting to VPP stats API failed (rc=%v)", rc)
	}

	globalStatClient = c
	return nil
}

func (c *statClient) Disconnect() error {
	globalStatClient = nil

	C.govpp_stat_disconnect()
	return nil
}

func (c *statClient) ListStats(patterns ...string) (indexes []adapter.StatIdentifier, err error) {
	dir := C.govpp_stat_segment_ls(convertStringSlice(patterns))
	if dir == nil {
		return nil, adapter.ErrStatsDataBusy
	}
	defer C.govpp_stat_segment_vec_free(unsafe.Pointer(dir))

	l := C.govpp_stat_segment_vec_len(unsafe.Pointer(dir))
	for i := 0; i < int(l); i++ {
		nameChar := C.govpp_stat_segment_dir_index_to_name(dir, C.uint32_t(i))
		indexes = append(indexes, adapter.StatIdentifier{
			Name:  []byte(C.GoString(nameChar)),
			Index: uint32(i),
		})
		C.free(unsafe.Pointer(nameChar))
	}

	return indexes, nil
}

func (c *statClient) DumpStats(patterns ...string) (stats []adapter.StatEntry, err error) {
	dir := C.govpp_stat_segment_ls(convertStringSlice(patterns))
	if dir == nil {
		return nil, adapter.ErrStatsDataBusy
	}
	defer C.govpp_stat_segment_vec_free(unsafe.Pointer(dir))

	dump := C.govpp_stat_segment_dump(dir)
	if dump == nil {
		return nil, adapter.ErrStatsDataBusy
	}
	defer C.govpp_stat_segment_data_free(dump)

	l := C.govpp_stat_segment_vec_len(unsafe.Pointer(dump))
	for i := 0; i < int(l); i++ {
		v := C.govpp_stat_segment_dump_index(dump, C.int(i))
		nameChar := v.name
		name := C.GoString(nameChar)
		typ := adapter.StatType(C.govpp_stat_segment_data_type(&v))

		stat := adapter.StatEntry{
			StatIdentifier: adapter.StatIdentifier{
				Name:  []byte(name),
				Index: uint32(i),
			},
			Type: typ,
		}

		switch typ {
		case adapter.ScalarIndex:
			stat.Data = adapter.ScalarStat(C.govpp_stat_segment_data_get_scalar_value(&v))

		case adapter.ErrorIndex:
			stat.Data = adapter.ErrorStat([]adapter.Counter{adapter.Counter(C.govpp_stat_segment_data_get_error_value(&v))})

		case adapter.SimpleCounterVector:
			length := int(C.govpp_stat_segment_vec_len(unsafe.Pointer(C.govpp_stat_segment_data_get_simple_counter(&v))))
			vector := make([][]adapter.Counter, length)
			for k := 0; k < length; k++ {
				for j := 0; j < int(C.govpp_stat_segment_vec_len(unsafe.Pointer(C.govpp_stat_segment_data_get_simple_counter_index(&v, C.int(k))))); j++ {
					vector[k] = append(vector[k], adapter.Counter(C.govpp_stat_segment_data_get_simple_counter_index_value(&v, C.int(k), C.int(j))))
				}
			}
			stat.Data = adapter.SimpleCounterStat(vector)

		case adapter.CombinedCounterVector:
			length := int(C.govpp_stat_segment_vec_len(unsafe.Pointer(C.govpp_stat_segment_data_get_combined_counter(&v))))
			vector := make([][]adapter.CombinedCounter, length)
			for k := 0; k < length; k++ {
				for j := 0; j < int(C.govpp_stat_segment_vec_len(unsafe.Pointer(C.govpp_stat_segment_data_get_combined_counter_index(&v, C.int(k))))); j++ {
					vector[k] = append(vector[k], [2]uint64{
						uint64(C.govpp_stat_segment_data_get_combined_counter_index_packets(&v, C.int(k), C.int(j))),
						uint64(C.govpp_stat_segment_data_get_combined_counter_index_bytes(&v, C.int(k), C.int(j))),
					})
				}
			}
			stat.Data = adapter.CombinedCounterStat(vector)

		case adapter.NameVector:
			length := int(C.govpp_stat_segment_vec_len(unsafe.Pointer(C.govpp_stat_segment_data_get_name_vector(&v))))
			var vector []adapter.Name
			for k := 0; k < length; k++ {
				s := C.govpp_stat_segment_data_get_name_vector_index(&v, C.int(k))
				var name adapter.Name
				if s != nil {
					name = adapter.Name(C.GoString(s))
				}
				vector = append(vector, name)
			}
			stat.Data = adapter.NameStat(vector)

		default:
			fmt.Fprintf(os.Stderr, "invalid stat type: %v (%v)\n", typ, name)
			continue

		}

		stats = append(stats, stat)
	}

	return stats, nil
}

func (c *statClient) PrepareDir(_ ...string) (*adapter.StatDir, error) {
	return nil, adapter.ErrNotImplemented
}

func (c *statClient) PrepareDirOnIndex(_ ...uint32) (*adapter.StatDir, error) {
	return nil, adapter.ErrNotImplemented
}

func (c *statClient) UpdateDir(_ *adapter.StatDir) error {
	return adapter.ErrNotImplemented
}

func convertStringSlice(strs []string) **C.uint8_t {
	var arr **C.uint8_t
	for _, str := range strs {
		arr = C.govpp_stat_segment_string_vector(arr, C.CString(str))
	}
	return arr
}