Skip to content

Commit

Permalink
feat(ct-metrics): process metrics within IFDEF
Browse files Browse the repository at this point in the history
  • Loading branch information
SRodi committed Dec 9, 2024
1 parent 31bbf53 commit 1031c3f
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ data:
metricsIntervalDuration: {{ .Values.metricsIntervalDuration }}
enableTelemetry: {{ .Values.enableTelemetry }}
enablePodLevel: {{ .Values.enablePodLevel }}
enableConntrackMetrics: {{ .Values.enableConntrackMetrics }}
remoteContext: {{ .Values.remoteContext }}
enableAnnotations: {{ .Values.enableAnnotations }}
bypassLookupIPOfInterest: {{ .Values.bypassLookupIPOfInterest }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ data:
metricsIntervalDuration: {{ .Values.metricsIntervalDuration }}
enableTelemetry: {{ .Values.enableTelemetry }}
enablePodLevel: {{ .Values.enablePodLevel }}
enableConntrackMetrics: {{ .Values.enableConntrackMetrics }}
remoteContext: {{ .Values.remoteContext }}
enableAnnotations: {{ .Values.enableAnnotations }}
bypassLookupIPOfInterest: {{ .Values.bypassLookupIPOfInterest }}
Expand Down
1 change: 1 addition & 0 deletions deploy/legacy/manifests/controller/helm/retina/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ image:
# Overrides the image tag whose default is the chart appVersion.
tag: "v0.0.2"

enableConntrackMetrics: false
enablePodLevel: false
remoteContext: false
enableAnnotations: false
Expand Down
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type Config struct {
EnableTelemetry bool `yaml:"enableTelemetry"`
EnableRetinaEndpoint bool `yaml:"enableRetinaEndpoint"`
EnablePodLevel bool `yaml:"enablePodLevel"`
EnableConntrackMetrics bool `yaml:"enableConntrackMetrics"`
RemoteContext bool `yaml:"remoteContext"`
EnableAnnotations bool `yaml:"enableAnnotations"`
BypassLookupIPOfInterest bool `yaml:"bypassLookupIPOfInterest"`
Expand Down
92 changes: 62 additions & 30 deletions pkg/plugin/conntrack/_cprog/conntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "compiler.h"
#include "bpf_helpers.h"
#include "conntrack.h"
#include "dynamic.h"

struct tcpmetadata {
__u32 seq; // TCP sequence number
Expand Down Expand Up @@ -147,18 +148,24 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
new_value.flags_seen_tx_dir = p->flags;
new_value.is_direction_unknown = false;
new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
new_value.conntrack_metadata.packets_forward_count = 1;
new_value.conntrack_metadata.bytes_forward_count = p->bytes;
// The initial SYN is captured. Set the traffic direction of the connection.
// This is important for the case where the SYN packet is not captured
// and the connection is created with unknown direction.
new_value.conntrack_metadata.traffic_direction = new_value.traffic_direction;
bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);

#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
new_value.conntrack_metadata.packets_forward_count = 1;
new_value.conntrack_metadata.bytes_forward_count = p->bytes;
// The initial SYN is captured. Set the traffic direction of the connection.
// This is important for the case where the SYN packet is not captured
// and the connection is created with unknown direction.
new_value.conntrack_metadata.traffic_direction = new_value.traffic_direction;
// Update initial conntrack metadata for the connection.
__builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
#endif
#endif // CONNTRACK_METRICS

// Update packet
p->is_reply = false;
p->traffic_direction = new_value.traffic_direction;
// Update initial conntrack metadata for the connection.
__builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
return true;
}

Expand All @@ -180,14 +187,19 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
new_value.flags_seen_tx_dir = p->flags;
new_value.last_report_tx_dir = now;
new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
new_value.conntrack_metadata.packets_forward_count = 1;
new_value.conntrack_metadata.bytes_forward_count = p->bytes;
bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
new_value.conntrack_metadata.packets_forward_count = 1;
new_value.conntrack_metadata.bytes_forward_count = p->bytes;
// Update packet's conntrack metadata.
__builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
#endif
#endif // CONNTRACK_METRICS

// Update packet
p->is_reply = false;
p->traffic_direction = new_value.traffic_direction;
// Update packet's conntrack metadata.
__builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
return true;
}

