Skip to content

Commit d727731

Browse files
authored
Merge pull request #714 from mercimat/pcap_support_in_fast_generator
Pcap support in fast generator
2 parents 308eae9 + 7905c7a commit d727731

File tree

7 files changed

+151
-0
lines changed

7 files changed

+151
-0
lines changed

examples/nffPktgen/generator/generator.go

+72
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package generator
77
import (
88
"fmt"
99
"math/rand"
10+
"os"
1011
"unsafe"
1112

1213
"github.com/intel-go/nff-go/packet"
@@ -229,6 +230,77 @@ func generateICMPIPv4(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand)
229230
pktICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4ICMPChecksum(pktIP, pktICMP, pkt.Data))
230231
}
231232

233+
func generatePcap(pkt *packet.Packet, config *PacketConfig, _ *rand.Rand) {
234+
if pkt == nil {
235+
panic("Failed to create new packet")
236+
}
237+
pcapConfig := &config.Pcap
238+
if pcapConfig.FileReader == nil {
239+
f, err := os.Open(pcapConfig.Path)
240+
if err != nil {
241+
panic(fmt.Sprintf("Failed to open pcap file %s", pcapConfig.Path))
242+
}
243+
pcapConfig.FileReader = f
244+
var glHdr packet.PcapGlobHdr
245+
if err := packet.ReadPcapGlobalHdr(f, &glHdr); err != nil {
246+
f.Close()
247+
panic(fmt.Sprintf("Failed to read pcap file header, returned %v", err))
248+
}
249+
}
250+
isEOF, err := pkt.ReadPcapOnePacket(pcapConfig.FileReader)
251+
if err != nil {
252+
panic("Failed to read one packet from pcap")
253+
}
254+
if isEOF {
255+
if _, err := pcapConfig.FileReader.Seek(packet.PcapGlobHdrSize, 0); err != nil {
256+
panic("Failed to parse pcap file header")
257+
}
258+
if _, err := pkt.ReadPcapOnePacket(pcapConfig.FileReader); err != nil {
259+
panic("Failed to read one packet from pcap")
260+
}
261+
}
262+
}
263+
264+
func generatePcapInMemory(pkt *packet.Packet, config *PacketConfig, _ *rand.Rand) {
265+
if pkt == nil {
266+
panic("Failed to create new packet")
267+
}
268+
pcapConfig := &config.Pcap
269+
if !pcapConfig.ReachedEOF {
270+
if pcapConfig.FileReader == nil {
271+
f, err := os.Open(pcapConfig.Path)
272+
if err != nil {
273+
panic(fmt.Sprintf("Failed to open pcap file %s", pcapConfig.Path))
274+
}
275+
pcapConfig.FileReader = f
276+
var glHdr packet.PcapGlobHdr
277+
if err := packet.ReadPcapGlobalHdr(f, &glHdr); err != nil {
278+
f.Close()
279+
panic(fmt.Sprintf("Failed to read pcap file header, returned %v", err))
280+
}
281+
}
282+
isEOF, err := pkt.ReadPcapOnePacket(pcapConfig.FileReader)
283+
if err != nil {
284+
panic("Failed to read one packet from pcap")
285+
}
286+
if isEOF {
287+
pcapConfig.FileReader.Close()
288+
pcapConfig.ReachedEOF = true
289+
} else {
290+
data := pkt.GetRawPacketBytes()
291+
pcapConfig.Packets = append(pcapConfig.Packets, data)
292+
}
293+
}
294+
if pcapConfig.ReachedEOF {
295+
bytes := pcapConfig.Packets[pcapConfig.NextPacket]
296+
pcapConfig.NextPacket = (pcapConfig.NextPacket + 1) % len(pcapConfig.Packets)
297+
ok := packet.GeneratePacketFromByte(pkt, bytes)
298+
if !ok {
299+
panic("Failed to generate packet from byte")
300+
}
301+
}
302+
}
303+
232304
func FillTCPHdr(pkt *packet.Packet, l4 *TCPConfig, rnd *rand.Rand) {
233305
emptyPacketTCP := (*packet.TCPHdr)(pkt.L4)
234306
emptyPacketTCP.SrcPort = packet.SwapBytesUint16(uint16(l4.SPort.Current))

examples/nffPktgen/generator/parseConfig.go

+52
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
)
1919

2020
var mixPattern = regexp.MustCompile(`^mix[0-9]*$`)
21+
var pcapPattern = regexp.MustCompile(`^.*\.pcap$`)
2122

2223
type AddrRange struct {
2324
Min uint64
@@ -57,12 +58,14 @@ const (
5758
RANDDATA
5859
RAWDATA
5960
NONE
61+
PCAP
6062
)
6163

6264
// PacketConfig configures packet
6365
type PacketConfig struct {
6466
DType DataType
6567
Ether EtherConfig
68+
Pcap PcapConfig
6669
}
6770

6871
// MixConfig contains PacketConfigs with quantity.
@@ -75,6 +78,16 @@ func (mc *MixConfig) String() string {
7578
return fmt.Sprintf("config: %v; quantity: %v\n", mc.Config, mc.Quantity)
7679
}
7780

81+
// PcapCOnfig configures pcap file
82+
type PcapConfig struct {
83+
Path string
84+
FileReader *os.File
85+
InMemory bool
86+
ReachedEOF bool
87+
Packets [][]byte
88+
NextPacket int
89+
}
90+
7891
// EtherConfig configures ether header.
7992
type EtherConfig struct {
8093
DAddr AddrRange
@@ -201,6 +214,14 @@ func ParseConfig(in map[string]interface{}) (config GeneratorConfig, err error)
201214
}
202215
pktConfig := PacketConfig{Ether: ethHdr, DType: ETHERHDR}
203216
return append(config, MixConfig{Config: pktConfig, Quantity: 1}), nil
217+
case key == "pcap":
218+
pcapConfig := v.(map[string]interface{})
219+
pcap, err := parsePcap(pcapConfig)
220+
if err != nil {
221+
return nil, fmt.Errorf("parsePcap returned: %v", err)
222+
}
223+
pktConfig := PacketConfig{Pcap: pcap, DType: PCAP}
224+
return append(config, MixConfig{Config: pktConfig, Quantity: 1}), nil
204225
case mixPattern.MatchString(key):
205226
return ParseGeneratorConfig(in)
206227
default:
@@ -230,6 +251,13 @@ func ParseGeneratorConfig(in map[string]interface{}) (config GeneratorConfig, er
230251
return nil, fmt.Errorf("parseEtherHdr returned: %v", err)
231252
}
232253
pktConfig = PacketConfig{Ether: ethHdr, DType: ETHERHDR}
254+
case "pcap":
255+
pcapConfig := vv.(map[string]interface{})
256+
pcap, err := parsePcap(pcapConfig)
257+
if err != nil {
258+
return nil, fmt.Errorf("parsePcap returned: %v", err)
259+
}
260+
pktConfig = PacketConfig{Pcap: pcap, DType: PCAP}
233261
case "quantity", "q":
234262
q = uint32(vv.(float64))
235263
default:
@@ -845,3 +873,27 @@ func parsePortRange(in map[string]interface{}) (AddrRange, error) {
845873
}
846874
return portRng, nil
847875
}
876+
877+
func parsePcap(in map[string]interface{}) (PcapConfig, error) {
878+
pcap := PcapConfig{}
879+
for k, v := range in {
880+
switch strings.ToLower(k) {
881+
case "path":
882+
path, ok := v.(string)
883+
if !ok {
884+
return PcapConfig{}, fmt.Errorf("parsePcapConfig for path returned: not a string")
885+
}
886+
if !pcapPattern.MatchString(path) {
887+
return PcapConfig{}, fmt.Errorf("parsePcapConfig for path returned: invalid pcap file")
888+
}
889+
pcap.Path = path
890+
case "inmemory":
891+
inmemory, ok := v.(bool)
892+
if !ok {
893+
return PcapConfig{}, fmt.Errorf("parsePcapConfig for inmemory returned: not a bool")
894+
}
895+
pcap.InMemory = inmemory
896+
}
897+
}
898+
return pcap, nil
899+
}

examples/nffPktgen/generator/utility.go

+6
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ func getGenerator(configuration PacketConfig) (func(*packet.Packet, *PacketConfi
8484
default:
8585
return nil, fmt.Errorf("unknown packet l3 configuration")
8686
}
87+
case PCAP:
88+
pcap := configuration.Pcap
89+
if pcap.InMemory {
90+
return generatePcapInMemory, nil
91+
}
92+
return generatePcap, nil
8793
default:
8894
return nil, fmt.Errorf("unknown packet l2 configuration")
8995
}

examples/nffPktgen/testing/mix.json

+14
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,19 @@
103103
}
104104
},
105105
"quantity": 6
106+
},
107+
"mix4": {
108+
"pcap": {
109+
"path": "./test.pcap",
110+
"inmemory": false
111+
},
112+
"quantity": 1
113+
},
114+
"mix5": {
115+
"pcap": {
116+
"path": "./test.pcap",
117+
"inmemory": true
118+
},
119+
"quantity": 1
106120
}
107121
}

examples/nffPktgen/testing/pcap.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"pcap": {
3+
"path": "./test.pcap",
4+
"inmemory": false
5+
}
6+
}

examples/nffPktgen/testing/run.sh

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616
./sendGetBack -number 100 -outConfig "'arpVlan.pcap':'arpVlan.json'"
1717
./sendGetBack -number 100 -outConfig "'config.pcap': 'config.json'"
1818
./sendGetBack -number 100 -outConfig "'mix.pcap': 'mix.json'"
19+
./sendGetBack -number 100 -outConfig "'pcap.pcap': 'pcap.json'"

examples/nffPktgen/testing/test.pcap

132 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)