-
Notifications
You must be signed in to change notification settings - Fork 707
Support for eBPF based port forwarding #3067
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,13 @@ | |
"errors" | ||
"os" | ||
"reflect" | ||
"strconv" | ||
"sync" | ||
"syscall" | ||
"time" | ||
|
||
"github.com/balajiv113/trackport/pkg/trackapi" | ||
"github.com/balajiv113/trackport/pkg/tracker" | ||
"github.com/elastic/go-libaudit/v2" | ||
"github.com/elastic/go-libaudit/v2/auparse" | ||
"github.com/lima-vm/lima/pkg/guestagent/api" | ||
|
@@ -138,11 +141,11 @@ | |
} | ||
} | ||
|
||
type eventState struct { | ||
ports []*api.IPPort | ||
} | ||
|
||
func comparePorts(old, neww []*api.IPPort) (added, removed []*api.IPPort) { | ||
mRaw := make(map[string]*api.IPPort, len(old)) | ||
mStillExist := make(map[string]bool, len(old)) | ||
|
||
|
@@ -169,7 +172,7 @@ | |
return | ||
} | ||
|
||
func (a *agent) collectEvent(ctx context.Context, st eventState) (*api.Event, eventState) { | ||
var ( | ||
ev = &api.Event{} | ||
err error | ||
|
@@ -186,7 +189,7 @@ | |
return ev, newSt | ||
} | ||
|
||
func isEventEmpty(ev *api.Event) bool { | ||
empty := &api.Event{} | ||
copied := ev | ||
copied.Time = nil | ||
|
@@ -195,24 +198,26 @@ | |
|
||
func (a *agent) Events(ctx context.Context, ch chan *api.Event) { | ||
defer close(ch) | ||
tickerCh, tickerClose := a.newTicker() | ||
defer tickerClose() | ||
var st eventState | ||
for { | ||
var ev *api.Event | ||
ev, st = a.collectEvent(ctx, st) | ||
if !isEventEmpty(ev) { | ||
ch <- ev | ||
} | ||
select { | ||
case <-ctx.Done(): | ||
return | ||
case _, ok := <-tickerCh: | ||
if !ok { | ||
return | ||
} | ||
logrus.Debug("tick!") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To simplify https://github.com/balajiv113/trackport/tree/main/pkg/internal/bpftracker , can we keep the existing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes yes will do that. I wanted to purely use eBPF because fentry and fexit will wait for the eBPF logic to complete. So I wanted to verify if the UDP forwarding issue is resolved in that case |
||
|
||
portMonitor := tracker.NewRunner(tracker.WithBpf(), tracker.WithNft()) | ||
|
||
callbackFn := func(event *trackapi.PortEvent) { | ||
port := make([]*api.IPPort, 1) | ||
ev := &api.Event{Time: timestamppb.Now()} | ||
atoi, _ := strconv.Atoi(event.Port) | ||
if event.Action == trackapi.OPEN { | ||
port[0] = &api.IPPort{Ip: event.Ip.String(), Port: int32(atoi), Protocol: trackapi.ProtocolToString(event.Protocol)} | ||
|
||
ev.LocalPortsAdded = port | ||
} else { | ||
port[0] = &api.IPPort{Ip: event.Ip.String(), Port: int32(atoi), Protocol: trackapi.ProtocolToString(event.Protocol)} | ||
|
||
ev.LocalPortsRemoved = port | ||
} | ||
ch <- ev | ||
} | ||
errCh := portMonitor.Run(ctx, callbackFn) | ||
err := <-errCh | ||
if err != nil { | ||
return | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The binary blobs such as https://github.com/balajiv113/trackport/blob/main/pkg/internal/bpftracker/bpf_arm64_bpfel.o have to be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those are actually needed it will be embedded in go logics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we compile them from source in the Lima repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes yes that's the ultimate goal after it's all good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will clean up stuff and verify it again and see if all still holds good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be even fine to just execute the
bpftrace
command to stimulate the ticker, if thego build
stuff is too complicatedlima/cmd/lima-guestagent/daemon_linux.go
Lines 57 to 63 in 7459f45
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do that as a temp solution.
If we use ebpf then i wanted to avoid parsing the proc file again. As this will add further delay only in forwarding. But identifying ip and ports just by using bpftrace its hard. we need multiple variations. That's where using celium helped to write down our logics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds like it is not really a generic solution and requires custom rules for each container runtime.
I wonder how much latency parsing the proc file is adding; maybe it is not noticeable?
As long as we manage to close the port forwarding before a new container can reopen the port, we should be fine. I guess we can do some stress-testing to see how it works.