-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ct-metrics): BPF implementation (#1102)
# Description BPF implementation for connection tracking metrics. This is the data-plane work mentioned in this comment #1057 (comment) Summary - feature flag enableConntrackMetrics - counters incremented within IFDEF in BPF - counters: packets forward/reply + bytes forward/reply - conntrack metadata includes metrics and is added to packets struct - add/update unit tests for conntrack_linux and packetparser_linux ## Related Issue #806 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/contributing). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. 1. `enableConntrackMetrics=false` ```sh # bpftool map dump id 994 -j | jq -r .[0] { "key": [ ... ], "value": [ ... ], "formatted": { "key": { ... }, "value": { ... "conntrack_metadata": { "bytes_forward_count": 0, "bytes_reply_count": 0, "packets_forward_count": 0, "packets_reply_count": 0 } } } } ``` 2. `enableConntrackMetrics=true` ```sh # bpftool map dump id 1019 -j | jq -r .[0] { "key": [ ... ], "value": [ ... ], "formatted": { "key": { ... }, "value": { ..., "conntrack_metadata": { "bytes_forward_count": 13440, "bytes_reply_count": 56335, "packets_forward_count": 56, "packets_reply_count": 43 } } } } ``` At userland level I provisionally added a debug statement, just for this test, in `packetparser_linux.go` (without IP and proto translation) ```sh ❯ k logs -n kube-system retina-agent-chvdh | head -n 10 | grep metadata Defaulted container "retina" out of: retina, init-retina (init) ts=2024-12-13T10:37:08.881Z level=debug caller=packetparser/packetparser_linux.go:577 msg="Conntrack metadata" SrcIp=788657162 DstIp=2499867658 SrcPort=19117 DstPort=23313 Proto=6 PacketsForwardCount=73 PacketsReplyCount=83 BytesForwardCount=16068 BytesReplyCount=6936 ts=2024-12-13T10:37:08.881Z level=debug caller=packetparser/packetparser_linux.go:577 msg="Conntrack metadata" SrcIp=788657162 DstIp=2499867658 SrcPort=19117 DstPort=23313 Proto=6 PacketsForwardCount=73 PacketsReplyCount=82 BytesForwardCount=16068 BytesReplyCount=6870 ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project.
- Loading branch information
Showing
16 changed files
with
345 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// Place holder header file that will be replaced by the actual header file during runtime | ||
// DO NOT DELETE |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package conntrack | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"path" | ||
"runtime" | ||
"testing" | ||
) | ||
|
||
func TestBuildDynamicHeaderPath(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
expectedPath string | ||
}{ | ||
{ | ||
name: "ExpectedPath", | ||
expectedPath: fmt.Sprintf("%s/%s/%s", path.Dir(getCurrentFilePath(t)), bpfSourceDir, dynamicHeaderFileName), | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
actualPath := BuildDynamicHeaderPath() | ||
if actualPath != tt.expectedPath { | ||
t.Errorf("unexpected dynamic header path: got %q, want %q", actualPath, tt.expectedPath) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestGenerateDynamic(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
conntrackMetrics int | ||
expectedContents string | ||
}{ | ||
{ | ||
name: "ConntrackMetricsEnabled", | ||
conntrackMetrics: 1, | ||
expectedContents: "#define ENABLE_CONNTRACK_METRICS 1\n", | ||
}, | ||
{ | ||
name: "ConntrackMetricsDisabled", | ||
conntrackMetrics: 0, | ||
expectedContents: "#define ENABLE_CONNTRACK_METRICS 0\n", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
// Create a temporary directory | ||
tempDir, err := os.MkdirTemp("", "conntrack_test") | ||
if err != nil { | ||
t.Fatalf("failed to create temp directory: %v", err) | ||
} | ||
// Clean up the temporary directory after the test completes | ||
defer os.RemoveAll(tempDir) | ||
|
||
// Override the dynamicHeaderPath to use the temporary directory | ||
dynamicHeaderPath := path.Join(tempDir, dynamicHeaderFileName) | ||
|
||
// Call the GenerateDynamic function and check if it returns an error. | ||
ctx := context.Background() | ||
if err = GenerateDynamic(ctx, dynamicHeaderPath, tt.conntrackMetrics); err != nil { | ||
t.Fatalf("failed to generate dynamic header: %v", err) | ||
} | ||
|
||
// Verify that the dynamic header file was created in the expected location and contains the expected contents. | ||
if _, err = os.Stat(dynamicHeaderPath); os.IsNotExist(err) { | ||
t.Fatalf("dynamic header file does not exist: %v", err) | ||
} | ||
|
||
actualContents, err := os.ReadFile(dynamicHeaderPath) | ||
if err != nil { | ||
t.Fatalf("failed to read dynamic header file: %v", err) | ||
} | ||
if string(actualContents) != tt.expectedContents { | ||
t.Errorf("unexpected dynamic header file contents: got %q, want %q", string(actualContents), tt.expectedContents) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func getCurrentFilePath(t *testing.T) string { | ||
_, filename, _, ok := runtime.Caller(1) | ||
if !ok { | ||
t.Fatal("failed to determine test file path") | ||
} | ||
return filename | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.