88 lines
2.5 KiB
Go
88 lines
2.5 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package vpp
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"go.fd.io/govpp/adapter"
|
|
"go.fd.io/govpp/binapi/ip"
|
|
"go.fd.io/govpp/binapi/ip_types"
|
|
)
|
|
|
|
// routeToStatPath is the VPP stats-segment path exposing the per-FIB-entry
|
|
// "route-to" combined counter (packets + bytes), indexed by the load-
|
|
// balance index of each FIB entry. See lbm_to_counters in
|
|
// src/vnet/dpo/load_balance.c.
|
|
const routeToStatPath = "/net/route/to"
|
|
|
|
// fibStatsIndex returns the FIB entry's stats_index (load_balance index)
|
|
// for the host prefix of addr. Uses exact=0 (longest-match) so a covering
|
|
// route is returned if there is no host-prefix entry — note this means
|
|
// two maglev entities sharing a covering route will report identical
|
|
// /net/route/to counters.
|
|
func fibStatsIndex(ch *loggedChannel, addr net.IP) (uint32, error) {
|
|
var prefix ip_types.Prefix
|
|
if v4 := addr.To4(); v4 != nil {
|
|
prefix.Address.Af = ip_types.ADDRESS_IP4
|
|
copy(prefix.Address.Un.XXX_UnionData[:4], v4)
|
|
prefix.Len = 32
|
|
} else {
|
|
prefix.Address.Af = ip_types.ADDRESS_IP6
|
|
copy(prefix.Address.Un.XXX_UnionData[:], addr.To16())
|
|
prefix.Len = 128
|
|
}
|
|
req := &ip.IPRouteLookup{
|
|
TableID: 0,
|
|
Exact: 0,
|
|
Prefix: prefix,
|
|
}
|
|
reply := &ip.IPRouteLookupReply{}
|
|
if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
|
|
return 0, fmt.Errorf("ip_route_lookup: %w", err)
|
|
}
|
|
if reply.Retval != 0 {
|
|
return 0, fmt.Errorf("ip_route_lookup: retval=%d", reply.Retval)
|
|
}
|
|
return reply.Route.StatsIndex, nil
|
|
}
|
|
|
|
// findCombinedCounter returns the CombinedCounterStat matching name, or
|
|
// nil if not found or the wrong type.
|
|
func findCombinedCounter(entries []adapter.StatEntry, name string) adapter.CombinedCounterStat {
|
|
for _, e := range entries {
|
|
if string(e.Name) != name {
|
|
continue
|
|
}
|
|
if s, ok := e.Data.(adapter.CombinedCounterStat); ok {
|
|
return s
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// reduceCombinedCounter sums the (packets, bytes) CombinedCounter across
|
|
// workers at column i, tolerating short per-worker vectors.
|
|
func reduceCombinedCounter(s adapter.CombinedCounterStat, i int) (pkts, byts uint64) {
|
|
for _, thread := range s {
|
|
if i >= 0 && i < len(thread) {
|
|
pkts += thread[i][0]
|
|
byts += thread[i][1]
|
|
}
|
|
}
|
|
return pkts, byts
|
|
}
|
|
|
|
// vipKeyToIP extracts the VIP address from a vipKey's CIDR string. The
|
|
// second return is the prefix length. Used by the scrape path to feed
|
|
// a VIP prefix into fibStatsIndex.
|
|
func vipKeyToIP(k vipKey) (net.IP, int, error) {
|
|
ip, ipnet, err := net.ParseCIDR(k.prefix)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
ones, _ := ipnet.Mask.Size()
|
|
return ip, ones, nil
|
|
}
|