The content of this page is still work in progress

P4 is a domain-specific language designed to allow programming of protocol-independent packet processors. Behavioral Model v2 (BMv2) is the reference P4 software switch. Initial support for this type of device has been included into ONOS 1.6 (Goldeneye) with 2 goals: i) provide the research community with a platform to experiment with P4-based applications and ii) define a common groundwork to support programmable data planes in the next versions of ONOS.

This document will guide you through the necessary steps to program a network of BMv2 (virtual) devices using ONOS. This document assumes you are already familiar with ONOS, P4 and BMv2. In other words, we assume you already know how to build and run ONOS, write a P4 program, build and run BMv2.

Contributors

AuthorOrganizationRoleEmail
Carmelo CasconeON.LabDevelopercarmelo@onlab.us

 


Features at a glance

By using ONOS 1.6, you'll be able to program a network of BMv2 devices with all the benefits of a logically centralized SDN platform. The following features are currently supported:

Overview

The figure below sketches the high-level architecture of the BMv2 integration in ONOS (click to zoom).

BMv2 integration in ONOS

On the northbound, ONOS provides a new Java API called "BMv2 Device Context Service" that can be used by applications to specify at runtime the JSON configuration of a given BMv2 device. Match-action tables can be populated using existing northbound APIs such as flow rule, flow objective or intents, with native support for non-standard P4 match and actions (via extension selectors and treatments).

On the southbound, ONOS speaks with BMv2 using Thrift. This project has been based on a customized version of the BMv2 “simple_switch” target that, differently from the original one, supports primitives to send packet-in events to the controller and to receive and transmit packet-outs. The source code of onos-bmv2 is available here.

BMv2 device context

In order to enforce a given JSON configuration on a device, applications need to provide a “BMv2 Device Context”. Device contexts are used to bind together in a Java class a BMv2 JSON configuration and an “Interpreter” implementation. Interpreters are used by ONOS to “understand” a given P4 program. They provide a mapping between ONOS objects and program-specific P4 objects (e.g. headers, actions, table names, etc.), allowing existing services and apps (e.g. host tracking, LLDP discovery, ARP proxy, reactive forwarding, etc.) to work with virtually any P4 program.

Interpreter

The Interpreter interface defines 3 types of mapping:

  1. ONOS table ID ↔ P4 table name

  2. Criterion's type ↔ P4 header instance’s field name

  3. Flow rule's treatment instance → BMv2 action instance

While for criteria and tables it is possible to specify a 1-to-1 relationship through a map, for Instructions the same is not possible or at least it's not convenient. The reason is that Instructions in ONOS are modeled after OpenFlow actions (which are protocol-dependent), while flow rule treatments (to be applied as a consequence of a match) are usually defined as a list of multiple instructions. In P4 instead, actions are defined as a compound of low-level protocol-independent primitives (not expressible using ONOS Instructions), and, most important, P4 allows to specify only one action per table entry. Extracting the "meaning" of a given treatment instance and mapping it to a P4 action is not straightforward and it's usually program-specific. That’s why we expect a P4 programmer using ONOS to write its own interpretation logic (i.e. Java code) that can map a given treatment instance to a BMv2 action instance.

"Default" context

When devices connect for the first time to ONOS a “default” context is automatically applied, triggering a device configuration swap and exposing to the system a default interpreter. Such a context is used to provide a minimum set of data plane capabilities for basic ONOS services and apps to work. The default context is based on a default.json BMv2 configuration, (compiled from default.p4) and a default interpreter implementation.

FAQ regarding interpreters

Non-standard match and actions

BMv2 extension selectors and treatments can be used to express flow rules with match fields or actions for which either a mapping is not provided by the interpreter, or for which such a mapping is not possible using standard ONOS types. The following code example shows how to create a flow rule that uses these extensions. Header fields and actions can be referenced using the same name used in the P4 program, while the BMv2 configuration is needed by the extension builder to properly format the values according to the specific P4 program (e.g. generate the appropriate byte representation of a given match field).

ApplicationId myAppId = ...;
DeviceId myDeviceId = ...;
Bmv2DeviceContext myContext = ...;

Bmv2Configuration myConfiguration = myContext.configuration();

Ip4Prefix dstPrefix = Ip4Prefix.valueOf("192.16.184.0/24");

ExtensionSelector extSelector = Bmv2ExtensionSelector.builder()
        .forConfiguration(myConfiguration)
        .matchExact("standard_metadata", "ingress_port", 10)
        .matchLpm("ipv4", "dstAddr", dstPrefix.address().toOctets(), dstPrefix.prefixLength())
        .build();

ExtensionTreatment extTreatment = Bmv2ExtensionTreatment.builder()
        .forConfiguration(myConfiguration)
        .setActionName("next_hop")
        .addParameter("nhop_id", 4)
        .build();

FlowRule rule = DefaultFlowRule.builder()
        .forDevice(myDeviceId)
        .fromApp(myAppId)
        .forTable(0)
        .withSelector(DefaultTrafficSelector.builder()
                              .extension(extSelector, myDeviceId)
                              .build())
        .withTreatment(DefaultTrafficTreatment.builder()
                               .extension(extTreatment, myDeviceId)
                               .build())
        .build();

 

Developers guide

ONOS+P4 development environment

To make it easy for you to get started, we prepared a repository with all you need to build and run a Mininet network of BMv2 devices that connect to ONOS. It includes:

Follow the instructions at this link to get started:

 

To get the most from the tools and instructions discussed in the following sections,  it is highly recommended that you add this line to your shell configuration profile (.bash_aliases.profile, etc.):

source /<path>/<to>/onos-p4-dev/tools/bash_profile

Walkthrough

This walkthrough demonstrates the necessary steps to run a network of BMv2 devices in Mininet, connected to ONOS.

  1. First you need to build and run ONOS. The developer guide and this how-to screencast is a good starting point to build and run ONOS locally on your development machine. 

    Important! We are transitioning our build system from Maven to BUCK. Most of ONOS 1.6 modules can be build using BUCK expect for the bmv2 modules which are built using Maven. Be sure to build ONOS using the command:

     

bmv2.py Mininet script

BMv2 Device Context Service API

Known issues (WIP)

Future work (WIP)