<commit_before>= LIBOFP: OpenFlow to YAML Converter
:icons: font
:toc:
ifdef::env-github[]
:toc-placement: preamble
endif::[]

image:https://travis-ci.org/byllyfish/libofp.svg?branch=develop["Travis-CI Build Status", link="https://travis-ci.org/byllyfish/libofp"]
image:https://scan.coverity.com/projects/5587/badge.svg["Coverity Scan Build Status", link="https://scan.coverity.com/projects/5587"]

== What is Libofp?

The *libofp* program translates binary https://www.opennetworking.org/sdn-resources/openflow[OpenFlow] messages to http://www.yaml.org/spec/1.2/spec.html[YAML 1.2] and back again. It provides a uniform object syntax for working with the OpenFlow protocol programmatically.

* Supports Linux and OS X
* Supports OpenFlow versions 1.0, 1.1, 1.2, 1.3, 1.4
* Optional JSON RPC Microservice supports:
** multiple incoming or outgoing connections
** auxiliary connections
** TLS and DTLS

Libofp is a *tool* in the unix tradition. Use `netcat` in a pipe to feed OpenFlow messages to a switch or controller:

[source,console]
----
$ libofp encode input.yml | nc -w 3 10.0.0.1 6653 | libofp decode
----

Parse a .pcap file with `tcpflow` and then decode all the OpenFlow 
messages, while retaining metadata such as timestamps:

[source,bash]
----
#!/bin/bash
tcpflow -I -r saved.pcap -o "/tmp/flow_$$" 
libofp decode --use-findx "/tmp/flow_$$/*.findx"
----

Libofp includes a JSON-RPC microservice that can operate as an OpenFlow 
controller, agent, or both simultaneously. The JSON-RPC microservice can control
the OpenFlow protocol over an IPC channel using asynchronous JSON events.

[source,console]
----
$ libofp jsonrpc
----

=== YAML to OpenFlow

The following YAML input will produce an OpenFlow 1.3 message:

[source,yaml]
----
type: PACKET_OUT
version: 4    # OpenFlow 1.3
msg:
  buffer_id: NO_BUFFER
  in_port: CONTROLLER    # Use strings for special values and flags
  actions: 
    - action: OUTPUT
      port: 0x11    # YAML supports hexadecimal numbers
      max_len: MAX
  data: 'ffffffffffff0000000000010800'
----

The YAML syntax is based on OpenFlow 1.4, but the same input
can generate earlier protocol version messages. Libofp is intelligent about
translating between OpenFlows versions. For example,
here's a FlowMod message specified using OpenFlow 1.4 syntax, but which will 
output a "1.0" message because version 1 is explicitly specified.

[source,yaml]
----
  type: FLOW_MOD
  version: 1    # OpenFlow 1.0
  msg:
    cookie: 0
    cookie_mask: 0xFFFFFFFFFFFFFFFF   # Ignored; not present in OpenFlow 1.0
    table_id: 0    # Ignored; not present in OpenFlow 1.0
    command: ADD
    idle_timeout: 10
    hard_timeout: 30
    priority: 2
    buffer_id: NO_BUFFER
    out_port: ANY
    out_group: ANY
    flags: [ SEND_FLOW_REM, CHECK_OVERLAP ]   # Flags as array of strings
    match:
      - field: IN_PORT
        value: 1
      - field: IPV4_SRC     # Match field dependencies added automatically
        value: '192.168.1.1'
    instructions:
      - instruction: APPLY_ACTIONS
        actions:
          - action: OUTPUT
            port: 2
            max_len: MAX
----

=== OpenFlow to YAML

Given a binary OpenFlow message, `libofp` can translate it back to a human-readable
YAML object. Here's the binary for an OpenFlow OFPT_ERROR message in hexadecimal:

[source,hex]
----
01010013 00000062 00010001 FFFF1234 567890
----

Decoding this binary OpenFlow message yields:

