-
Notifications
You must be signed in to change notification settings - Fork 16
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
Header processing is too simplified for IPv6 #15
Comments
I am unsure how fragments are handled. I don't think it's a problem since only the first packet of every connection is handled. |
do you want to take it Lars? |
Yes. I would like to learn howto make bit manipulations in go (I have done it in C). The difficult thing is to check for too-short packets in every step. /assign |
yeah, I can see in multiple repos they initialize this value to
just the first X bits because is very useful for debugging , special for DNS or plain protocols
|
No, your optimization is correct. It should be 1280 if you only want headers. There is no need to copy 9000 byte jumbo frames in full to user-space. Beside performance, there is a much larger risk of filling the netlink socket buffer. |
@aojea I have looked at https://pkg.go.dev/github.com/google/gopacket, and thinking of investigate if it can be used in I see an opportunity to unit-test packet-parsing with actual real packet in pcap format (I did that in nfqloadbalancer). It is a very tedious work to manufacture packets by hand. |
gopacket brings a lot of dependencies and increase the size of the binaries cilium/cilium#25980 , |
Ok. It is probably possible to use pcap-captured packets for unit-test anyway. |
I don't know if is possible to play with build tags, @BenTheElder is the expert on that |
If you only use it in It will still be part of the dependency graph for the module. Another option is to have a module used only at test time that isolates these tests, but then it can only test public APIs.
To me it sounds like we could grab some some real packets and stick that data in a test file statically? You could also use gopacket to generate fake packets statically in an isolated tools module? |
Sounds like good options. All that's needed in _test are the byte[] data |
There is a use-case that makes this a kind/bug: If an IPv6-UDP packet is fragmented it will have a fragment extension header before the UDP header. When unknown protocols are allowed (#49), then a fragmented IPV6-UDP packets will never be subject to network policies. There should be an e2e test with fragmented UDP packets (which would fail for now) /kind bug |
I wrote a simple program to convert pcap files to [][]byte slices. It's trivial (~60loc), but I don't know where to put it. Example use:
pcap2go.gopackage main
import (
"flag"
"fmt"
"os"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func main() {
variable := flag.String("variable", "pcap_packets", "Name of the variable")
flag.Parse()
if flag.NArg() < 1 {
fmt.Println(`
pcap2go [options] <file>
Read a pcap-file and emit packets declared as go []byte
slices. Intended for including captured packets in unit tests.
`)
flag.PrintDefaults()
return
}
if err := readFile(flag.Arg(0), *variable); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func readFile(file, variable string) error {
handle, err := pcap.OpenOffline(file)
if err != nil {
return err
}
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
fmt.Printf("var %s = [][]byte{\n", variable)
for packet := range packetSource.Packets() {
fmt.Printf("\t[]byte{\n")
printBytes(packet.Data())
fmt.Printf("\t},\n")
}
fmt.Printf("}\n")
return nil
}
func printBytes(b []byte) {
for i := 0; i < len(b); i++ {
if (i % 16) == 0 {
fmt.Printf("\t\t")
}
if (i % 16) == 15 {
fmt.Printf("0x%02x,\n", b[i])
} else {
fmt.Printf("0x%02x, ", b[i])
}
}
if (len(b) % 16) != 0 {
fmt.Printf("\n")
}
} |
we use the hack/tools trick for these things https://pkg.go.dev/k8s.io/kubernetes/hack/tools |
I created https://github.com/uablrek/pcap2go, but I don't intend to add it to https://pkg.go.dev/k8s.io/kubernetes/hack/tools since it's so trivial (any programmer can recreate it from scratch in less than 1h), and it's not used in kubernetes, but in kubernetes-sigs. Instead I plan to describe it in the testing/README.md file. |
Ah, miscommunication, k8s.io/kubernetes/hack/tools is just an example of a tools module, the suggestion is we could import it in a hack/tools/go.mod in this repo following the same pattern. It sounds reasonable not to for now though |
The code for extracting ports, and a pointer to the payload is too simplified:
kube-network-policies/pkg/networkpolicy/packet.go
Lines 77 to 84 in c7fc563
It assumes that there are no extension headers. This is mentioned in:
kube-network-policies/pkg/networkpolicy/packet.go
Line 57 in c7fc563
But should be documented, as it is a serious limitation. It must eventually be addressed, and then the copied packet length in:
kube-network-policies/pkg/networkpolicy/controller.go
Line 231 in c7fc563
must be raised to 1280 (all extension headers must fit into a minimum sized IPv6 packet).
The text was updated successfully, but these errors were encountered: