Skip to content
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

Fix Issue #6976: Modified the logic to capture either source or destination traffic in PacketCapture CRD #6997

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ifrah-ashraf
Copy link

Description

This PR fixes Issue #6976 by ensuring that PacketCapture CRD properly validates source and destination separately.

  1. Updated packetcapture.yaml schema to enforce oneOf validation.
  2. Modified bpf.go to handle traffic capturing based on either source or destination.
  3. Fixed packetcapture_controller.go logic to correctly process packet captures for either source or destination.

Source Pod traffic (egressing from a pod)

Screenshot from 2025-02-14 02-25-20

Destination Pod traffic (ingressing into a pod)

Screenshot from 2025-02-14 02-25-20


Note:
For destination pod traffic (ingress), I need to further verify whether externally sent traffic is properly captured at the destination. Initial tests with locally exposed pod service indicate that ingress traffic might be translated at the gateway, making it appear as if it's coming from another internal source pod. If any modifications are required in this regard, please let me know. Otherwise, I will update the e2e test suite accordingly to validate this scenario and share my findings.

Comment on lines 69 to 77
oneOf:
- properties:
source:
required: [pod]
required: [source]
- properties:
destination:
required: [pod]
required: [destination]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that doesn't seem right to me: if I define a PacketCapture with both .spec.source.pod and .spec.destination.pod, I believe validation will fail as both alternatives in the oneOf will match

I am also not sure I understand the rationale behind the change. I think the previous requirement (with the anyOf) as fine. What we are trying to ensure is that at least one one .spec.source.pod and .spec.destination.pod is provided. If at least one of them is provided, then of course at least one of .spec.source and .spec.destination is provided.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @antoninbas, for your feedback!

I've updated the Packet Capture CRD to capture packets in the following scenarios:

  • Egress traffic – packets originating from a pod.
  • Ingress traffic – packets destined for a pod.
  • Pod-to-pod traffic – packets where at least one endpoint (source or destination) is a pod.

Let me know if any further improvements are needed!


var sourceIP, destIP net.IP
// Parse only one IP either source or destination
podIP, isSource, err := c.parseOneIP(ctx, pc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both IPs can still be provided, so returning a single IP here is incorrect

it seems to me that the existing implementation of parseIPs is correct actually, and compatible with what we are trying to achieve with this PR

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed parseOneIP and kept the previous parseIPs logic.

Additionally, I made little changes in bpf.go to ensure that the instruction count
is correctly calculated based on the Pod CRD for all types of traffic.

@ifrah-ashraf
Copy link
Author

Hey @antoninbas, thanks for the feedback!

I've made the necessary changes to ensure correct packet capture and verified
that all conditions mentioned in issue #6976 are met.

Let me know if any further improvements are needed. Otherwise, I'll test it
locally and provide an update.

required: [pod]
- properties:
destination:
required: [pod]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ifrah-ashraf
what if both src and dst is provided? Then doesn't you think then both src and dst must be pod?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @devc007 , if both (source and dest) is specified then it will work as it was working before but either of them must be a pod as to store the pcapng file one pod must be specified and yeah if both source and destination are defined then by default it will store the file at source pod.

I hope it is clear now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarification @ifrah-ashraf but i am still trying to understand the things you have pointed out. And thanks to explain me why one of them must be a pod.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I understand why we don't just have this:

              required:
                - captureConfig
              anyOf:
                - properties:
                    source:
                      required: [pod]
                - properties:
                    destination:
                      required: [pod]

wouldn't that work?

required: [pod]
- properties:
destination:
required: [pod]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I understand why we don't just have this:

              required:
                - captureConfig
              anyOf:
                - properties:
                    source:
                      required: [pod]
                - properties:
                    destination:
                      required: [pod]

wouldn't that work?

@@ -76,7 +76,16 @@ func compareProtocol(protocol uint32, skipTrue, skipFalse uint8) bpf.Instruction
// ipv4 traffic. Compared to the raw BPF filter supported by libpcap, we only need to support
// limited use cases, so an expression parser is not needed.
func compilePacketFilter(packetSpec *crdv1alpha1.Packet, srcIP, dstIP net.IP) []bpf.Instruction {
size := uint8(calculateInstructionsSize(packetSpec))
//size := uint8(calculateInstructionsSize(packetSpec))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove such commented out lines when you submit a PR for review

@@ -212,8 +221,16 @@ func calculateInstructionsSize(packet *crdv1alpha1.Packet) int {
}
}
// src and dst ip
count += 4
//count += 4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto


// generate traffic for source pod (egress)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the new comments here. What does "generate traffic" mean here?

srcIP, dstIP, err := c.parseIPs(ctx, pc)
if err != nil {
return false, err
}

/* var sourceIP, destIP net.IP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, remove all the commented out code that is not needed

@@ -447,11 +447,26 @@ func (c *Controller) performCapture(
file afero.File,
device string,
) (bool, error) {

// here is the IP parsing when both source and destination pod is specified
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a useful comment

@@ -447,11 +447,26 @@ func (c *Controller) performCapture(
file afero.File,
device string,
) (bool, error) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't add an empty line at the beginning of functions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants