Giter VIP home page Giter VIP logo

p4-traffictool's Introduction

p4-traffictool

p4-traffictool helps in packet generation and parsing (dissection) for custom packet formats specified in P4. Specifically, it generates "plugin code" for Wireshark (Tshark), Scapy, MoonGen, and PcapPlusPlus such that these target tools can now support custom packet formats.

Currently, p4-traffictool expects the input P4 source code to be written for the bmv2 simple_switch target. For P4 source code written for other targets, you need to extract your headers and parser definition and modify it to fit in the v1model template available at /usr/share/p4-traffictool/templates/template.p4 (after installation).

Ongoing: We are currently working on enabling p4-traffictool to directly accept P4 source code written for any target.

Limitations

The target tools for which p4-traffictool generates plugin code do not support all possible P4 packet specifications e.g. Wireshark does not support parser transitions based on multiple header field values. p4-traffictool is therefore inherently limited by the kind of packet formats supported by the target tools.

Publication

p4-traffictool was presented as a poster at ACM SOSR 2019: Poster Extended Abstract (BibTeX entry)

Installation

Dependencies

p4-traffictool requires the open-source p4c compiler installed and accessible by running the p4c command on bash shell. Other required dependencies are python3 and the python3-tabulate library.

Building from source

After installing the dependencies, clone this repository and run ./install.sh.

PPAs for Ubuntu 16.04 and 18.04

p4-traffictool PPAs are available for Ubuntu 16.04 and 18.04:

sudo add-apt-repository ppa:pro-panda/p4-traffictool
sudo apt-get update
sudo apt install p4-traffictool

Usage

# With P4 program as the input.
p4-traffictool -p4 <path to p4 source> [OPTIONS] <target tool(s)>

# With bmv2 json as the input.
p4-traffictool -json <path to json HLIR description> [OPTIONS] <target tool(s)>

<target tool(s)>
--scapy --wireshark --moongen --pcpp --all

[OPTIONS]
--std {p4-14|p4-16} : The P4 standard to use. Default is p4-16.
-o <output dir>     : Output directory path. Default is the same as the P4/json input file.
--debug             : Shows debugging information.

# For help
p4-traffictool --help

Using the generated plugin code

The plugin code is generated in a target tool specific sub-directory within the output directory. For steps on using the plugin code, please refer to the tool-specific usage below: Wireshark (Tshark), Scapy, MoonGen, PcapPlusPlus.

Standard headers

If standard headers for Ethernet, IPv4, IPv6, TCP, and UDP are detected, the user will be prompted to choose between using the built-in header implementations provided by the tools (except Wireshark) or generating new implementations for them.

Variable Length Fields

There is limited support for variable length fields with Scapy, PcapPlusPlus and Wireshark. p4-traffictool prompts the user to enter the maximum length of a variable length field when it detects one. This length should be a multiple of 8 to ensure that the header is byte aligned. A fixed length field would be produced for the current run of p4-traffictool for Scapy, PcapPlusPlus and Wireshark Lua dissector. In order to modify this length, the user needs to rerun p4-traffictool.

Wireshark (Tshark) Lua Dissector

Usage

To open Wireshark with the generated plugin code imported into it:

wireshark -X lua_script:init.lua 

Note: init.lua is generated by p4-traffictool in the sub-directory "wireshark" within the output directory.

To extract field values from the packets captured in a pcap file using tshark with the custom plugin code enabled:

tshark -X lua_script:init.lua -r captured_packets.pcap -Tfields -e <field_name>

Wireshark-specific Notes

  • p4-traffictool expects that the user will be using Ethernet as the base layer and any modifications to the network stack shall be present on top of it.
  • As of now, p4-traffictool does not support using Wireshark's built-in implementation of standard headers.

Scapy

Scapy is a powerful Python-based interactive packet manipulation program and library.

Usage

  1. In your Python code that uses Scapy, import the generated Python file using

    from <filename> import *
    
  2. Then, you can generate packets using standard Scapy syntax. For example, if you want to generate a packet with custom P4-defined layers foo and bar with payload "foobar" , then:

    a = Foo()/Bar()/"foobar"
    

    will generate the required packet.

Scapy-specific Notes

  • Post build fields like length and checksums need to be defined by the user himself/herself in the post build method.
  • Fields are automatically mapped to XBit, XByte, XShort, XInt, etc. User can modify them if desired.

MoonGen

MoonGen is a Lua-based high-speed packet generator/sniffer that runs on top of DPDK.

Usage

  1. Copy the file templates/bitfields_def.lua to the directory MoonGen/libmoon/lua/. This is just a one-time requirement. This file contains struct definitions for 24, 40 and 48 bits fields.

  2. Copy the newly generated protocol files (Lua files) to MoonGen/libmoon/lua/proto/

  3. If you used any default (built-in) headers then add the corresponding next layer headers to the resolveNextHeader function of the default header.

    • Let's say you have added the protocol foo on top of the standard UDP layer. Then you need to modify MoonGen/libmoon/lua/proto/udp.lua so that foo gets recognized while parsing the UDP packet. Search for the function resolveNextHeader in the file udp.lua. Over there you will find a map mapNamePort. Add the pair foo = udp.PORT_FOO to the map. Here, udp.PORT_FOO is a constant defined in the same file (udp.lua).
  4. In the file MoonGen/libmoon/lua/packet.lua, register the packet header combinations using the createStack function.

    • Say you have defined the layer foo over UDP. Then inside the file packet.lua you need to define a getFooPacket function to generate a packet of the foo protocol:

      pkt.getFooPacket = createStack("eth","ip4","udp","FOO")
  5. Additional changes in MoonGen/libmoon/lua/packet.lua may also be required:

    • if the header has a length field that depends on the next layer's length, then adapt the function packetSetLength
    • if the packet has a checksum, adapt createStack (the loop at end of function createStack) and packetCalculateChecksums
  6. Add your protocol to MoonGen/libmoon/lua/proto/proto.lua so that it gets loaded :

    proto.<protocol name> = require "proto.<file containing protocol without the .lua extension>"
    • For example, the foo protocol could be added as following:

      proto.foo = require "proto.foo"
  7. Now you can run any of the examples (or otherwise scripts) in MoonGen by using the function get<ProtoName>Packet() instead of the usual getUdpPacket().

    • For example, to get a packet of the protocol foo, use getFooPacket() which was defined in step #3 above.

MoonGen-specific Notes

  • Post build fields like length and checksums need to be calculated in the setter function by the user.
  • Field lengths which are not amongst {8, 16, 24, 32, 40, 48, 64} shall be promoted to the next higher power of 2. If the user needs a field to be strictly of a particular size other than these then a proper struct needs to be defined and corresponding ntoh and hton functions need to be defined.

PcapPlusPlus

PcapPlusPlus is a multi-platform C++ network sniffing and packet parsing/crafting framework for popular packet processing engines such as libpcap, WinPcap, Npcap, DPDK and PF_RING.

Usage

  1. Copy the files uint24_t.h,uint40_t.h and uint48_t.h from /usr/share/p4-traffictool/templates/ to Packet++/header inside your PcapPlusPlus source tree. This is just a one-time requirement. These files contain definitions for 24, 40 and 48 bit data types.

  2. Copy the header (.h) files of custom P4-defined protocol(s) to Packet++/header directory and the C++ (.cpp) files to Packet++/source directory inside your PcapPlusPlus source tree.

  3. If you have used any standard PcapPlusPlus headers (e.g. Ethernet, IPv4, etc.) and if any of the new custom headers are the "next" layers, then add the new custom headers to the parseNextLayer function of the standard header.

    • For example, if a new custom header foo appears after the Ethernet layer and is identified by etherType 0x123, then add a new switch case inside the function EthLayer::parseNextLayer() in Packet++/src/EthLayer.cpp.
  4. Add the newly generated protocol(s) to the enum ProtocolType inside Packet++/header/ProtocolType.h. The enum ProtocolType specifies a separate bit for each protocol. So if the already defined last protocol in the enum ProtocolType has value 0x20000000, then to add a newly generated protocol foo, add P4_FOO = 0x40000000 to the enum.

  5. Now recompile PcapPlusPlus and also install it (if you are accessing it from a central location):

