Files
weave-scope/vendor/github.com/google/gopacket/examples/pcaplay/main.go
Damien Lespiau 6bb6d4dd5a vendoring: Update gopacket to latest master
We'd like to benefit from the memory reduction from:

  https://github.com/google/gopacket/pull/377

I just ran:

  $ gvt update github.com/google/gopacket

Fixes: https://github.com/weaveworks/scope/issues/2905
2017-10-27 12:32:05 +01:00

164 lines
3.8 KiB
Go

// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.
// The pcaplay binary load an offline capture (pcap file) and replay
// it on the select interface, with an emphasis on packet timing
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"strings"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/examples/util"
"github.com/google/gopacket/pcap"
)
var iface = flag.String("i", "eth0", "Interface to write packets to")
var fname = flag.String("r", "", "Filename to read from")
var fast = flag.Bool("f", false, "Send each packets as fast as possible")
var lastTS time.Time
var lastSend time.Time
var start time.Time
var bytesSent int
func writePacketDelayed(handle *pcap.Handle, buf []byte, ci gopacket.CaptureInfo) {
if ci.CaptureLength != ci.Length {
// do not write truncated packets
return
}
intervalInCapture := ci.Timestamp.Sub(lastTS)
elapsedTime := time.Since(lastSend)
if (intervalInCapture > elapsedTime) && !lastSend.IsZero() {
time.Sleep(intervalInCapture - elapsedTime)
}
lastSend = time.Now()
writePacket(handle, buf)
lastTS = ci.Timestamp
}
func writePacket(handle *pcap.Handle, buf []byte) error {
if err := handle.WritePacketData(buf); err != nil {
log.Printf("Failed to send packet: %s\n", err)
return err
}
return nil
}
func pcapInfo(filename string) (start time.Time, end time.Time, packets int, size int) {
handleRead, err := pcap.OpenOffline(*fname)
if err != nil {
log.Fatal("PCAP OpenOffline error (handle to read packet):", err)
}
var previousTs time.Time
var deltaTotal time.Duration
for {
data, ci, err := handleRead.ReadPacketData()
if err != nil && err != io.EOF {
log.Fatal(err)
} else if err == io.EOF {
break
} else {
if start.IsZero() {
start = ci.Timestamp
}
end = ci.Timestamp
packets++
size += len(data)
if previousTs.IsZero() {
previousTs = ci.Timestamp
} else {
deltaTotal += ci.Timestamp.Sub(previousTs)
previousTs = ci.Timestamp
}
}
}
sec := int(deltaTotal.Seconds())
if sec == 0 {
sec = 1
}
fmt.Printf("Avg packet rate %d/s\n", packets/sec)
return start, end, packets, size
}
func main() {
defer util.Run()()
// Sanity checks
if *fname == "" {
log.Fatal("Need a input file")
}
// Open PCAP file + handle potential BPF Filter
handleRead, err := pcap.OpenOffline(*fname)
if err != nil {
log.Fatal("PCAP OpenOffline error (handle to read packet):", err)
}
defer handleRead.Close()
if len(flag.Args()) > 0 {
bpffilter := strings.Join(flag.Args(), " ")
fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter)
if err = handleRead.SetBPFFilter(bpffilter); err != nil {
log.Fatal("BPF filter error:", err)
}
}
// Open up a second pcap handle for packet writes.
handleWrite, err := pcap.OpenLive(*iface, 65536, true, pcap.BlockForever)
if err != nil {
log.Fatal("PCAP OpenLive error (handle to write packet):", err)
}
defer handleWrite.Close()
start = time.Now()
pkt := 0
tsStart, tsEnd, packets, size := pcapInfo(*fname)
// Loop over packets and write them
for {
data, ci, err := handleRead.ReadPacketData()
switch {
case err == io.EOF:
fmt.Printf("\nFinished in %s", time.Since(start))
return
case err != nil:
log.Printf("Failed to read packet %d: %s\n", pkt, err)
default:
if *fast {
writePacket(handleWrite, data)
} else {
writePacketDelayed(handleWrite, data, ci)
}
bytesSent += len(data)
duration := time.Since(start)
pkt++
if duration > time.Second {
rate := bytesSent / int(duration.Seconds())
remainingTime := tsEnd.Sub(tsStart) - duration
fmt.Printf("\rrate %d kB/sec - sent %d/%d kB - %d/%d packets - remaining time %s",
rate/1000, bytesSent/1000, size/1000,
pkt, packets, remainingTime)
}
}
}
}