d36d860dd3278230befdb64f14bbd0cd36a2c9c0
[govpp.git] / vendor / github.com / google / gopacket / examples / pcaplay / main.go
1 // Copyright 2012 Google, Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree.
6
7 // The pcaplay binary load an offline capture (pcap file) and replay
8 // it on the select interface, with an emphasis on packet timing
9 package main
10
11 import (
12         "flag"
13         "fmt"
14         "io"
15         "log"
16         "os"
17         "strings"
18         "time"
19
20         "github.com/google/gopacket"
21         "github.com/google/gopacket/examples/util"
22         "github.com/google/gopacket/pcap"
23 )
24
25 var iface = flag.String("i", "eth0", "Interface to write packets to")
26 var fname = flag.String("r", "", "Filename to read from")
27 var fast = flag.Bool("f", false, "Send each packets as fast as possible")
28
29 var lastTS time.Time
30 var lastSend time.Time
31
32 var start time.Time
33 var bytesSent int
34
35 func writePacketDelayed(handle *pcap.Handle, buf []byte, ci gopacket.CaptureInfo) {
36         if ci.CaptureLength != ci.Length {
37                 // do not write truncated packets
38                 return
39         }
40
41         intervalInCapture := ci.Timestamp.Sub(lastTS)
42         elapsedTime := time.Since(lastSend)
43
44         if (intervalInCapture > elapsedTime) && !lastSend.IsZero() {
45                 time.Sleep(intervalInCapture - elapsedTime)
46         }
47
48         lastSend = time.Now()
49         writePacket(handle, buf)
50         lastTS = ci.Timestamp
51 }
52
53 func writePacket(handle *pcap.Handle, buf []byte) error {
54         if err := handle.WritePacketData(buf); err != nil {
55                 log.Printf("Failed to send packet: %s\n", err)
56                 return err
57         }
58         return nil
59 }
60
61 func pcapInfo(filename string) (start time.Time, end time.Time, packets int, size int) {
62         handleRead, err := pcap.OpenOffline(*fname)
63         if err != nil {
64                 log.Fatal("PCAP OpenOffline error (handle to read packet):", err)
65         }
66
67         var previousTs time.Time
68         var deltaTotal time.Duration
69
70         for {
71                 data, ci, err := handleRead.ReadPacketData()
72                 if err != nil && err != io.EOF {
73                         log.Fatal(err)
74                 } else if err == io.EOF {
75                         break
76                 } else {
77
78                         if start.IsZero() {
79                                 start = ci.Timestamp
80                         }
81                         end = ci.Timestamp
82                         packets++
83                         size += len(data)
84
85                         if previousTs.IsZero() {
86                                 previousTs = ci.Timestamp
87                         } else {
88                                 deltaTotal += ci.Timestamp.Sub(previousTs)
89                                 previousTs = ci.Timestamp
90                         }
91                 }
92         }
93         sec := int(deltaTotal.Seconds())
94         if sec == 0 {
95                 sec = 1
96         }
97         fmt.Printf("Avg packet rate %d/s\n", packets/sec)
98         return start, end, packets, size
99 }
100
101 func main() {
102         defer util.Run()()
103
104         // Sanity checks
105         if *fname == "" {
106                 log.Fatal("Need a input file")
107         }
108
109         // Open PCAP file + handle potential BPF Filter
110         handleRead, err := pcap.OpenOffline(*fname)
111         if err != nil {
112                 log.Fatal("PCAP OpenOffline error (handle to read packet):", err)
113         }
114         defer handleRead.Close()
115         if len(flag.Args()) > 0 {
116                 bpffilter := strings.Join(flag.Args(), " ")
117                 fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter)
118                 if err = handleRead.SetBPFFilter(bpffilter); err != nil {
119                         log.Fatal("BPF filter error:", err)
120                 }
121         }
122         // Open up a second pcap handle for packet writes.
123         handleWrite, err := pcap.OpenLive(*iface, 65536, true, pcap.BlockForever)
124         if err != nil {
125                 log.Fatal("PCAP OpenLive error (handle to write packet):", err)
126         }
127         defer handleWrite.Close()
128
129         start = time.Now()
130         pkt := 0
131         tsStart, tsEnd, packets, size := pcapInfo(*fname)
132
133         // Loop over packets and write them
134         for {
135                 data, ci, err := handleRead.ReadPacketData()
136                 switch {
137                 case err == io.EOF:
138                         fmt.Printf("\nFinished in %s", time.Since(start))
139                         return
140                 case err != nil:
141                         log.Printf("Failed to read packet %d: %s\n", pkt, err)
142                 default:
143                         if *fast {
144                                 writePacket(handleWrite, data)
145                         } else {
146                                 writePacketDelayed(handleWrite, data, ci)
147                         }
148
149                         bytesSent += len(data)
150                         duration := time.Since(start)
151                         pkt++
152
153                         if duration > time.Second {
154                                 rate := bytesSent / int(duration.Seconds())
155                                 remainingTime := tsEnd.Sub(tsStart) - duration
156                                 fmt.Printf("\rrate %d kB/sec - sent %d/%d kB - %d/%d packets - remaining time %s",
157                                         rate/1000, bytesSent/1000, size/1000,
158                                         pkt, packets, remainingTime)
159                         }
160                 }
161         }
162
163 }