make clean
make all [-j4]
sudo make install
  1. For using the new P4-defined layers in your PcapPlusPlus application, simply include the header (.h) files of the required layer(s) in your C++ program and call the constructor, getters, setters, etc. in the usual way of using PcapPlusPlus.

PcapPlusPlus-specific Notes

  • Post build fields like length and checksums need to be calculated in the setter function by the user.
  • Field lengths which are not amongst {8, 16, 32, 64} shall be promoted to the next higher power of 2. If the user needs a field to be strictly of a particular size other than these, then a proper struct needs to be defined and corresponding ntoh and hton functions need to be provided.

Similar Tools

p4pktgen is closely related to p4-traffictool. However, p4pktgen is focused on testing all possible packet header combinations, whereas p4-traffictool provides auto-generated plugin code for popular traffic generation and parsing tools.

P4 Wireshark Dissector also generates a Wireshark (Tshark) Lua dissector plugin for a given P4 program. However, a custom P4-defined layer can only be the last layer in the protocol stack. For example, if "foo" and "bar" are custom layers, then using P4 Wireshark Dissector, you would be able to parse a packet of format Ethernet/IP/UDP/foo or Ethernet/IP/bar, but not of the format Ethernet/IP/UDP/foo/bar or Ethernet/bar/foo.

License

MIT License

p4-traffictool's People

Contributors

dependabot[bot] avatar djin31 avatar nishantbudhdev avatar non4-rjb avatar nonarjb avatar rajkiranjoshi avatar rhl-bthr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

p4-traffictool's Issues

Incorrect code generation for a specific parser graph

The generated Wireshark plugin code is incorrect for the perc1 header. Also, possible issues with generated Scapy code for the guess_payload_class() function of the perc1 header. The expected next hop is based on the ACK field and later on the BOS field. This is sort of a multi-field transition but not expressed so by the P4 programmer. Common programmer expectation is to base the transitions between the PERC header based only on the BOS field. The ACK field check is only for other dataplane processing purposes.

Result: Wireshark doesn't parse the packet beyond perc1 header.

Attachments in zip:

  1. perc.p4: source P4 program
  2. perc_parser.pdf: parser graph for the P4 program
  3. perc_sample.pcap: sample pcap file contain PERC packets

perc_issue.zip

Tool doesn't handle default transitions in the parser

The tool runs into errors for PcapPlusPlus and Scapy backends when the defined parser in P4 program contains a default transition to the next parser state. The type of error varies depending on how the default transition is:

  1. Default transition via a transition select block: In this case the error is TypeError: 'NoneType' object has no attribute '__getitem__'

  2. Default transition which is directly specified like transition parse_next_state: In this case the error is KeyError: u'bos'. Here the p4c compiler would merge the parser states and the said transition actually doesn't exist. This is a right thing to do from P4 perspective, but it confuses the tool.

Attached zip contains:

  1. perc-tcp-options.p4: by default it is a working P4 file. Follow comments around "BUGGY Line #โ 1" and "BUGGY Line #โ 2" to reproduce the two error respectively. Reproduce only one error at a time.
  2. graphs/ParseGraph-works.pdf: a working parser graph
  3. graphs/ParseGraph-bug_line1.pdf: parser graph corresponding to the first error.
  4. graphs/ParseGraph-bug_line2.pdf: parser graph corresponding to the second error.

perc-tcp-options.zip

Dockerization