Expand Down Expand Up @@ -226,19 +238,31 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
p->is_reply = true;
new_value.flags_seen_rx_dir = p->flags;
new_value.last_report_rx_dir = now;
new_value.conntrack_metadata.bytes_reply_count = p->bytes;
new_value.conntrack_metadata.packets_reply_count = 1;
#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
new_value.conntrack_metadata.bytes_reply_count = p->bytes;
new_value.conntrack_metadata.packets_reply_count = 1;
#endif
#endif // CONNTRACK_METRICS
bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY);
} else { // Otherwise, the packet is considered as a packet in the send direction.
p->is_reply = false;
new_value.flags_seen_tx_dir = p->flags;
new_value.last_report_tx_dir = now;
new_value.conntrack_metadata.bytes_forward_count = p->bytes;
new_value.conntrack_metadata.packets_forward_count = 1;
#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
new_value.conntrack_metadata.bytes_forward_count = p->bytes;
new_value.conntrack_metadata.packets_forward_count = 1;
#endif
#endif // CONNTRACK_METRICS
bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
}
// Update packet's conntrack metadata.
__builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
// Update packet's conntrack metadata.
__builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
#endif
#endif // CONNTRACK_METRICS
return true;
}

Expand Down Expand Up @@ -357,11 +381,15 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
// Update the packet accordingly.
p->is_reply = false;
p->traffic_direction = entry->traffic_direction;
// Update packet count and bytes count on conntrack entry.
WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
// Update packet's conntract metadata.
__builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
// Update packet count and bytes count on conntrack entry.
WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
// Update packet's conntract metadata.
__builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
#endif
#endif // CONNTRACK_METRICS
return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
}

Expand All @@ -377,11 +405,15 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
// Update the packet accordingly.
p->is_reply = true;
p->traffic_direction = entry->traffic_direction;
// Update packet count and bytes count on conntrack entry.
WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
// Update packet's conntract metadata.
__builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
// Update packet count and bytes count on conntrack entry.
WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
// Update packet's conntract metadata.
__builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
#endif
#endif // CONNTRACK_METRICS
return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &reverse_key);
}

Expand Down
1 change: 1 addition & 0 deletions pkg/plugin/conntrack/_cprog/dynamic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define CONNTRACK_METRICS 0
21 changes: 21 additions & 0 deletions pkg/plugin/conntrack/conntrack_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ package conntrack

