func benchmarkPacketDecode(packetSource *gopacket.PacketSource) { count, errors := 0, 0 start := time.Now() for packet, err := packetSource.NextPacket(); err != io.EOF; packet, err = packetSource.NextPacket() { if err != nil { fmt.Println("Error reading in packet:", err) continue } count++ var hasError bool if *printErrors && packet.ErrorLayer() != nil { fmt.Println("\n\n\nError decoding packet:", packet.ErrorLayer().Error()) fmt.Println(hex.Dump(packet.Data())) fmt.Printf("%#v\n", packet.Data()) errors++ hasError = true } if *printLayers || hasError { fmt.Printf("\n=== PACKET %d ===\n", count) for _, l := range packet.Layers() { fmt.Printf("--- LAYER %v ---\n%#v\n\n", l.LayerType(), l) } fmt.Println() } } duration := time.Since(start) fmt.Printf("\tRead in %v packets in %v, %v per packet\n", count, duration, duration/time.Duration(count)) if *printErrors { fmt.Printf("%v errors, successfully decoded %.02f%%\n", errors, float64(count-errors)*100.0/float64(count)) } }
// Packet reading -------------------------------------------------------------------- func(g *GPCapture) ReadPackets(packetSource *gopacket.PacketSource) { var numConsecDecodingFailures int SysLog.Debug("Entered Read packets") for { select { case <-g.quitCaptureChan: return default: // repeatedly read the packets from the packet source, return an error string // if the packet could not be decoded if packet, packerr := packetSource.NextPacket(); packerr == nil { // safely increment packet counter atomic.AddUint64(&g.pktsRead, 1) // OSAG gopacket addition: make sure that non-standard encapsulated packets // are sliced up correctly. The original gopacket does not support GRE-en- // capsulated packets for example packet.StripHeaders(g.linkType) // pull out the flow-relevant information and write it to the flow matrix. // Block the write out thread for the time of the insertion if p, perr := g.handlePacket(packet); perr == nil { // protect critical section g.flowTab.Lock() g.flowTab.flows.addToFlow(p) g.flowTab.Unlock() numConsecDecodingFailures = 0 } else { numConsecDecodingFailures++ // shut down the interface thread if too many consecutive decoding failures // have been encountered if numConsecDecodingFailures > 10000 { SysLog.Err(g.iface+": the last 10 000 packets could not be decoded") return } } } else if packerr == pcap.NextErrorTimeoutExpired { continue } else { SysLog.Warning(g.iface+": interface capture error: " + packerr.Error()) return } } } }
func main() { flag.Parse() filename := os.TempDir() + string(os.PathSeparator) + "gopacket_benchmark.pcap" if _, err := os.Stat(filename); err != nil { // This URL points to a publicly available packet data set from a DARPA // intrusion detection evaluation. See // http://www.ll.mit.edu/mission/communications/cyber/CSTcorpora/ideval/data/1999/training/week1/index.html // for more details. fmt.Println("Local pcap file", filename, "doesn't exist, reading from", *url) if resp, err := http.Get(*url); err != nil { panic(err) } else if out, err := os.Create(filename); err != nil { panic(err) } else if gz, err := gzip.NewReader(resp.Body); err != nil { panic(err) } else if n, err := io.Copy(out, gz); err != nil { panic(err) } else if err := gz.Close(); err != nil { panic(err) } else if err := out.Close(); err != nil { panic(err) } else { fmt.Println("Successfully read", n, "bytes from url, unzipped to local storage") } } fmt.Println("Reading file once through to hopefully cache most of it") if f, err := os.Open(filename); err != nil { panic(err) } else if n, err := io.Copy(ioutil.Discard, f); err != nil { panic(err) } else if err := f.Close(); err != nil { panic(err) } else { fmt.Println("Read in file", filename, ", total of", n, "bytes") } if *cpuProfile != "" { if cpu, err := os.Create(*cpuProfile); err != nil { panic(err) } else if err := pprof.StartCPUProfile(cpu); err != nil { panic(err) } else { defer func() { pprof.StopCPUProfile() cpu.Close() }() } } var packetDataSource *BufferPacketSource var packetSource *gopacket.PacketSource fmt.Printf("Opening file %q for read\n", filename) if h, err := pcap.OpenOffline(filename); err != nil { panic(err) } else { fmt.Println("Reading all packets into memory with BufferPacketSource.") start := time.Now() packetDataSource = NewBufferPacketSource(h) duration := time.Since(start) fmt.Printf("Time to read packet data into memory from file: %v\n", duration) packetSource = gopacket.NewPacketSource(packetDataSource, h.LinkType()) packetSource.DecodeOptions.Lazy = *decodeLazy packetSource.DecodeOptions.NoCopy = *decodeNoCopy } for i := 0; i < *repeat; i++ { packetDataSource.Reset() count, errors := 0, 0 runtime.GC() fmt.Printf("Benchmarking decode %d/%d\n", i+1, *repeat) start := time.Now() for packet, err := packetSource.NextPacket(); err != io.EOF; packet, err = packetSource.NextPacket() { if err != nil { fmt.Println("Error reading in packet:", err) } count++ var hasError bool if *printErrors && packet.ErrorLayer() != nil { fmt.Println("\n\n\nError decoding packet:", packet.ErrorLayer().Error()) fmt.Println(hex.Dump(packet.Data())) fmt.Printf("%#v\n", packet.Data()) errors++ hasError = true } if *printLayers || hasError { fmt.Printf("\n=== PACKET %d ===\n", count) for _, l := range packet.Layers() { fmt.Printf("--- LAYER %v ---\n%#v\n\n", l.LayerType(), l) } fmt.Println() } } duration := time.Since(start) fmt.Printf("\tRead in %v packets in %v, %v per packet\n", count, duration, duration/time.Duration(count)) if *printErrors { fmt.Printf("%v errors, successfully decoded %.02f%%\n", errors, float64(count-errors)*100.0/float64(count)) } } }