Table Of Contents
Table Of Contents

PCAP Recording

Goals

INET has support for recording PCAP traces from simulations. The recording process produces PCAP files that are similar to real world PCAP traces, so one can use the same tools and techniques for analyzing simulated traffic as used on real traffic, such as Wireshark and TCPDump. Knowledge of PCAP can be reused in the context of simulations.

This showcase contains an example simulation, which generates and records PCAP traces of TCP, UDP, and ICMP traffic, using various physical layer protocols like ethernet and 802.11.

INET version: 4.0

Source files location: inet/showcases/general/pcaprecording

The model

In order to record PCAP traces in a node, a PcapRecorder module needs to be included in it. Pcap recorder modules can be easily included in hosts and routers by specifying their numPcapRecorders parameter (available in modules that extend LinkLayerNodeBase, such as StandardHost and derivatives, and router modules.)

The PCAP recorder module records packets sent to and from modules that are in the same host as the PCAP recorder module. By default, it records L2 (link layer) frames (frames going in and out of the L2 layer.) It can also be set to record L3 frames. It writes traces in a PCAP file, which has to be specified by the pcapFile parameter. This parameter acts as the main switch for recording, thus specifying this parameter enables packet capture. The PCAP recorder writes traces in the original PCAP format, not the next generation one (PcapNg.) There can be packets with only one link layer header type in the PCAP file (this is a limitation of the original PCAP file format.) The PCAP file’s link layer header type needs to be set with the pcapNetwork parameter, so PCAP programs interpret the traces correctly. Some widely used type codes are the following:

  • ethernet: 1
  • 802.11: 105
  • ppp: 204

The complete list of link layer header type codes can be found here.

The moduleNamePatterns parameter specifies which modules’ traffic should be recorded. It takes a space separated list of module names. For selecting a module vector, [*] can be used. The recorded modules are on the same level in the hierarchy as the PCAP recorder module. The default value for the moduleNamePatterns parameter is wlan[*] eth[*] ppp[*] ext[*], so it records the most commonly present L2 interfaces. The dumpProtocols parameter is a filter, and selects which protocols to include in the capture. It matches packets which are of the specified protocol type at the level of capture, but not the protocol type of encapsulated packets. The parameter takes protocol names registered in INET (see /inet/scr/inet/common/Protocol.cc) The parameter’s default value is "ethernetmac ppp ieee80211mac".

By default the PCAP recorder module records L2 frames, but setting the moduleNamePatterns to ipv4, for example, lets one record L3 frames (note that the parameter’s value is lowercase, because it refers to the actual ipv4 module in the host, not the module type.) In order to record IP frames, the pcapNetwork parameter also needs to be set to the proper link layer header type (101 - raw IP), and the dumpProtocols parameter to ipv4 (see the configuration section below.)

When a node connects to the network via just one kind of interface, specifying the link layer header type is sufficient for capturing a proper trace. However, if there are multiple kinds of interfaces the node connects with, the set of captured interfaces or physical layer protocols should be narrowed to the ones with the link layer header type specified by the pcapNetwork parameter. It is needed because traffic for all interfaces are included in the trace by default. Multiple PCAP recorder modules need to be included in the network to record packets with different link layer headers. One PCAP recorder module should only record traces with one link layer header type, because the packets with the other header types would not be recognized by PCAP programs.

Additionally, there are two packet filtering parameters. The packetFilter parameter can filter for the packet class and its properties, most commonly the packet’s name. The packetDataFilter parameter can filter for the packet’s contents, i.e. the contained chunks. Specifically, it can filter for class names of protocol headers, and their fields. The expression given as the parameter’s value is evaluated for all chuncks, and the set of recorded packets are narrowed to the ones that match the expression. The default value of both parameters is *, thus no packets are filtered. See the following sections for examples.

To summerize: the moduleNamePatterns parameter specifies which modules’ outputs should be captured. The pcapNetwork parameter sets the link layer header type according to the captured module outputs, so PCAP programs can interpret the PCAP file correctly. The dumpProtocols parameter can narrow the set of recorded protocols at the level of capture. The packetFilter and packetDataFilter parameters can further narrow the set of captured packets.

The configuration

The example simulation for this showcase contains wired and wireless hosts, and routers. The hosts are configured to generate TCP, UDP and ICMP traffic. The hosts connect to routers via ethernet, the connection between the routers is ppp. The wireless hosts communicate via 802.11. The simulation can be run by choosing the PcapRecording configuration from the ini file. The simulation uses the following network:

../../../../_images/network2.png

The network contains two adhocHosts named host1 and host2, and two StandardHosts named ethHost1 and ethHost2. There are two Router modules (router1 and router2), which are connected to each other by ppp. Each wired host is connected to one of the routers via ethernet. The network also contains an Ipv4NetworkConfigurator, an Ieee80211ScalarRadioMedium, and an IntegratedMultiVisualizer module.

Traffic generation is set up the following way: host1 is configured to send a UDP stream to host2 (via 802.11), ethHost1 is configured to open a TCP connection to ethHost2, and send a 1Mbyte file (via ethernet). Additionally, ethHost1 is configured to ping ethHost2.

We set up multiple PCAP recorder modules in various hosts in the network:

In host1, we’ll record 802.11 traffic on the wlan0 interface. We configure host1’s PCAP recorder to use the 802.11 link layer headers:

*.host1.numPcapRecorders = 1
*.host1.pcapRecorder[*].pcapNetwork = 105		# 802.11
*.host1.pcapRecorder[*].pcapFile = "results/host1.pcap"

In host2, we’ll record only the ARP packets from the 802.11 traffic on wlan0. The link layer header type is set to 802.11, and the packetDataFilter is set to record only to packets of ArpPacket class:

*.host2.numPcapRecorders = 1
*.host2.pcapRecorder[*].pcapNetwork = 105		# 802.11
*.host2.pcapRecorder[*].pcapFile = "results/host2.arp.pcap"
*.host2.pcapRecorder[*].packetDataFilter = "*ArpPacket"

The packetDataFilter parameter’s value *ArpPacket matches the inet::ArpPacket class. There is an ARP request packet open in the packet inspector on the following image:

../../../../_images/arppacketclass.png

In ethHost1, we’ll record ethernet traffic on the eth0 interface. We set the link layer header type to ethernet:

*.ethHost1.numPcapRecorders = 1
*.ethHost1.pcapRecorder[*].pcapNetwork = 1		# ethernet
*.ethHost1.pcapRecorder[*].pcapFile = "results/ethHost1.pcap"

There are two PCAP recorder modules in router1, with one of them recording ethernet traffic on eth0 and the other ppp traffic on ppp0. The moduleNamePatters parameter needs to be set for both PCAP recorder modules, because router1 has two interfaces.

*.router1.numPcapRecorders = 2
*.router1.pcapRecorder[0].pcapNetwork = 204		# ppp
*.router1.pcapRecorder[0].moduleNamePatterns = "ppp[*]"
*.router1.pcapRecorder[0].pcapFile = "results/router1.ppp.pcap"
*.router1.pcapRecorder[1].pcapNetwork = 1		# ethernet
*.router1.pcapRecorder[1].pcapFile = "results/router1.eth.pcap"
*.router1.pcapRecorder[1].moduleNamePatterns = "eth[*]"

In router2, we’ll record only packets carrying TCP data on the eth0 interface. router2 has two interfaces, so the moduleNamePatters parameter needs to be set. The link layer header type is set to ethernet, and the packet data filter is set to match packets containing an Ipv4Header, and where the totalLengthField field’s value is 576 (the size of TCP data packets with IP encapsulation):

*.router2.numPcapRecorders = 1
*.router2.pcapRecorder[*].pcapNetwork = 1		# ethernet
*.router2.pcapRecorder[*].moduleNamePatterns = "eth[*]"
*.router2.pcapRecorder[*].pcapFile = "results/router2.tcpdata.pcap"
*.router2.pcapRecorder[*].packetDataFilter = "*Ipv4Header and totalLengthField(576*)"

In ethHost2, we’ll record traffic of the ipv4 module. The dumpProtocols parameter’s default is ethernetmac ppp ieee80211mac, so it has to be set to ipv4.

*.ethHost2.numPcapRecorders = 1
*.ethHost2.pcapRecorder[*].pcapNetwork = 101	# raw IP
*.ethHost2.pcapRecorder[*].pcapFile = "results/ethHost2.ip.pcap"
*.ethHost2.pcapRecorder[*].moduleNamePatterns = "ipv4"
*.ethHost2.pcapRecorder[*].dumpProtocols = "ipv4"

By default, modules like Ipv4 and EthernetInterface don’t compute CRC and FCS frames, but assumes they are correct (“declared correct” mode.) In order to include the CRC and FCS values in the capture file, L2 and L3 modules need to be set to compute CRC and FCS:

**.crcMode = "computed"
**.fcsMode = "computed"

Note that these settings are required, otherwise an error is returned.

The alwaysFlush parameter controls whether to write packets to the pcap file as they are recorded, or after the simulation has concluded. It is false by default, but it’s set to true in all PCAP recorders to make sure there are recorded packets even if the simulation crashes:

**.pcapRecorder[*].alwaysFlush = true

Results

The following video shows the traffic in the network:

The following images show the same packets viewed in Qtenv’s packet mode inspector panel and in the PCAP trace opened with Wireshark. Both display the same data about the same packet (with the same data, sequence number, crc, etc. Click to zoom.)

TCP data, in ethHost1 (sent from ethHost1 to ethHost2):

../../../../_images/ethHost9.png

Ping request, in router1’s eth interface (sent from ethHost1 to router1):

../../../../_images/routerEth2_2.png

TCP ACK, in router1’s ppp interface (sent from ethHost1 to ethHost2):

../../../../_images/routerPPP3.png

UDP data packet, in host1’s wlan interface (sent from host1 to host2):

../../../../_images/wifi5.png

The following screenshot shows ethHost1.pcap opened with TCPDump:

../../../../_images/tcpdump.png

TCP data packet, in ethHost2, recorded at the IPv4 module (sent from ethHost1 to ethHost2):

../../../../_images/rawip.png

The following images are the PCAP traces from host2 and router2, where the set of recorded packets were narrowed with packetDataFilter.

The ARP packets from host2:

../../../../_images/arp.png

The TCP data packets from router2:

../../../../_images/tcpdata.png

Discussion

Use this page in the GitHub issue tracker for commenting on this showcase.