-
Notifications
You must be signed in to change notification settings - Fork 376
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
Add bidirectional packet capture #6882
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Aryan Bakliwal <[email protected]>
Signed-off-by: Aryan Bakliwal <[email protected]>
@hangyan please let me know what you think about this |
…antrea-io#6877) Bumps the golang-org-x group with 1 update: [golang.org/x/net](https://github.com/golang/net). Updates `golang.org/x/net` from 0.32.0 to 0.33.0 - [Commits](golang/net@v0.32.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-org-x ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…oup (antrea-io#6880) Bumps the ginkgo group with 1 update: [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo). Updates `github.com/onsi/ginkgo/v2` from 2.22.0 to 2.22.1 - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](onsi/ginkgo@v2.22.0...v2.22.1) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ginkgo ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: Aryan Bakliwal <[email protected]>
Hey @hangyan @antoninbas, I made the changes in the bpf code according to the one generated by tcpdump. When I try to test the bidirectional packet capture, it fails with this log
Could you please take a look and help me identify what might be going wrong? Also, golangci-lint is giving me this error even though I have changed the
|
this error was reported by golangci on windows, we have a |
Signed-off-by: Aryan Bakliwal <[email protected]>
I’ve added the Please let me know if any adjustments are needed or if there's anything else I should update or add. Captured packets |
@@ -134,18 +122,96 @@ func compilePacketFilter(packetSpec *crdv1alpha1.Packet, srcIP, dstIP net.IP) [] | |||
} | |||
} | |||
|
|||
// source ip |
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.
In the future we may also support tcp flags and other layer4 configs, if that happens, we should consider make the current code structure more modularized, or it would be extremely hard to extend this function . This won't be easy but i suggest to review this part and see if we can do better.
not sure if we can separate the ip section and ports section apart, call sub functions to calculate their instruments size and sums up.
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'll try my best to improve the code structure and explore separating the IP and port sections as suggested
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.
@hangyan I am thinking of refactoring the code as you suggested by modularizing the logic for IP and port comparison by adding helper functions for taking decisions based on direction and other parameters.
I’ve created a function compareIP
to handle the conditional logic for building the instruction to compare IP address depending on the direction and which IP address is loaded for comparison (the boolean isSrc
tells if I have loaded the source or destination IP address)
func compareIP(direction crdv1alpha1.CaptureDirection, skipTrue, skipFalse uint8, isSrc bool, srcAddrVal, dstAddrVal uint32) bpf.Instruction {
if isSrc {
if direction == crdv1alpha1.CaptureDirectionDestinationToSource {
return bpf.JumpIf{Cond: bpf.JumpEqual, Val: dstAddrVal, SkipTrue: skipTrue, SkipFalse: skipFalse}
} else {
return bpf.JumpIf{Cond: bpf.JumpEqual, Val: srcAddrVal, SkipTrue: skipTrue, SkipFalse: skipFalse}
}
} else {
if direction == crdv1alpha1.CaptureDirectionDestinationToSource {
return bpf.JumpIf{Cond: bpf.JumpEqual, Val: srcAddrVal, SkipTrue: skipTrue, SkipFalse: skipFalse}
} else {
return bpf.JumpIf{Cond: bpf.JumpEqual, Val: dstAddrVal, SkipTrue: skipTrue, SkipFalse: skipFalse}
}
}
}
Similarly a function comparePort
builds instruction for comparing port
Additional functions to calculate number of SkipTrue
and SkipFalse
instructions dynamically
Let me know if this looks better or if you have any suggestions for further improvements.
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.
could we add an e2e test with the Both
direction?
Signed-off-by: Aryan Bakliwal <[email protected]>
7b17816
to
7eb34de
Compare
@antoninbas @hangyan I have refactored the |
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.
thanks for your ongoing work on this
transPort := packet.TransportHeader | ||
if transPort.TCP != nil { | ||
// load Fragment Offset | ||
count += 3 | ||
if transPort.TCP.SrcPort != nil { | ||
count += 2 | ||
} | ||
if transPort.TCP.DstPort != nil { | ||
count += 2 | ||
} | ||
|
||
} else if transPort.UDP != nil { | ||
count += 3 | ||
if transPort.UDP.SrcPort != nil { | ||
count += 2 | ||
} | ||
if transPort.UDP.DstPort != nil { | ||
count += 2 | ||
} | ||
} |
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.
correct me if I'm wrong but this code looks like a perfect duplicate of the code above
you could do something like this:
transport := packet.TransportHeader
portFiltersSize := func() int {
count := 0
if transport.TCP != nil {
// load Fragment Offset
count += 3
if transport.TCP.SrcPort != nil {
count += 2
}
if transport.TCP.DstPort != nil {
count += 2
}
} else if transport.UDP != nil {
count += 3
if transport.UDP.SrcPort != nil {
count += 2
}
if transport.UDP.DstPort != nil {
count += 2
}
}
return count
}
Note that I have changed the spelling of transPort
to transport
, as the current version makes no sense.
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.
You're correct, it is indeed a copy. I'll replace it with this function to remove duplication.
Thanks for sharing this.
@@ -214,6 +332,31 @@ func calculateInstructionsSize(packet *crdv1alpha1.Packet) int { | |||
// src and dst ip | |||
count += 4 | |||
|
|||
if direction == crdv1alpha1.CaptureDirectionBoth { | |||
count += 3 |
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 you add a comment for this one?
based on your function comment, in the Both
direction case, we have to repeat the source host and destination host filters. Is that what this is for? This seems "small" to me, as I see the following above:
// src and dst ip
count += 4
but I assume you validated it in your unit tests
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, this is for the IP check instructions. We only need 3 more in the Both
case because the source IP address is already loaded and
// (004) ld [26] # Load 4B at 26 (source address)
we jump to compare it with the destination IP address.
I will add a comment for this.
if direction == crdv1alpha1.CaptureDirectionBoth { | ||
count += 3 | ||
|
||
transPort := packet.TransportHeader |
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 notice that you are not checking for packet != nil
here, which doesn't match the above code?
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.
Thanks for pointing this out, I overlooked it. Will add this check.
if srcIP != nil { | ||
inst = append(inst, loadIPv4SourceAddress) | ||
// from here we need to check the inst length to calculate skipFalse. If no protocol is set, there will be no related bpf instructions. | ||
inst = append(inst, compareIP(direction, 0, calculateSkipFalse(size, uint8(len(inst)), srcPort, dstPort, direction), true, srcAddrVal, dstAddrVal)) | ||
} | ||
// dst ip | ||
if dstIP != nil { |
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 code above assumes that srcIP
and dstIP
are never nil. There was a discussion about it, which was marked as resolved. We should be consistent. If this is a precondition for the function, then we should not include these nil checks.
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.
You're right, I will remove these nil checks.
@@ -72,11 +72,67 @@ func compareProtocol(protocol uint32, skipTrue, skipFalse uint8) bpf.Instruction | |||
return bpf.JumpIf{Cond: bpf.JumpEqual, Val: protocol, SkipTrue: skipTrue, SkipFalse: skipFalse} | |||
} | |||
|
|||
func calculateSkipTrue(size, instlen uint8, direction crdv1alpha1.CaptureDirection, srcPort, dstPort uint16, isSrc bool) uint8 { |
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 way these helper functions are written doesn't make a lot of sense to me. The functions have a generic name, yet they have very specialized implementation that is dependent on a bunch of parameters. To me, the fact that direction
is a parameter to this function is a bit of a red flag.
overall, I would expect the implementation to be more streamlined. There should be a helper function to generate IP + port matching. We can call the function for the SourceToDestination
direction. We can also call the function for the DestinationToSource
direction by swapping src / dst function parameters. For the Both
direction, the function should just be called twice, and the caller should add the glue to make it work (or
operator). Am I missing something? Does it have to be much more complex than that?
fixes: #6862
Added
bidirectional
field in packet capture CR spec.For testing, I created two pods and pinged one from the other.
Screenshot of the
.pcapng
output file.