[source,yaml]
----
type:            ERROR
xid:             0x00000062
version:         0x01
msg:             
  type:            OFPET_BAD_REQUEST
  code:            OFPBRC_BAD_TYPE
  data:            FFFF1234567890
----

== Installation

Before you build, you need a C++11 compiler, cmake and git. You will also need 
Python, Perl and Go.

On Ubuntu, use apt-get to install the dependencies.
[source,console]
----
$ sudo apt-get -yq update
$ sudo apt-get install build-essential cmake git golang libpcap-dev
----

On Mac OS X, you can obtain cmake from http://cmake.org/download/.

To build the software:

[source,console]
----
$ git clone --recursive https://github.com/byllyfish/libofp.git
$ mkdir libofp/Build
$ cd libofp/Build
$ cmake ..
$ make
$ make test
$ make install
----

On Ubuntu, you can also install the software from a https://launchpad.net/~byllyfish/+archive/ubuntu/libofp[Launchpad PPA].

== Examples

To translate a text file into binary OpenFlow messages:

[source,console]
----
$ libofp encode -o output.bin input.yml
----

To translate a text file into binary OpenFlow messages, while ignoring
sets of match fields with missing prerequisites:

[source,console]
----
$ libofp encode --unchecked-match -o output.bin input.yml
----

To translate a text file of compact, single line JSON objects separated by
linefeeds:

[source,console]
----
$ libofp encode --json input.json
----

To decode a file of binary OpenFlow messages to YAML:

[source,console]
----
$ libofp decode input.bin
----

To decode a file of binary OpenFlow messages to compact single-line JSON objects:

[source,console]
----
$ libofp decode --json "filename"
----

To decode binary OpenFlow messages to a valid JSON array of objects:

[source,console]
----
$ libofp decode --json-array "filename"
----

To decode binary OpenFlow messages with the additional check that the resulting<commit_msg>Mention .pcap support in readme.<commit_after>= LIBOFP: OpenFlow to YAML Converter
:icons: font
:toc:
ifdef::env-github[]
:toc-placement: preamble
endif::[]

image:https://travis-ci.org/byllyfish/libofp.svg?branch=develop["Travis-CI Build Status", link="https://travis-ci.org/byllyfish/libofp"]
image:https://scan.coverity.com/projects/5587/badge.svg["Coverity Scan Build Status", link="https://scan.coverity.com/projects/5587"]

== What is Libofp?

The *libofp* program translates binary https://www.opennetworking.org/sdn-resources/openflow[OpenFlow] messages to http://www.yaml.org/spec/1.2/spec.html[YAML 1.2] and back again. It provides a uniform object syntax for working with the OpenFlow protocol programmatically.

* Supports Linux and OS X
* Supports OpenFlow versions 1.0, 1.1, 1.2, 1.3, 1.4
* Optional JSON RPC Microservice supports:
** multiple incoming or outgoing connections
** auxiliary connections
** TLS and DTLS

Decode the OpenFlow messages in a ".pcap" file while retaining metadata such as timestamps:

[source,bash]
----
$ libofp decode "filename.pcap"
----

Libofp includes a JSON-RPC microservice that can operate as an OpenFlow 
controller, agent, or both simultaneously. The JSON-RPC microservice can control
the OpenFlow protocol over an IPC channel using asynchronous JSON events.

[source,console]
----
$ libofp jsonrpc
----

=== YAML to OpenFlow

The following YAML input will produce an OpenFlow 1.3 message:

[source,yaml]
----
type: PACKET_OUT
version: 4    # OpenFlow 1.3
msg:
  buffer_id: NO_BUFFER
  in_port: CONTROLLER    # Use strings for special values and flags
  actions: 
    - action: OUTPUT
      port: 0x11    # YAML supports hexadecimal numbers
      max_len: MAX
  data: 'ffffffffffff0000000000010800'
----

