Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Prep
run: |
sudo cp -r /home/runner/work/l3afd/l3afd /root
sudo git clone https://github.com/l3af-project/l3af-arch.git /root/l3af-arch
sudo git clone -b output-all-metrics https://github.com/Atul-source/l3af-arch.git /root/l3af-arch
sudo bash /root/l3af-arch/dev_environment/e2e_test/prep_env.sh
sudo bash /root/l3af-arch/dev_environment/setup_linux_dev_env.sh --ci-build
hm=$(hostname)
Expand Down
28 changes: 18 additions & 10 deletions bpfprogs/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -713,7 +712,7 @@ func (b *BPF) GetBPFMap(mapName string) (*BPFMap, error) {
}

// Add eBPF map into BPFMaps list
func (b *BPF) AddMetricsBPFMap(mapName, aggregator string, key, samplesLength int) error {
func (b *BPF) AddMetricsBPFMap(mapName, key, aggregator string, samplesLength int) error {
var tmpMetricsBPFMap MetricsBPFMap
bpfMap, err := b.GetBPFMap(mapName)
if err != nil {
Expand All @@ -725,8 +724,8 @@ func (b *BPF) AddMetricsBPFMap(mapName, aggregator string, key, samplesLength in
tmpMetricsBPFMap.Aggregator = aggregator
tmpMetricsBPFMap.Values = ring.New(samplesLength)

log.Info().Msgf("added Metrics map ID %d Name %s Type %s Key %d Aggregator %s", tmpMetricsBPFMap.MapID, tmpMetricsBPFMap.Name, tmpMetricsBPFMap.Type, tmpMetricsBPFMap.Key, tmpMetricsBPFMap.Aggregator)
map_key := mapName + strconv.Itoa(key) + aggregator
log.Info().Msgf("added Metrics map ID %d Name %s Type %s Key %s Aggregator %s", tmpMetricsBPFMap.MapID, tmpMetricsBPFMap.Name, tmpMetricsBPFMap.Type, tmpMetricsBPFMap.Key, tmpMetricsBPFMap.Aggregator)
map_key := mapName + key + aggregator
b.MetricsBpfMaps[map_key] = &tmpMetricsBPFMap

return nil
Expand All @@ -735,17 +734,26 @@ func (b *BPF) AddMetricsBPFMap(mapName, aggregator string, key, samplesLength in
// This method to fetch values from bpf maps and publish to metrics
func (b *BPF) MonitorMaps(ifaceName string, intervals int) error {
for _, element := range b.Program.MonitorMaps {
log.Debug().Msgf("monitor maps element %s key %d aggregator %s", element.Name, element.Key, element.Aggregator)
mapKey := element.Name + strconv.Itoa(element.Key) + element.Aggregator
log.Debug().Msgf("monitor maps element %s key %s aggregator %s", element.Name, element.Key, element.Aggregator)
mapKey := element.Name + element.Key + element.Aggregator
_, ok := b.MetricsBpfMaps[mapKey]
if !ok {
if err := b.AddMetricsBPFMap(element.Name, element.Aggregator, element.Key, intervals); err != nil {
return fmt.Errorf("unable to fetch map %s key %d aggregator %s : %w", element.Name, element.Key, element.Aggregator, err)
if err := b.AddMetricsBPFMap(element.Name, element.Key, element.Aggregator, intervals); err != nil {
return fmt.Errorf("unable to fetch map %s key %s aggregator %s : %w", element.Name, element.Key, element.Aggregator, err)
}
}
bpfMap := b.MetricsBpfMaps[mapKey]
MetricName := element.Name + "_" + strconv.Itoa(element.Key) + "_" + element.Aggregator
stats.SetValue(bpfMap.GetValue(), stats.BPFMonitorMap, b.Program.Name, MetricName, ifaceName)
if element.Key != "*" {
stats.SetValue(bpfMap.GetValue(element.KeyType), stats.BPFMonitorMap, b.Program.Name, element.Name, ifaceName, bpfMap.Aggregator, element.Key)
} else {
allKV, err := bpfMap.GetAllKeysAndValues(element.KeyType)
if err != nil {
return fmt.Errorf("GetAllKeysAndValues failed with error %w", err)
}
for _, kv := range allKV {
stats.SetValue(kv.Value, stats.BPFMonitorMap, b.Program.Name, element.Name, ifaceName, bpfMap.Aggregator, kv.Key)
}
}
}
return nil
}
Expand Down
79 changes: 74 additions & 5 deletions bpfprogs/bpfmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"errors"
"fmt"
"math"
"net/netip"
"strconv"
"unsafe"

"github.com/cilium/ebpf"
Expand All @@ -24,10 +26,15 @@ type BPFMap struct {
BPFProg *BPF `json:"-"`
}

type MetricKeyValue struct {
Key string
Value float64
}

// This stores Metrics map details.
type MetricsBPFMap struct {
BPFMap
Key int
Key string
Values *ring.Ring
Aggregator string
LastValue float64
Expand Down Expand Up @@ -87,7 +94,7 @@ func (b *BPFMap) Update(key, value int) error {
// max-rate - this calculates delta requests / sec and stores absolute value.
// avg - stores the values in the circular queue
// We can implement more aggregate function as needed.
func (b *MetricsBPFMap) GetValue() float64 {
func (b *MetricsBPFMap) GetValue(keyType string) float64 {
ebpfMap, err := ebpf.NewMapFromID(b.MapID)
if err != nil {
// We have observed in smaller configuration VM's, if we restart BPF's
Expand All @@ -107,10 +114,31 @@ func (b *MetricsBPFMap) GetValue() float64 {
}
}
defer ebpfMap.Close()

var value int64
if err = ebpfMap.Lookup(unsafe.Pointer(&b.Key), unsafe.Pointer(&value)); err != nil {
log.Warn().Err(err).Msgf("GetValue Lookup failed : Name %s ID %d", b.Name, b.MapID)
switch keyType {
case "int":
var k int
k, err = strconv.Atoi(b.Key)
if err != nil {
log.Warn().Err(err).Msgf("conversion of key to int failed : Name %s ID %d", b.Name, b.MapID)
return 0
}
if err = ebpfMap.Lookup(unsafe.Pointer(&k), unsafe.Pointer(&value)); err != nil {
log.Warn().Err(err).Msgf("GetValue Lookup failed : Name %s ID %d", b.Name, b.MapID)
return 0
}
case "ipv4":
ip, err := netip.ParseAddr(b.Key)
if err != nil {
log.Warn().Err(err).Msgf("Parsing of IP address failed %v : Name %s ID %d", b.Key, b.Name, b.MapID)
return 0
}
if err = ebpfMap.Lookup(ip, unsafe.Pointer(&value)); err != nil {
log.Warn().Err(err).Msgf("GetValue Lookup failed : Name %s ID %d", b.Name, b.MapID)
return 0
}
default:
log.Warn().Msgf("unsupported keytype %s", keyType)
return 0
}

Expand All @@ -133,6 +161,47 @@ func (b *MetricsBPFMap) GetValue() float64 {
return retVal
}

func (b *MetricsBPFMap) GetAllKeysAndValues(KeyType string) ([]MetricKeyValue, error) {
var result []MetricKeyValue
ebpfMap, err := ebpf.NewMapFromID(b.MapID)
if err != nil {
return nil, fmt.Errorf("access new map from ID failed %w", err)
}
defer ebpfMap.Close()
if KeyType == "ipv4" {
var key netip.Addr
var val int64
iter := ebpfMap.Iterate()
for iter.Next(&key, &val) {
result = append(result, MetricKeyValue{
Key: key.String(),
Value: float64(val),
})
}
if iter.Err() != nil {
return nil, iter.Err()
}
} else {
if KeyType == "int" {
var key int
var val int64
iter := ebpfMap.Iterate()
for iter.Next(unsafe.Pointer(&key), unsafe.Pointer(&val)) {
result = append(result, MetricKeyValue{
Key: strconv.Itoa(key),
Value: float64(val),
})
}
if iter.Err() != nil {
return nil, iter.Err()
}
} else {
return nil, fmt.Errorf("unsupported keytype")
}
}
return result, nil
}

// This method finds the max value in the circular list
func (b *MetricsBPFMap) MaxValue() float64 {
tmp := b.Values
Expand Down
4 changes: 2 additions & 2 deletions bpfprogs/bpfmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestMetricsBPFMapMaxValue(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
metricsMap := &MetricsBPFMap{
Values: TestValues,
Key: 0,
Key: "0",
Aggregator: tt.args.aggregator,
LastValue: 0,
}
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestMetricsBPFMapAvgValue(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
metricsMap := &MetricsBPFMap{
Values: TestValues,
Key: 0,
Key: "0",
Aggregator: tt.args.aggregator,
LastValue: 0,
}
Expand Down
5 changes: 3 additions & 2 deletions models/l3afd.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ type BPFProgram struct {
// L3afDNFMetricsMap defines BPF map
type L3afDNFMetricsMap struct {
Name string `json:"name"` // BPF map name
Key int `json:"key"` // Index of the bpf map
Key string `json:"key"` // Index of the bpf map
Aggregator string `json:"aggregator"` // Aggregation function names
KeyType string `json:"key_type"` // Type of key
}

// KeyValue defines struct for key and value
Expand Down Expand Up @@ -122,7 +123,7 @@ type MetaColl struct {

type MetaMetricsBPFMap struct {
MapName string
Key int
Key string
Values []float64
Aggregator string
LastValue float64
Expand Down
2 changes: 1 addition & 1 deletion restart/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ func SetMetrics(t models.L3AFALLHOSTDATA) {
getValueofLabel("version", f.Labels), getValueofLabel("direction", f.Labels), getValueofLabel("interface_name", f.Labels))
} else if len(getValueofLabel("map_name", f.Labels)) > 0 {
stats.SetValue(f.Value, getGaugeVecByMetricName(f.MetricName), getValueofLabel("ebpf_program", f.Labels),
getValueofLabel("map_name", f.Labels), getValueofLabel("interface_name", f.Labels))
getValueofLabel("map_name", f.Labels), getValueofLabel("interface_name", f.Labels), getValueofLabel("aggregator", f.Labels), getValueofLabel("key", f.Labels))
} else {
stats.Set(f.Value, getGaugeVecByMetricName(f.MetricName), getValueofLabel("ebpf_program", f.Labels),
getValueofLabel("direction", f.Labels), getValueofLabel("interface_name", f.Labels))
Expand Down
12 changes: 8 additions & 4 deletions stats/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package stats

import (
"errors"
"fmt"
"net"
"net/http"

Expand Down Expand Up @@ -108,7 +109,7 @@ func SetupMetrics(hostname, daemonName, metricsAddr string) {
Name: "BPFMonitorMap",
Help: "This value indicates BPF program monitor counters",
},
[]string{"host", "ebpf_program", "map_name", "interface_name"},
[]string{"host", "ebpf_program", "map_name", "interface_name", "key", "aggregator"},
)

if err := prometheus.Register(bpfMonitorMapVec); err != nil {
Expand Down Expand Up @@ -197,7 +198,7 @@ func Set(value float64, gaugeVec *prometheus.GaugeVec, ebpfProgram, direction, i
}

// Set gaugevec metrics value with given mapName and other fields
func SetValue(value float64, gaugeVec *prometheus.GaugeVec, ebpfProgram, mapName, ifaceName string) {
func SetValue(value float64, gaugeVec *prometheus.GaugeVec, ebpfProgram, mapName, ifaceName, aggregator, key string) {

if gaugeVec == nil {
log.Warn().Msg("Metrics: gauge vector is nil and needs to be initialized before SetValue")
Expand All @@ -208,11 +209,14 @@ func SetValue(value float64, gaugeVec *prometheus.GaugeVec, ebpfProgram, mapName
"ebpf_program": ebpfProgram,
"map_name": mapName,
"interface_name": ifaceName,
"key": key,
"aggregator": aggregator,
}),
)
if err != nil {
log.Warn().Msgf("Metrics: unable to fetch gauge with fields: ebpf_program: %s, map_name: %s, interface_name: %s",
ebpfProgram, mapName, ifaceName)
log.Warn().Msgf("Metrics: unable to fetch gauge with fields: ebpf_program: %s, map_name: %s, interface_name: %s , key %s , aggregator %s",
ebpfProgram, mapName, ifaceName, key, aggregator)
fmt.Println(err)
return
}
bpfGauge.Set(value)
Expand Down
Loading