Dockerfile is already written. Two main tasks:

  • Integrate properly with Dockerhub with automated builds
    Currently the tool appears on Dockerhub at this url. On Docker hub, the organization is sysnetlab while the machine user is sysnetlabadmin (linked to [email protected]). Also, the Github account used by Dockerhub is nussnl-docker (linked to [email protected]).

  • Figure out a way to invoke the tool from a simple single line Docker command along with the input file and options (if any). Passing arguments while instantiating a Docker container and doing volume mounting+copying is the challenge.

Correcting the use of the compiler

Currently what we are doing in the top-level bash script p4-traffictool.sh is very weird - we are invoking the backend p4c-bm2-ss first and if it fails then we are invoking the frontend p4c. Ideally speaking we do NOT need to invoke any backend for our purpose. We only need the header and parser definitions as per standard P4_16.

  • Try and use only the p4c frontend by default. No backends need to be invoked.
  • If the above works correctly, then with proper addition of an include path, the p4c frontend should be able to handle code written for any architecture (NetFPGA, Tofino). See how microP4 does it. In fact, Barefoot's proprietary compiler uses the open-source p4c compiler frontend. This should take away a lot of pain in using the tool for programs written for Barefoot Tofino and avoid workarounds like --only-headers.

Code Generation for Scapy

For the generated Scapy code, replace tabs with spaces. Scapy isn't happy when you copy-paste that code into Scapy's commandline terminal.

Extensive testing for tool's correctness

The biggest impediment in formally announcing the tool is the lack of confidence in its correctness. The tool has not been tested extensively for all the backends that it supports with a variety of P4 programs. We can find more public domain P4 programs here for testing.

Possibly also need to craft custom P4 programs to test handling of corner cases.

Better error reporting

When p4c compilation fails, do display the errors. For a small syntax error like missing a semi-colon, the user is left clueless as to what went wrong.

./install.sh does not really install

./install.sh adds an alias to p4-traffictool.sh within the (downloaded) source code.

Ideally, it should copy the source code and p4-traffictool.sh to /bin, similar to what a .deb package would do.

Website Improvements

  • Design Rehaul: The current website isn't that great looking. Look at pcapplusplus.github.io OR erpc.io for a better inspiration.
  • On both Github main page and website, the link to the poster's extended abstract should appear upfront. Can appeal modestly to cite our poster if they have benefited from the tool's use. Maybe like this?
  • Current Readme.md shows some table at the top in master, but the same is not visible in develop. So I am sure we can get rid of the same while having all the website related stuff properly organized under docs/.

p4-traffictool cannot generate scapy code

Our team try to introduce p4-traffictool into our p4 traffic test unit. However, when we try to use p4-traffictool to generate scapy code base on our p4 code, the tool says it cannot generate scapy.
image

Seems like this is an IOError in GenTrafficScapy.py, so I add traceback func in that part of code and get this
image

Looks like it try to open a temp file, but turns out some wrong happened, I think it is caused by DESTINATION variable received wrong value?

if [[ "$SCAPY" = true ]];then
temp="$OUTPUT/scapy"
echo "Running Scapy backend script"
mkdir -p $temp
python $DIR/src/GenTrafficScapy.py $JSONSOURCE $temp $DEBUG_MODE $START_WITH_ETH

DESTINATION = sys.argv[2]
if (DESTINATION[-1] != '/'):
DESTINATION += '/'

make_template(data, DESTINATION+local_name+".py")

image

Better and smarter top-level bash script

  • Support using both long options and short options. The sequence of options should be pretty flexible.
  • It should automatically detect the P4 language version (P4_14 vs P4_16). See Barefoot Academy's p4_build.sh script for ideas on this.
  • Interactive Mode: The top-level script should run the interactive mode by default and ask all missing options showing their default values. If certain options are specified by the user, it should not ask again for them, but only ask for remaining options. If the top-level script invocation specifies all options (especially the targets), then interactive mode should not be triggered.

Master and develop not in sync

master and develop have diverged in their git histories, with conflicts on merge attempts.

Since they seem to differ in docs/ at master, and more code in develop, would it be better to migrate docs/ to develop and make develop the new master

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.