The YAML syntax is based on OpenFlow 1.4, but the same input
can generate earlier protocol version messages. Libofp is intelligent about
translating between OpenFlows versions. For example,
here's a FlowMod message specified using OpenFlow 1.4 syntax, but which will 
output a "1.0" message because version 1 is explicitly specified.

[source,yaml]
----
  type: FLOW_MOD
  version: 1    # OpenFlow 1.0
  msg:
    cookie: 0
    cookie_mask: 0xFFFFFFFFFFFFFFFF   # Ignored; not present in OpenFlow 1.0
    table_id: 0    # Ignored; not present in OpenFlow 1.0
    command: ADD
    idle_timeout: 10
    hard_timeout: 30
    priority: 2
    buffer_id: NO_BUFFER
    out_port: ANY
    out_group: ANY
    flags: [ SEND_FLOW_REM, CHECK_OVERLAP ]   # Flags as array of strings
    match:
      - field: IN_PORT
        value: 1
      - field: IPV4_SRC     # Match field dependencies added automatically
        value: '192.168.1.1'
    instructions:
      - instruction: APPLY_ACTIONS
        actions:
          - action: OUTPUT
            port: 2
            max_len: MAX
----

=== OpenFlow to YAML

Given a binary OpenFlow message, `libofp` can translate it back to a human-readable
YAML object. Here's the binary for an OpenFlow OFPT_ERROR message in hexadecimal:

[source,hex]
----
01010013 00000062 00010001 FFFF1234 567890
----

Decoding this binary OpenFlow message yields:

[source,yaml]
----
type:            ERROR
xid:             0x00000062
version:         0x01
msg:             
  type:            OFPET_BAD_REQUEST
  code:            OFPBRC_BAD_TYPE
  data:            FFFF1234567890
----

== Installation

Before you build, you need a C++11 compiler, cmake and git. You will also need 
Python, Perl and Go.

On Ubuntu, use apt-get to install the dependencies.
[source,console]
----
$ sudo apt-get -yq update
$ sudo apt-get install build-essential cmake git golang libpcap-dev
----

On Mac OS X, you can obtain cmake from http://cmake.org/download/.

To build the software:

[source,console]
----
$ git clone --recursive https://github.com/byllyfish/libofp.git
$ mkdir libofp/Build
$ cd libofp/Build
$ cmake ..
$ make
$ make test
$ make install
----

On Ubuntu, you can also install the software from a https://launchpad.net/~byllyfish/+archive/ubuntu/libofp[Launchpad PPA].

== Examples

To translate a text file into binary OpenFlow messages:

[source,console]
----
$ libofp encode -o output.bin input.yml
----

To translate a text file into binary OpenFlow messages, while ignoring
sets of match fields with missing prerequisites:

[source,console]
----
$ libofp encode --unchecked-match -o output.bin input.yml
----

To translate a text file of compact, single line JSON objects separated by
linefeeds:

[source,console]
----
$ libofp encode --json input.json
----

To decode a file of binary OpenFlow messages to YAML:

[source,console]
----
$ libofp decode input.bin
----

To decode a ".pcap" file containing OpenFlow messages, treating all TCP streams
as potential OpenFlow connections:

[source,console]
----
$ libofp decode --pcap-filter='' "input.pcap" 
----

To decode a file of binary OpenFlow messages to compact single-line JSON objects:

[source,console]
----
$ libofp decode --json "filename"
----

To decode binary OpenFlow messages to a valid JSON array of objects:

[source,console]
----
$ libofp decode --json-array "filename"
----

To decode binary OpenFlow messages with the additional check that the resulting
{'fraction_non_alphanumeric': 0.10077150204781407, 'fraction_numerical': 0.027050195256691112, 'mean_word_length': 3.2151746286631875, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 14, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 3, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4837755', 'n_tokens_mistral': 3532, 'n_tokens_neox': 3244, 'n_words': 1182}