import (
"context"
"fmt"
"path"
"runtime"
"time"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/rlimit"
"github.com/microsoft/retina/internal/ktime"
"github.com/microsoft/retina/pkg/loader"
"github.com/microsoft/retina/pkg/log"
plugincommon "github.com/microsoft/retina/pkg/plugin/common"
_ "github.com/microsoft/retina/pkg/plugin/conntrack/_cprog" // nolint // This is needed so cprog is included when vendoring
Expand Down Expand Up @@ -66,6 +70,23 @@ func New() (*Conntrack, error) {
return ct, nil
}

// Generate dynamic header file for conntrack eBPF program.
func GenerateDynamic(ctx context.Context, conntrackMetrics int) error {
// Get absolute path to this file during runtime.
_, filename, _, ok := runtime.Caller(0)
if !ok {
return errors.New("unable to get absolute path for conntrack file")
}
dir := path.Dir(filename)
dynamicHeaderPath := fmt.Sprintf("%s/%s/%s", dir, bpfSourceDir, dynamicHeaderFileName)
st := fmt.Sprintf("#define CONNTRACK_METRICS %d\n", conntrackMetrics)
err := loader.WriteFile(ctx, dynamicHeaderPath, st)
if err != nil {
return errors.Wrap(err, "failed to write conntrack dynamic header")
}
return nil
}

// Run starts the Conntrack garbage collection loop.
func (ct *Conntrack) Run(ctx context.Context) error {
ticker := time.NewTicker(ct.gcFrequency)
Expand Down
5 changes: 4 additions & 1 deletion pkg/plugin/conntrack/types_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
)

const (
defaultGCFrequency = 15 * time.Second
defaultGCFrequency = 15 * time.Second
bpfSourceDir = "_cprog"
bpfSourceFileName = "conntrack.c"
dynamicHeaderFileName = "dynamic.h"
)

type Conntrack struct {
Expand Down
1 change: 1 addition & 0 deletions pkg/plugin/packetparser/_cprog/dynamic.h
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#define BYPASS_LOOKUP_IP_OF_INTEREST 0
#define DATA_AGGREGATION_LEVEL 0
#define CONNTRACK_METRICS 0
12 changes: 8 additions & 4 deletions pkg/plugin/packetparser/_cprog/packetparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,14 @@ static void parse(struct __sk_buff *skb, __u8 obs)
return;
}

// Initialize the conntrack metadata.
struct conntrackmetadata conntrack_metadata;
__builtin_memset(&conntrack_metadata, 0, sizeof(conntrack_metadata));
p.conntrack_metadata = conntrack_metadata;
#ifdef CONNTRACK_METRICS
#if CONNTRACK_METRICS == 1
// Initialize conntrack metadata in packet struct.
struct conntrackmetadata conntrack_metadata;
__builtin_memset(&conntrack_metadata, 0, sizeof(conntrack_metadata));
p.conntrack_metadata = conntrack_metadata;
#endif
#endif // CONNTRACK_METRICS

// Process the packet in ct
bool report __attribute__((unused));
Expand Down
15 changes: 14 additions & 1 deletion pkg/plugin/packetparser/packetparser_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/microsoft/retina/pkg/log"
"github.com/microsoft/retina/pkg/metrics"
plugincommon "github.com/microsoft/retina/pkg/plugin/common"
"github.com/microsoft/retina/pkg/plugin/conntrack"
_ "github.com/microsoft/retina/pkg/plugin/lib/_amd64" // nolint
_ "github.com/microsoft/retina/pkg/plugin/lib/_arm64" // nolint
_ "github.com/microsoft/retina/pkg/plugin/lib/common/libbpf/_include/asm" // nolint
Expand Down Expand Up @@ -82,8 +83,20 @@ func (p *packetParser) Generate(ctx context.Context) error {
p.l.Info("bypassing lookup IP of interest")
bypassLookupIPOfInterest = 1
}
conntrackMetrics := 0
// Check if packetparser has Conntrack metrics enabled.
if p.cfg.EnableConntrackMetrics {
p.l.Info("conntrack metrics enabled")
conntrackMetrics = 1
// Generate dynamic header for conntrack.
err := conntrack.GenerateDynamic(ctx, conntrackMetrics)
if err != nil {
return errors.Wrap(err, "failed to generate dynamic header for conntrack")
}
p.l.Info("Conntrack header generated")
}
p.l.Info("data aggregation level", zap.String("level", p.cfg.DataAggregationLevel.String()))
st := fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n#define DATA_AGGREGATION_LEVEL %d\n", bypassLookupIPOfInterest, p.cfg.DataAggregationLevel)
st := fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n#define DATA_AGGREGATION_LEVEL %d\n#define CONNTRACK_METRICS %d\n", bypassLookupIPOfInterest, p.cfg.DataAggregationLevel, conntrackMetrics)
err := loader.WriteFile(ctx, dynamicHeaderPath, st)
if err != nil {
return errors.Wrap(err, "failed to write dynamic header")
Expand Down

0 comments on commit 1031c3f

Please sign in to comment.